From 8c938b79cb197d6c8a168f535d81d2cc449ede36 Mon Sep 17 00:00:00 2001 From: panurgomatic Date: Tue, 15 Mar 2011 15:20:02 +0000 Subject: [PATCH] This is a rather big mecha update (not everything is polished, bughunt in progress). - Mechs equipment is customizable (you can add different equipment to mechs). Weapons go to combat mechs only, clown mech equipment - to HONK only. Clamp goes only to Ripley. - Mech equipment can be built by mech fabricator. - Added mecha RCD, mecha teleporter, mecha wormhole generator equipment. - Equipment(if any left) can be pried from mecha wreckage with crowbar. - Mech control console circuitboard added to circuit storage. - Mechs can teleport from teleport hub. - Fixed ripley cargo problems with moving objects(bots, carps, huggers etc). Loading hostile organisms may be harmful. Be vigilant. - Fixed bug with many mobs climbing inside one mecha. - Fixed mecha "unable-to-move" message spam. Other things: - Rooms in random asteroids for extended and sandbox (WIP) - Misc. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@1190 316c924e-a436-60f5-8080-3fe189b3f50e --- code/defines/procs/AStar.dm | 2 + code/defines/procs/gamehelpers.dm | 26 ++ code/game/asteroid/asteroid.dm | 34 +- .../gamemodes/malfunction/Malf_Modules.dm | 2 + code/game/mecha/combat/combat.dm | 37 +- code/game/mecha/combat/durand.dm | 9 +- code/game/mecha/combat/gygax.dm | 2 + code/game/mecha/combat/honker.dm | 14 +- code/game/mecha/combat/marauder.dm | 15 +- code/game/mecha/equipment/mecha_equipment.dm | 74 ++++ code/game/mecha/equipment/tools/tools.dm | 337 +++++++++++++++ .../{combat => equipment}/weapons/weapons.dm | 397 +++++++++--------- code/game/mecha/mech_fabricator.dm | 19 +- code/game/mecha/mecha.dm | 129 ++++-- code/game/mecha/mecha_control_console.dm | 8 +- code/game/mecha/mecha_wreckage.dm | 7 + code/game/mecha/working/firefighter.dm | 9 +- code/game/mecha/working/ripley.dm | 22 +- code/game/mecha/working/tools/tools.dm | 297 ------------- code/game/mecha/working/working.dm | 29 +- icons/misc/mech_construct.dmi | Bin 7231 -> 21433 bytes maps/tgstation.2.0.3.dmm | 2 +- tgstation.dme | 11 +- 23 files changed, 823 insertions(+), 659 deletions(-) create mode 100644 code/game/mecha/equipment/mecha_equipment.dm create mode 100644 code/game/mecha/equipment/tools/tools.dm rename code/game/mecha/{combat => equipment}/weapons/weapons.dm (62%) delete mode 100644 code/game/mecha/working/tools/tools.dm diff --git a/code/defines/procs/AStar.dm b/code/defines/procs/AStar.dm index 17d3dccc287..7909d6cd475 100644 --- a/code/defines/procs/AStar.dm +++ b/code/defines/procs/AStar.dm @@ -121,6 +121,8 @@ proc var/PriorityQueue/open = new /PriorityQueue(/proc/PathWeightCompare) var/closed[] = new() var/path[] + start = get_turf(start) + if(!start) return 0 open.Enqueue(new /PathNode(start,null,0,call(start,dist)(end))) diff --git a/code/defines/procs/gamehelpers.dm b/code/defines/procs/gamehelpers.dm index 05987df680e..d0c4cf223c3 100644 --- a/code/defines/procs/gamehelpers.dm +++ b/code/defines/procs/gamehelpers.dm @@ -81,3 +81,29 @@ //turfs += centerturf return turfs + +/proc/circlerangeturfs(center=usr,radius=3) + + var/turf/centerturf = get_turf(center) + var/list/turfs = new/list() + var/rsq = radius * (radius+0.5) + + for(var/turf/T in range(radius, centerturf)) + var/dx = T.x - centerturf.x + var/dy = T.y - centerturf.y + if(dx*dx + dy*dy <= rsq) + turfs += T + return turfs + +/proc/circleviewturfs(center=usr,radius=3) + + var/turf/centerturf = get_turf(center) + var/list/turfs = new/list() + var/rsq = radius * (radius+0.5) + + for(var/turf/T in view(radius, centerturf)) + var/dx = T.x - centerturf.x + var/dy = T.y - centerturf.y + if(dx*dx + dy*dy <= rsq) + turfs += T + return turfs \ No newline at end of file diff --git a/code/game/asteroid/asteroid.dm b/code/game/asteroid/asteroid.dm index 6d288d76643..e120ab6e8a5 100644 --- a/code/game/asteroid/asteroid.dm +++ b/code/game/asteroid/asteroid.dm @@ -8,8 +8,9 @@ proc/spawn_asteroid(var/atom/start_loc,var/type,var/size,var/richness)//type: 0 if(!richness) richness = rand(10,40) // world << "Asteroid size: [size]; Asteroid type: [type]" - var/list/turfs = circlerange(start_loc,size) + var/list/turfs = circlerangeturfs(start_loc,size) var/area/asteroid/AstAr = new + AstAr.name = "Asteroid #[start_loc.x][start_loc.y][start_loc.z]" for(var/turf/T in turfs) var/dist = get_dist(start_loc,T) if(abs(GaussRand(dist))= 10) + var/x_len = rand(4,size) + var/y_len = pick(4,size) var/st_l = locate(start_loc.x-round(x_len/2),start_loc.y-round(y_len/2),start_loc.z) spawn_room(st_l,x_len,y_len) max_secret_rooms-- -*/ + return 1 -/proc/populate_w_asteroids(var/z,var/density) +/proc/populate_w_asteroids(var/z,var/density=null) if(!density) density = pick(10,20,40) while(density) @@ -96,9 +97,9 @@ proc/spawn_asteroid(var/atom/start_loc,var/type,var/size,var/richness)//type: 0 proc/spawn_room(var/atom/start_loc,var/x_size,var/y_size,var/wall,var/floor) var/list/room_turfs = list("walls"=list(),"floors"=list()) - world << "Room spawned at [start_loc.x],[start_loc.y],[start_loc.z]" + //world << "Room spawned at [start_loc.x],[start_loc.y],[start_loc.z]" if(!wall) - wall = pick(/turf/simulated/wall/r_wall,/turf/simulated/wall) + wall = pick(/turf/simulated/wall/r_wall,/turf/simulated/wall,/obj/alien/resin) if(!floor) floor = pick(/turf/simulated/floor,/turf/simulated/floor/engine) @@ -141,7 +142,18 @@ proc/admin_spawn_room_at_pos() spawn_room(locate(x,y,z),x_len,y_len,wall,floor) return +var/global/list/space_surprises = list(/obj/alien/facehugger, + /obj/livestock/spesscarp, + /obj/livestock/spesscarp/elite, + /obj/creature, + /obj/item/weapon/rcd, + /obj/item/weapon/rcd_ammo, + /obj/item/weapon/spacecash, + /obj/item/weapon/cloaking_device, + /obj/item/weapon/gun/energy/teleport_gun, + /obj/item/weapon/rubber_chicken, + /obj/item/weapon/sword/pirate + ) - -var/global/max_secret_rooms = 3 \ No newline at end of file +var/global/max_secret_rooms = 6 diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 38f4310906f..2dd666a0229 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -65,6 +65,8 @@ rcd light flash thingy on matter drain rcdmod.uses -- for(var/obj/item/weapon/rcd/rcd in world) rcd.disabled = 1 + for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world) + rcd.disabled = 1 usr << "RCD-disabling pulse emitted." else usr << "Out of uses." diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm index 8a6fc0438c9..a2cb685ba09 100644 --- a/code/game/mecha/combat/combat.dm +++ b/code/game/mecha/combat/combat.dm @@ -1,9 +1,6 @@ /obj/mecha/combat deflect_chance = 10 health = 500 - - var/list/weapons = new - var/datum/mecha_weapon/selected_weapon operation_req_access = list(access_security) internals_req_access = list(access_engine,access_robotics) var/force = 25 @@ -33,12 +30,14 @@ return */ +/* /obj/mecha/combat/range_action(target as obj|mob|turf) if(internal_damage&MECHA_INT_CONTROL_LOST) target = pick(view(3,target)) if(selected_weapon) selected_weapon.fire(target) return +*/ /obj/mecha/combat/melee_action(target as obj|mob|turf) if(internal_damage&MECHA_INT_CONTROL_LOST) @@ -115,7 +114,7 @@ V.show_message("[src.name] hits [target].", 1) if(!istype(target, /turf/simulated/wall)) target:attackby(src,src.occupant) - else if(prob(5)) + else if(prob(20)) target:dismantle_wall(1) src.occupant_message("\blue You smash through the wall.") src.visible_message("[src.name] smashes through the wall") @@ -153,17 +152,9 @@ return 0 */ -/obj/mecha/combat/Topic(href, href_list) - ..() - if (href_list["select_weapon"]) - var/weapon = locate(href_list["select_weapon"]) - if(weapon) - src.selected_weapon = weapon - return - /obj/mecha/combat/moved_inside(var/mob/living/carbon/human/H as mob) - if(..(H)) + if(..()) if(usr.client) usr.client.mouse_pointer_icon = file("icons/misc/mecha_mouse.dmi") return 1 @@ -176,26 +167,12 @@ ..() return - -/obj/mecha/combat/check_for_internal_damage(var/list/possible_int_damage,var/ignore_threshold=null) - ..() - if(prob(5) && (ignore_threshold || (src.health*100/initial(src.health))The [destr_weapon] is destroyed!") - src.log_append_to_last("[destr_weapon] is destoyed.",1) - src.occupant << sound('weapdestr.ogg',volume=50) - return - /obj/mecha/combat/get_stats_part() var/output = ..() output += "Weapon systems:
" - if(weapons.len) - for(var/datum/mecha_weapon/W in weapons) - output += "[selected_weapon==W?"":""][W.get_weapon_info()][selected_weapon==W?"":""]
" + if(equipment.len) + for(var/obj/item/mecha_parts/mecha_equipment/W in equipment) + output += "[selected==W?"":""][W.get_equip_info()][selected==W?"":""]
" else output += "None" output += "
" diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm index 8ab1c8ac45c..9df6bc6d9e1 100644 --- a/code/game/mecha/combat/durand.dm +++ b/code/game/mecha/combat/durand.dm @@ -4,7 +4,7 @@ icon_state = "durand" step_in = 6 health = 350 - deflect_chance = 12 + deflect_chance = 15 max_temperature = 3000 infra_luminosity = 8 operation_req_access = list(access_security) @@ -13,17 +13,20 @@ var/defence_deflect = 30 wreckage = "/obj/decal/mecha_wreckage/durand" - +/* /obj/mecha/combat/durand/New() ..() weapons += new /datum/mecha_weapon/ballistic/lmg(src) weapons += new /datum/mecha_weapon/ballistic/scattershot(src) selected_weapon = weapons[1] return +*/ /obj/mecha/combat/durand/relaymove(mob/user,direction) if(defence) - src.occupant_message("Unable to move while in defence mode") + if(world.time - last_message > 20) + src.occupant_message("Unable to move while in defence mode") + last_message = world.time return 0 . = ..() return diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm index c4812e5ae32..6c20420f385 100644 --- a/code/game/mecha/combat/gygax.dm +++ b/code/game/mecha/combat/gygax.dm @@ -11,6 +11,7 @@ operation_req_access = list(access_security) wreckage = "/obj/decal/mecha_wreckage/gygax" +/* /obj/mecha/combat/gygax/New() ..() weapons += new /datum/mecha_weapon/taser(src) @@ -18,6 +19,7 @@ weapons += new /datum/mecha_weapon/missile_rack/flashbang(src) selected_weapon = weapons[1] return +*/ /obj/mecha/combat/gygax/verb/overload() set category = "Exosuit Interface" diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm index ac2c279f78b..6c5993f07b2 100644 --- a/code/game/mecha/combat/honker.dm +++ b/code/game/mecha/combat/honker.dm @@ -12,20 +12,20 @@ /obj/mecha/combat/honker/New() ..() +/* weapons += new /datum/mecha_weapon/honker(src) weapons += new /datum/mecha_weapon/missile_rack/banana_mortar(src) weapons += new /datum/mecha_weapon/missile_rack/mousetrap_mortar(src) selected_weapon = weapons[1] return +*/ /obj/mecha/combat/honker/melee_action(target) - if(internal_damage&MECHA_INT_CONTROL_LOST) - target = pick(oview(1,src)) if(!melee_can_hit || !istype(target, /atom)) return - if(istype(selected_weapon, /datum/mecha_weapon/honker)) - selected_weapon.fire(target) + if(istype(selected, /obj/item/mecha_parts/mecha_equipment/weapon/honker)) + selected.action(target) else if(istype(target, /mob)) step_away(target,src,15) return @@ -43,9 +43,9 @@ Lights: [lights?"on":"off"]
"} output += "HONKon systems:
" - if(weapons.len) - for(var/datum/mecha_weapon/W in weapons) - output += "[selected_weapon==W?"":""][W.get_weapon_info()][selected_weapon==W?"":""]
" + if(equipment.len) + for(var/obj/item/mecha_parts/mecha_equipment/W in equipment) + output += "[selected==W?"":""][W.get_equip_info()][selected==W?"":""]
" else output += "None. HONK!" output += "
" diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm index 43543e3eff1..142dfe715c4 100644 --- a/code/game/mecha/combat/marauder.dm +++ b/code/game/mecha/combat/marauder.dm @@ -19,9 +19,10 @@ /obj/mecha/combat/marauder/New() ..() - weapons += new /datum/mecha_weapon/pulse(src) - weapons += new /datum/mecha_weapon/missile_rack(src) - selected_weapon = weapons[1] + var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/pulse + ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack + ME.attach(src) src.smoke_system.set_up(3, 0, src) src.smoke_system.attach(src) return @@ -30,10 +31,14 @@ if(!can_move) return 0 if(zoom) - src.occupant_message("Unable to move while in zoom mode.") + if(world.time - last_message > 20) + src.occupant_message("Unable to move while in zoom mode.") + last_message = world.time return 0 if(connected_port) - src.occupant_message("Unable to move while connected to the air system port") + if(world.time - last_message > 20) + src.occupant_message("Unable to move while connected to the air system port") + last_message = world.time return 0 if(!thrusters && src.pr_inertial_movement.active()) return 0 diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm new file mode 100644 index 00000000000..b9d251c35eb --- /dev/null +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -0,0 +1,74 @@ +//TODO: Add critfail checks and reliability + +/obj/item/mecha_parts/mecha_equipment + name = "mecha equipment" + icon = 'mech_construct.dmi' + icon_state = "mecha_equip" + force = 5 + construction_time = 100 + construction_cost = list("metal"=10000) + var/equip_cooldown = 0 + var/equip_ready = 1 + var/energy_drain = 0 + var/obj/mecha/chassis = null + var/ranged = 0 + + +/obj/item/mecha_parts/mecha_equipment/proc/do_after_cooldown() + sleep(equip_cooldown) + if(src && chassis) + return 1 + return 0 + + +/obj/item/mecha_parts/mecha_equipment/New() + ..() + return + + +/obj/item/mecha_parts/mecha_equipment/proc/destroy()//missiles detonating, teleporter creating singularity? + spawn + del src + return + +/obj/item/mecha_parts/mecha_equipment/proc/get_equip_info() + return "* [src.name]" + +/obj/item/mecha_parts/mecha_equipment/proc/is_ranged()//add a distance restricted equipment. Why not? + return ranged + + +/obj/item/mecha_parts/mecha_equipment/proc/action_checks(atom/target) + if(!target) + return 0 + if(!chassis) + return 0 + if(energy_drain && chassis.get_charge() < energy_drain) + return 0 + if(!equip_ready) + return 0 + return 1 + +/obj/item/mecha_parts/mecha_equipment/proc/action(atom/target) + return + +/obj/item/mecha_parts/mecha_equipment/proc/can_attach(obj/mecha/M as obj) + if(istype(M)) + if(M.equipment.len[target] succesfully loaded.") + chassis.log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]") + else + chassis.occupant_message("You must hold still while handling objects.") + O.anchored = initial(O.anchored) + equip_ready = 1 + + else + chassis.occupant_message("Not enough room in cargo compartment.") + else + chassis.occupant_message("[target] is firmly secured.") + + else if(istype(target,/mob)) + var/mob/M = target + if(M.stat>1) return + if(chassis.occupant.a_intent == "hurt") + M.bruteloss += dam_force + M.oxyloss += round(dam_force/2) + M.updatehealth() + chassis.occupant_message("\red You squeese [target] with [src.name]. Something cracks.") + chassis.visible_message("\red [chassis] squeeses [target].") + else + step_away(M,chassis) + chassis.occupant_message("You push [target] out of the way.") + chassis.visible_message("[chassis] pushes [target] out of the way.") + equip_ready = 0 + chassis.cell.use(energy_drain) + spawn(equip_cooldown) + equip_ready = 1 + return 1 + +/obj/item/mecha_parts/mecha_equipment/tool/drill + name = "Drill" + icon_state = "mecha_drill" + equip_cooldown = 40 + energy_drain = 20 + force = 15 + + action(atom/target) + if(!action_checks(target)) return + equip_ready = 0 + chassis.cell.use(energy_drain) + chassis.visible_message("[chassis] starts to drill [target]", "You hear the drill.") + chassis.occupant_message("You start to drill [target]") + var/T = chassis.loc + if(do_after_cooldown()) + if(T == chassis.loc && src == chassis.selected) + if(istype(target, /turf/simulated/wall/r_wall)) + chassis.occupant_message("[target] is too durable to drill through.") + else if(istype(target, /turf/simulated/mineral)) + var/turf/simulated/mineral/M = target + chassis.log_message("Drilled through [target]") + M.gets_drilled() + for(var/turf/simulated/mineral/N in range(chassis,1)) + if(get_dir(chassis,N)&chassis.dir) + N.gets_drilled() + else + chassis.log_message("Drilled through [target]") + target.ex_act(2) + equip_ready = 1 + return 1 + + +/obj/item/mecha_parts/mecha_equipment/tool/extinguisher + name = "Extinguisher" + icon_state = "mecha_exting" + equip_cooldown = 5 + energy_drain = 0 + + New() + reagents = new/datum/reagents(200) + reagents.my_atom = src + reagents.add_reagent("water", 200) + ..() + return + + action(atom/target) //copypasted from extinguisher. TODO: Rewrite from scratch. + if(!action_checks(target)) return + if(get_dist(chassis, target)>2) return + equip_ready = 0 + if(do_after_cooldown()) + equip_ready = 1 + if(istype(target, /obj/reagent_dispensers/watertank) && get_dist(chassis,target) <= 1) + var/obj/o = target + o.reagents.trans_to(src, 200) + chassis.occupant_message("\blue Extinguisher refilled") + playsound(chassis, 'refill.ogg', 50, 1, -6) + else + if(src.reagents.total_volume > 0) + playsound(chassis, 'extinguish.ogg', 75, 1, -3) + var/direction = get_dir(chassis,target) + var/turf/T = get_turf(target) + var/turf/T1 = get_step(T,turn(direction, 90)) + var/turf/T2 = get_step(T,turn(direction, -90)) + + var/list/the_targets = list(T,T1,T2) + for(var/a=0, a<5, a++) + spawn(0) + var/obj/effects/water/W = new /obj/effects/water(get_turf(chassis)) + if(!W) + return + var/turf/my_target = pick(the_targets) + var/datum/reagents/R = new/datum/reagents(5) + W.reagents = R + R.my_atom = W + src.reagents.trans_to(W,1) + for(var/b=0, b<5, b++) + if(!W) + return + step_towards(W,my_target) + if(!W) + return + var/turf/W_turf = get_turf(W) + W.reagents.reaction(W_turf) + for(var/atom/atm in W_turf) + W.reagents.reaction(atm) + if(W.loc == my_target) + break + sleep(2) + return 1 + + get_equip_info() + return "[..()] \[[src.reagents.total_volume]\]" + + on_reagent_change() + return + + +/obj/item/mecha_parts/mecha_equipment/tool/rcd + name = "Mounted RCD" + icon_state = "mecha_rcd" + equip_cooldown = 20 + energy_drain = 250 + ranged = 1 + construction_time = 1200 + construction_cost = list("metal"=50000,"plasma"=40000,"silver"=30000,"gold"=20000) + var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock. + var/disabled = 0 //malf + + action(atom/target) + if(!action_checks(target) || disabled || get_dist(chassis, target)>3) return + playsound(src.loc, 'click.ogg', 50, 1) + //meh + switch(mode) + if(0) + if (istype(target, /turf/simulated/wall)) + chassis.occupant_message("Deconstructing [target]...") + equip_ready = 0 + if(do_after_cooldown()) + if(disabled) return + chassis.spark_system.start() + target:ReplaceWithFloor() + playsound(src.loc, 'Deconstruct.ogg', 50, 1) + equip_ready = 1 + chassis.cell.give(energy_drain) + else if (istype(target, /turf/simulated/floor)) + chassis.occupant_message("Deconstructing [target]...") + equip_ready = 0 + if(do_after_cooldown()) + if(disabled) return + chassis.spark_system.start() + target:ReplaceWithSpace() + playsound(src.loc, 'Deconstruct.ogg', 50, 1) + equip_ready = 1 + chassis.cell.give(energy_drain) + else if (istype(target, /obj/machinery/door/airlock)) + chassis.occupant_message("Deconstructing [target]...") + equip_ready = 0 + if(do_after_cooldown()) + if(disabled) return + chassis.spark_system.start() + del(target) + playsound(src.loc, 'Deconstruct.ogg', 50, 1) + equip_ready = 1 + chassis.cell.give(energy_drain) + if(1) + if(istype(target, /turf/space)) + chassis.occupant_message("Building Floor...") + equip_ready = 0 + if(do_after_cooldown()) + if(disabled) return + target:ReplaceWithFloor() + playsound(chassis.loc, 'Deconstruct.ogg', 50, 1) + chassis.spark_system.start() + equip_ready = 1 + chassis.cell.use(energy_drain*3) + else if(istype(target, /turf/simulated/floor)) + chassis.occupant_message("Building Wall...") + equip_ready = 0 + if(do_after_cooldown()) + if(disabled) return + target:ReplaceWithWall() + playsound(chassis.loc, 'Deconstruct.ogg', 50, 1) + chassis.spark_system.start() + equip_ready = 1 + chassis.cell.use(energy_drain*3) + if(2) + if(istype(target, /turf/simulated/floor)) + chassis.occupant_message("Building Airlock...") + equip_ready = 0 + if(do_after_cooldown()) + if(disabled) return + chassis.spark_system.start() + var/obj/machinery/door/airlock/T = new /obj/machinery/door/airlock(target) + T.autoclose = 1 + playsound(src.loc, 'Deconstruct.ogg', 50, 1) + playsound(src.loc, 'sparks2.ogg', 50, 1) + equip_ready = 1 + chassis.cell.use(energy_drain*3) + return + + + Topic(href,href_list) + ..() + if(href_list["mode"]) + mode = text2num(href_list["mode"]) + switch(mode) + if(0) + chassis.occupant_message("Swithed RCD to Deconstruct.") + if(1) + chassis.occupant_message("Swithed RCD to Construct.") + if(2) + chassis.occupant_message("Swithed RCD to Construct Airlock.") + return + + get_equip_info() + return "[..()] \[D|C|A\]" + + + + +/obj/item/mecha_parts/mecha_equipment/teleporter + name = "Teleporter" + icon_state = "mecha_teleport" + equip_cooldown = 300 + energy_drain = 1000 + ranged = 1 + + action(atom/target) + if(!action_checks(target)) return + var/turf/T = get_turf(target) + if(T) + equip_ready = 0 + do_teleport(chassis, T, 4) + if(do_after_cooldown()) + equip_ready = 1 + return + + +/obj/item/mecha_parts/mecha_equipment/wormhole_generator + name = "Wormhole Generator" + icon_state = "mecha_teleport" + equip_cooldown = 50 + energy_drain = 300 + ranged = 1 + + + action(atom/target) + if(!action_checks(target)) return + var/list/theareas = list() + for(var/area/AR in orange(100, chassis)) + if(AR in theareas) continue + theareas += AR + if(!theareas.len) + return + var/area/thearea = pick(theareas) + var/list/L = list() + for(var/turf/T in get_area_turfs(thearea.type)) + if(!T.density) + var/clear = 1 + for(var/obj/O in T) + if(O.density) + clear = 0 + break + if(clear) + L+=T + if(!L.len) + return + var/turf/target_turf = pick(L) + if(!target_turf) + return + chassis.cell.use(energy_drain) + equip_ready = 0 + var/obj/portal/P = new /obj/portal(get_turf(target)) + P.target = target_turf + P.creator = null + P.icon = 'objects.dmi' + P.failchance = 0 + P.icon_state = "anom" + P.name = "wormhole" + if(do_after_cooldown()) + equip_ready = 1 + src = null + spawn(rand(150,300)) + del(P) + return \ No newline at end of file diff --git a/code/game/mecha/combat/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm similarity index 62% rename from code/game/mecha/combat/weapons/weapons.dm rename to code/game/mecha/equipment/weapons/weapons.dm index dd472656ba2..03454e4e51b 100644 --- a/code/game/mecha/combat/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -1,136 +1,30 @@ -/datum/mecha_weapon - var/name = "mecha weapon" - var/weapon_cooldown = 0 - var/weapon_ready = 1 - var/energy_drain = 0 - var/obj/mecha/combat/chassis = null +/obj/item/mecha_parts/mecha_equipment/weapon + name = "mecha weapon" + ranged = 1 + origin_tech = "materials=3;combat=3" -/datum/mecha_weapon/New(mecha) - if(!istype(mecha, /obj/mecha/combat)) - return - src.chassis = mecha - chassis.log_append_to_last("[src.name] initialized.") - return +/obj/item/mecha_parts/mecha_equipment/weapon/can_attach(obj/mecha/M as obj) + if(..()) + if(istype(M, /obj/mecha/combat)) + return 1 + return 0 -/datum/mecha_weapon/proc/destroy() - spawn - del src - return - - -/datum/mecha_weapon/proc/get_weapon_info() - return src.name - - -/datum/mecha_weapon/proc/fire_checks(target) //general checks. - if(!target) - return 0 - if(!chassis) - return 0 - if(energy_drain && chassis.get_charge() < energy_drain) - return 0 - if(!weapon_ready) - return 0 - return 1 - -/datum/mecha_weapon/proc/fire(target) - return fire_checks(target) - - - -/datum/mecha_weapon/missile_rack //TODO: move missile racks to ballistic class - name = "SRM-8 Missile Rack" - var/missiles = 8 - var/missile_speed = 2 - var/missile_range = 30 - var/missile_energy_cost = 1000 - weapon_cooldown = 60 - - fire(target) - if(!fire_checks(target) || missiles <=0) return - weapon_ready = 0 - var/obj/item/missile/M = new /obj/item/missile(chassis.loc) - M.primed = 1 - playsound(chassis, 'bang.ogg', 50, 1) - M.throw_at(target, missile_range, missile_speed) - missiles-- - spawn(weapon_cooldown) - weapon_ready = 1 - chassis.log_message("Fired from [src.name], targeting [target].") - return - - proc/rearm() - if(missiles < initial(missiles)) - var/missiles_to_add = initial(missiles) - missiles - while(chassis.get_charge() >= missile_energy_cost && missiles_to_add) - missiles++ - missiles_to_add-- - chassis.cell.use(missile_energy_cost) - chassis.log_message("Rearmed [src.name].") - return - - get_weapon_info() - return "[src.name]\[[src.missiles]\][(src.missiles < initial(src.missiles))?" - Rearm":null]" - - Topic(href, href_list) - if (href_list["rearm"]) - src.rearm() - return - - - -/obj/item/missile - icon = 'grenade.dmi' - icon_state = "flashbang" - var/primed = null - throwforce = 15 - - throw_impact(atom/hit_atom) - if(primed) - explosion(hit_atom, 0, 0, 2, 4) - del(src) - else - ..() - return - -/datum/mecha_weapon/missile_rack/flashbang - name = "SGL-6 Grenade Launcher" - missiles = 6 - missile_speed = 1.5 - missile_energy_cost = 800 - weapon_cooldown = 60 - var/det_time = 20 - - fire(target) - if(!fire_checks(target) || missiles <=0) return - weapon_ready = 0 - var/obj/item/weapon/flashbang/F = new /obj/item/weapon/flashbang(chassis.loc) - playsound(chassis, 'bang.ogg', 50, 1) - F.throw_at(target, missile_range, missile_speed) - missiles-- - spawn(det_time) - F.prime() - spawn(weapon_cooldown) - weapon_ready = 1 - chassis.log_message("Fired from [src.name], targeting [target].") - return - -/datum/mecha_weapon/laser - weapon_cooldown = 10 +/obj/item/mecha_parts/mecha_equipment/weapon/laser + equip_cooldown = 10 name = "CH-PS \"Immolator\" Laser" + icon_state = "mecha_laser" energy_drain = 30 - fire(target) - if(!fire_checks(target)) return - + action(target) + if(!action_checks(target)) return var/turf/curloc = chassis.loc var/atom/targloc = get_turf(target) if (!targloc || !istype(targloc, /turf) || !curloc) return if (targloc == curloc) return - weapon_ready = 0 + equip_ready = 0 playsound(chassis, 'Laser.ogg', 50, 1) var/obj/beam/a_laser/A = new /obj/beam/a_laser(curloc) A.current = curloc @@ -138,19 +32,20 @@ A.xo = targloc.x - curloc.x chassis.cell.use(energy_drain) A.process() - spawn(weapon_cooldown) - weapon_ready = 1 chassis.log_message("Fired from [src.name], targeting [target].") + if(do_after_cooldown()) + equip_ready = 1 return -/datum/mecha_weapon/pulse - weapon_cooldown = 30 +/obj/item/mecha_parts/mecha_equipment/weapon/pulse + equip_cooldown = 30 name = "eZ-13 mk2 Heavy pulse rifle" + icon_state = "mecha_pulse" energy_drain = 120 - fire(target) - if(!fire_checks(target)) return + action(target) + if(!action_checks(target)) return var/turf/curloc = chassis.loc var/atom/targloc = get_turf(target) @@ -164,12 +59,12 @@ A.current = curloc A.yo = targloc.y - curloc.y A.xo = targloc.x - curloc.x - weapon_ready = 0 + equip_ready = 0 chassis.cell.use(energy_drain) A.process() - spawn(weapon_cooldown) - weapon_ready = 1 chassis.log_message("Fired from [src.name], targeting [target].") + if(do_after_cooldown()) + equip_ready = 1 return @@ -183,14 +78,14 @@ src.life -= 10 return -/datum/mecha_weapon/taser - weapon_cooldown = 10 +/obj/item/mecha_parts/mecha_equipment/weapon/taser name = "PBT \"Pacifier\" Mounted Taser" + icon_state = "mecha_taser" energy_drain = 20 - weapon_cooldown = 7 + equip_cooldown = 7 - fire(target) - if(!fire_checks(target)) return + action(target) + if(!action_checks(target)) return var/turf/curloc = chassis.loc var/atom/targloc = get_turf(target) @@ -204,70 +99,37 @@ A.current = curloc A.yo = targloc.y - curloc.y A.xo = targloc.x - curloc.x - weapon_ready = 0 + equip_ready = 0 chassis.cell.use(energy_drain) spawn() A.process() - spawn(weapon_cooldown) - weapon_ready = 1 chassis.log_message("Fired from [src.name], targeting [target].") + if(do_after_cooldown()) + equip_ready = 1 return -/datum/mecha_weapon/missile_rack/banana_mortar - name = "Banana Mortar" - missiles = 15 - missile_speed = 1.5 - missile_energy_cost = 100 - weapon_cooldown = 20 - - fire(target) - if(!fire_checks(target) || missiles <=0) return - weapon_ready = 0 - var/obj/item/weapon/bananapeel/B = new /obj/item/weapon/bananapeel(chassis.loc) - playsound(chassis, 'bikehorn.ogg', 60, 1) - B.throw_at(target, missile_range, missile_speed) - missiles-- - spawn(weapon_cooldown) - weapon_ready = 1 - chassis.log_message("Bananed from [src.name], targeting [target]. HONK!") - return - - -/datum/mecha_weapon/missile_rack/mousetrap_mortar - name = "Mousetrap Mortar" - missiles = 15 - missile_speed = 1.5 - missile_energy_cost = 100 - weapon_cooldown = 10 - - fire(target) - if(!fire_checks(target) || missiles <=0) return - weapon_ready = 0 - var/obj/item/weapon/mousetrap/M = new /obj/item/weapon/mousetrap(chassis.loc) - M.armed = 1 - playsound(chassis, 'bikehorn.ogg', 60, 1) - M.throw_at(target, missile_range, missile_speed) - missiles-- - spawn(weapon_cooldown) - weapon_ready = 1 - chassis.log_message("Launched a mouse-trap from [src.name], targeting [target]. HONK!") - return - - -/datum/mecha_weapon/honker - weapon_cooldown = 10 +/obj/item/mecha_parts/mecha_equipment/weapon/honker name = "HoNkER BlAsT 5000" + icon_state = "mecha_honker" energy_drain = 200 - weapon_cooldown = 150 + equip_cooldown = 150 + construction_time = 500 + construction_cost = list("metal"=20000,"bananium"=10000) - fire(target) + can_attach(obj/mecha/M as obj) + if(..()) + if(istype(M, /obj/mecha/combat/honker)) + return 1 + return 0 + + action(target) if(!chassis) return 0 if(energy_drain && chassis.get_charge() < energy_drain) return 0 - if(!weapon_ready) + if(!equip_ready) return 0 - weapon_ready = 0 + equip_ready = 0 playsound(chassis, 'AirHorn.ogg', 100, 1) chassis.occupant_message("HONK") for(var/mob/living/carbon/M in ohearers(6, chassis)) @@ -297,20 +159,24 @@ walk(thingy,0) */ chassis.cell.use(energy_drain) - spawn(weapon_cooldown) - weapon_ready = 1 chassis.log_message("Honked from [src.name]. HONK!") + if(do_after_cooldown()) + equip_ready = 1 return - - -/datum/mecha_weapon/ballistic +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic name = "General Ballisic Weapon" var/projectiles var/projectile_energy_cost - get_weapon_info() - return "[src.name]\[[src.projectiles]\][(src.projectiles < initial(src.projectiles))?" - Rearm":null]" + action_checks(atom/target) + if(..()) + if(projectiles > 0) + return 1 + return 0 + + get_equip_info() + return "[..()]\[[src.projectiles]\][(src.projectiles < initial(src.projectiles))?" - Rearm":null]" proc/rearm() if(projectiles < initial(projectiles)) @@ -328,16 +194,17 @@ return -/datum/mecha_weapon/ballistic/scattershot +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot name = "LBX AC 10 \"Scattershot\"" - weapon_cooldown = 20 + icon_state = "mecha_scatter" + equip_cooldown = 20 projectiles = 100 projectile_energy_cost = 25 var/projectiles_per_shot = 4 var/deviation = 0.7 - fire(atom/target) - if(!fire_checks(target) || projectiles <=0) return + action(atom/target) + if(!action_checks(target)) return var/turf/curloc = get_turf(chassis) var/turf/targloc = get_turf(target) if(!curloc || !targloc) return @@ -355,25 +222,26 @@ A.current = curloc A.yo = targloc.y - curloc.y A.xo = targloc.x - curloc.x - weapon_ready = 0 + equip_ready = 0 A.process() - spawn(weapon_cooldown) - weapon_ready = 1 chassis.log_message("Fired from [src.name], targeting [target].") + if(do_after_cooldown()) + equip_ready = 1 return -/datum/mecha_weapon/ballistic/lmg +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg name = "Ultra AC 2" - weapon_cooldown = 10 + icon_state = "mecha_uac2" + equip_cooldown = 10 projectiles = 300 projectile_energy_cost = 20 var/projectiles_per_shot = 3 var/deviation = 0.3 - fire(atom/target) - if(!fire_checks(target) || projectiles <=0) return + action(atom/target) + if(!action_checks(target)) return var/turf/targloc = get_turf(target) var/target_x = targloc.x var/target_y = targloc.y @@ -395,10 +263,127 @@ A.xo = targloc.x - curloc.x A.process() sleep(2) - weapon_ready = 0 - spawn(weapon_cooldown) - weapon_ready = 1 + equip_ready = 0 chassis.log_message("Fired from [src.name], targeting [target].") + if(do_after_cooldown()) + equip_ready = 1 + return + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack + name = "SRM-8 Missile Rack" + icon_state = "mecha_missilerack" + projectiles = 8 + projectile_energy_cost = 1000 + equip_cooldown = 60 + var/missile_speed = 2 + var/missile_range = 30 + + action(target) + if(!action_checks(target)) return + equip_ready = 0 + var/obj/item/missile/M = new /obj/item/missile(chassis.loc) + M.primed = 1 + playsound(chassis, 'bang.ogg', 50, 1) + M.throw_at(target, missile_range, missile_speed) + projectiles-- + chassis.log_message("Fired from [src.name], targeting [target].") + if(do_after_cooldown()) + equip_ready = 1 return +/obj/item/missile + icon = 'grenade.dmi' + icon_state = "flashbang" + var/primed = null + throwforce = 15 + + throw_impact(atom/hit_atom) + if(primed) + explosion(hit_atom, 0, 0, 2, 4) + del(src) + else + ..() + return + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang + name = "SGL-6 Grenade Launcher" + icon_state = "mecha_grenadelnchr" + projectiles = 6 + missile_speed = 1.5 + projectile_energy_cost = 800 + equip_cooldown = 60 + var/det_time = 20 + + action(target) + if(!action_checks(target)) return + equip_ready = 0 + var/obj/item/weapon/flashbang/F = new /obj/item/weapon/flashbang(chassis.loc) + playsound(chassis, 'bang.ogg', 50, 1) + F.throw_at(target, missile_range, missile_speed) + projectiles-- + chassis.log_message("Fired from [src.name], targeting [target].") + spawn(det_time) + F.prime() + if(do_after_cooldown()) + equip_ready = 1 + return + + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar + name = "Banana Mortar" + icon_state = "mecha_bananamrtr" + projectiles = 15 + missile_speed = 1.5 + projectile_energy_cost = 100 + equip_cooldown = 20 + construction_time = 300 + construction_cost = list("metal"=20000,"bananium"=5000) + + can_attach(obj/mecha/M as obj) + if(..()) + if(istype(M, /obj/mecha/combat/honker)) + return 1 + return 0 + + action(target) + if(!action_checks(target)) return + equip_ready = 0 + var/obj/item/weapon/bananapeel/B = new /obj/item/weapon/bananapeel(chassis.loc) + playsound(chassis, 'bikehorn.ogg', 60, 1) + B.throw_at(target, missile_range, missile_speed) + projectiles-- + chassis.log_message("Bananed from [src.name], targeting [target]. HONK!") + if(do_after_cooldown()) + equip_ready = 1 + return + + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar + name = "Mousetrap Mortar" + icon_state = "mecha_mousetrapmrtr" + projectiles = 15 + missile_speed = 1.5 + projectile_energy_cost = 100 + equip_cooldown = 10 + construction_time = 300 + construction_cost = list("metal"=20000,"bananium"=5000) + + can_attach(obj/mecha/M as obj) + if(..()) + if(istype(M, /obj/mecha/combat/honker)) + return 1 + return 0 + + action(target) + if(!action_checks(target)) return + equip_ready = 0 + var/obj/item/weapon/mousetrap/M = new /obj/item/weapon/mousetrap(chassis.loc) + M.armed = 1 + playsound(chassis, 'bikehorn.ogg', 60, 1) + M.throw_at(target, missile_range, missile_speed) + projectiles-- + chassis.log_message("Launched a mouse-trap from [src.name], targeting [target]. HONK!") + if(do_after_cooldown()) + equip_ready = 1 + return \ No newline at end of file diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index c0e734adf1f..3e901b88577 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -398,6 +398,7 @@ "silver"=0, "diamond"=0, "plasma"=0, + "uranium"=0, "bananium"=0 ) var/res_max_amount = 200000 @@ -436,6 +437,20 @@ /obj/item/mecha_parts/part/honker_left_leg, /obj/item/mecha_parts/part/honker_right_leg ), + "Exosuit Equipment"=list( + /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp, + /obj/item/mecha_parts/mecha_equipment/tool/drill, + /obj/item/mecha_parts/mecha_equipment/tool/extinguisher, + /obj/item/mecha_parts/mecha_equipment/tool/rcd, + /obj/item/mecha_parts/mecha_equipment/weapon/laser, + /obj/item/mecha_parts/mecha_equipment/weapon/taser, + /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg, + /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot, + /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang, + /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar, + /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/banana_mortar, + /obj/item/mecha_parts/mecha_equipment/weapon/honker), + "Misc"=list(/obj/item/mecha_tracking) ) @@ -535,7 +550,7 @@ proc/output_available_resources() var/output for(var/resource in resources) - output += "[resource]: [min(res_max_amount, resources[resource])] cm3
" + output += "[resource]: [min(res_max_amount, resources[resource])] cm³
" return output proc/remove_resources(var/obj/item/mecha_parts/part as obj) @@ -733,6 +748,8 @@ material = "glass" else if(istype(W, /obj/item/stack/sheet/clown)) material = "bananium" + else if(istype(W, /obj/item/stack/sheet/uranium)) + material = "uranium" else return ..() diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index f9565e1b0ca..f6a02c64da5 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -24,6 +24,7 @@ var/obj/item/weapon/cell/cell = new var/state = 0 var/list/log = new + var/last_message = 0 var/datum/effects/system/spark_spread/spark_system = new var/lights = 0 @@ -52,6 +53,10 @@ var/wreckage + var/list/equipment = new + var/obj/item/mecha_parts/mecha_equipment/selected + var/max_equip = 2 + /obj/mecha/New() ..() @@ -111,50 +116,21 @@ var/dir_to_target = get_dir(src,target) if(dir_to_target && !(dir_to_target & src.dir))//wrong direction return - if(get_dist(src,target)>1) - src.range_action(target) + if(internal_damage&MECHA_INT_CONTROL_LOST) + target = pick(view(3,target)) + var/dist = get_dist(src, target) + if(dist>1) + if(selected && selected.is_ranged()) + selected.action(target) + else if(selected && !selected.is_ranged()) + selected.action(target) else src.melee_action(target) return /obj/mecha/proc/melee_action(atom/target) -/* - if(istype(target, /obj/machinery/door/airlock)) - var/obj/machinery/door/airlock/A = target - if(A.locked) - src.occupant_message("Unable to open airlock - bolted") - return 0 - else if(src.density && !src.welded && !src.operating) && ((!src.arePowerSystemsOn()) || (stat & NOPOWER))) - if(src.arePowerSystemsOn() && !(stat&NOPOWER)) - A.open() - else - spawn(0) - src.operating = 1 - animate("opening") - sleep(15) - src.density = 0 - update_icon() - if (!istype(src, /obj/machinery/door/airlock/glass)) - src.sd_SetOpacity(0) - src.operating = 0 - return 0 - else if(!src.density && !src.welded && !src.operating) - if(src.arePowerSystemsOn() && !(stat&NOPOWER)) - A.close() - else - spawn( 0 ) - src.operating = 1 - animate("closing") - src.density = 1 - sleep(15) - update_icon() - if ((src.visible) && (!istype(src, /obj/machinery/door/airlock/glass))) - src.sd_SetOpacity(1) - src.operating = 0 - return 0 -*/ - return 1 + return /obj/mecha/proc/range_action(atom/target) return @@ -234,15 +210,23 @@ // src.inertia_dir = null if(istype(obstacle, /obj)) var/obj/O = obstacle - if(istype(obstacle , /obj/machinery/door)) + if(istype(O , /obj/machinery/door)) if(src.occupant) O.Bumped(src.occupant) + /* //not working, will fix later + else if(istype(O, /obj/portal)) //derpfix + src.anchored = 0 + O.Bumped(src) + src.anchored = 1 + */ else if(!O.anchored) step(obstacle,src.dir) -// else -// obstacle.Bumped(src) + else //I have no idea why I disabled this + obstacle.Bumped(src) else if(istype(obstacle, /mob)) step(obstacle,src.dir) + else + obstacle.Bumped(src) return @@ -255,12 +239,13 @@ if("brute") src.health -= amount if("fire") - src.health -= amount*1.2 + amount *= 1.2 + src.health -= amount src.update_health() src.log_append_to_last("Took [amount] points of damage. Damage type: \"[type]\".",1) return -/obj/mecha/proc/check_for_internal_damage(var/list/possible_int_damage,var/ignore_threshold=null)//TODO +/obj/mecha/proc/check_for_internal_damage(var/list/possible_int_damage,var/ignore_threshold=null) if(!src) return if(prob(25)) if(ignore_threshold || src.health*100/initial(src.health)The [destr] is destroyed!") + src.log_append_to_last("[destr] is destroyed.",1) + if(istype(destr, /obj/item/mecha_parts/mecha_equipment/weapon)) + src.occupant << sound('weapdestr.ogg',volume=50) + else + src.occupant << sound('critdestr.ogg',volume=50) return @@ -390,12 +390,20 @@ // var/mob/M = src.occupant var/turf/T = src.loc var/wreckage = src.wreckage + var/list/r_equipment = src.equipment src = null del(mecha) explosion(T, 0, 0, 1, 3) spawn(0) if(wreckage) - new wreckage(T) + var/obj/decal/mecha_wreckage/WR = new wreckage(T) + for(var/obj/item/mecha_parts/mecha_equipment/E in r_equipment) + if(prob(30)) + WR.equipment += E + E.reliability = rand(30,100) + else + E.loc = T + E.destroy() return /obj/mecha/ex_act(severity) @@ -596,7 +604,10 @@ return usr << "You start climbing into [src.name]" spawn(20) - moved_inside(usr) + if(!src.occupant) + moved_inside(usr) + else if(src.occupant!=usr) + usr << "[src.occupant] was faster. Try better next time, loser." return /obj/mecha/proc/moved_inside(var/mob/living/carbon/human/H as mob) @@ -730,6 +741,16 @@ /obj/mecha/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/mecha_parts/mecha_equipment)) + var/obj/item/mecha_parts/mecha_equipment/E = W + spawn() + if(E.can_attach(src)) + user.drop_item() + E.attach(src) + user.visible_message("[user] attaches [W] to [src]", "You attach [W] to [src]") + else + user << "You were unable to attach [W] to [src]" + return if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) if(src.occupant) user << "Unable to initiate maintenance protocol." @@ -900,6 +921,10 @@ else src.occupant_message("Recalibration failed.") src.log_message("Recalibration of coordination system failed with 1 error.",1) + if(href_list["select_equip"]) + var/obj/item/mecha_parts/mecha_equipment/equip = locate(href_list["select_equip"]) + if(equip) + src.selected = equip /* if (href_list["ai_take_control"]) @@ -965,10 +990,24 @@ /obj/mecha/hear_talk(mob/M as mob, text) if(occupant && M) + if(!occupant.say_understands(M)) + text = stars(text) var/rendered = "[M.name] [M.say_quote(text)]" occupant.show_message(rendered, 2) return +/* +if ("binary") + if(src.robot_talk_understand || src.binarycheck()) + //message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) //seems redundant + src.robot_talk(message) + return +if ("alientalk") + if(src.alien_talk_understand || src.hivecheck()) + //message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) //seems redundant + src.alien_talk(message) + return +*/ /obj/mecha/proc/get_charge()//returns null if no powercell, else returns cell.charge if(!src.cell) return return max(0, src.cell.charge) diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm index 89dce975e53..70bc263e669 100644 --- a/code/game/mecha/mecha_control_console.dm +++ b/code/game/mecha/mecha_control_console.dm @@ -102,13 +102,7 @@ Airtank: [M.return_pressure()]kPa
Pilot: [M.occupant||"None"]
Location: [get_area(M)||"Unknown"]
- Active equipment:"} - if(istype(M, /obj/mecha/combat)) - var/obj/mecha/combat/CM = M - answer += " [CM.selected_weapon.name]
" - else if(istype(M, /obj/mecha/working)) - var/obj/mecha/working/WM = M - answer += " [WM.selected_tool.name]
" + Active equipment: [M.selected||"None"]"} if(istype(M, /obj/mecha/working/ripley)) var/obj/mecha/working/ripley/RM = M answer += "Used cargo space: [RM.cargo.len/RM.cargo_capacity*100]%
" diff --git a/code/game/mecha/mecha_wreckage.dm b/code/game/mecha/mecha_wreckage.dm index 0e8ec6875b0..927f5718145 100644 --- a/code/game/mecha/mecha_wreckage.dm +++ b/code/game/mecha/mecha_wreckage.dm @@ -13,6 +13,7 @@ var/list/welder_salvage = list("/obj/item/stack/sheet/r_metal","/obj/item/stack/sheet/metal","/obj/item/stack/rods") var/list/wirecutters_salvage = list("/obj/item/weapon/cable_coil") var/list/crowbar_salvage = list("/obj/item/weapon/cell") + var/list/equipment = new var/salvage_num = 5 /obj/decal/mecha_wreckage/ex_act(severity) @@ -50,6 +51,12 @@ user << "You failed to salvage anything valuable from [src]." salvage_num-- if(istype(W, /obj/item/weapon/crowbar)) + if(equipment.len) + var/obj/item/mecha_parts/mecha_equipment/E = pick(equipment) + if(E) + E.loc = get_turf(user) + user.visible_message("[user] pries [E] from [src].", "You pry [E] from [src].") + return if(salvage_num<=0) user << "You can't see anything of value left on this wreck." return diff --git a/code/game/mecha/working/firefighter.dm b/code/game/mecha/working/firefighter.dm index 8358ea5c9be..323aedea476 100644 --- a/code/game/mecha/working/firefighter.dm +++ b/code/game/mecha/working/firefighter.dm @@ -1,15 +1,15 @@ /obj/mecha/working/firefighter - desc = "Standart APLU chassis was refitted with additional thermal protection, cistern and fire pump." + desc = "Standart APLU chassis was refitted with additional thermal protection and cistern." name = "Ripley-on-Fire" icon_state = "ripley" step_in = 8 max_temperature = 6000 - health = 200 + health = 250 internal_damage_threshold = 40 wreckage = "/obj/decal/mecha_wreckage/ripley" infra_luminosity = 5 - +/* /obj/mecha/working/firefighter/New() ..() // tools += new /datum/mecha_tool/uni_interface(src) @@ -21,4 +21,5 @@ tools += new g_type(src) */ selected_tool = tools[1] - return \ No newline at end of file + return +*/ \ No newline at end of file diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm index d081b89385b..27cd2c149a2 100644 --- a/code/game/mecha/working/ripley.dm +++ b/code/game/mecha/working/ripley.dm @@ -6,23 +6,19 @@ max_temperature = 1000 health = 200 wreckage = "/obj/decal/mecha_wreckage/ripley" - var/list/cargo = new var/cargo_capacity = 15 - +/* /obj/mecha/working/ripley/New() ..() -// tools += new /datum/mecha_tool/uni_interface(src) - tools += new /datum/mecha_tool/hydraulic_clamp(src) - tools += new /datum/mecha_tool/drill(src) -/* - for(var/g_type in typesof(/datum/mecha_tool/gimmick)) - if(g_type!=/datum/mecha_tool/gimmick) - tools += new g_type(src) -*/ - selected_tool = tools[1] return +*/ + +/obj/mecha/working/ripley/Exit(atom/movable/O) + if(O in cargo) + return 0 + return ..() /obj/mecha/working/ripley/Topic(href, href_list) @@ -57,9 +53,7 @@ if(M==src.occupant) continue M.loc = get_turf(src) - var/turf/T = get_turf(M) - if(T) - T.Entered(M) + M.loc.Entered(M) step_rand(M) for(var/atom/movable/A in src.cargo) A.loc = get_turf(src) diff --git a/code/game/mecha/working/tools/tools.dm b/code/game/mecha/working/tools/tools.dm deleted file mode 100644 index 9b24a09d938..00000000000 --- a/code/game/mecha/working/tools/tools.dm +++ /dev/null @@ -1,297 +0,0 @@ -/datum/mecha_tool - var/name = "mecha tool" - var/tool_cooldown = 0 - var/tool_ready = 1 - var/energy_drain = 0 - var/obj/mecha/working/chassis = null - - -/datum/mecha_tool/New(mecha) - if(!istype(mecha, /obj/mecha/working)) - return - src.chassis = mecha - chassis.log_append_to_last("[src.name] initialized.") - return - - -/datum/mecha_tool/proc/destroy() - spawn - del src - return - -/datum/mecha_tool/proc/get_tool_info() - return src.name - - -/datum/mecha_tool/proc/action(atom/target) - if(!target) - return 0 - if(!chassis) - return 0 - if(energy_drain && chassis.get_charge() < energy_drain) - return 0 - if(!tool_ready) - return 0 - return 1 - -/datum/mecha_tool/proc/range_action(atom/target) - return - - -/* - //Merde, cette proc est tres bugged -/datum/mecha_tool/uni_interface - name = "Universal Interface" - tool_cooldown = 10 - tool_ready = 1 - energy_drain = 5 - - action(atom/target) - if(!..()) return - if(istype(target, /obj)) - var/obj/O = target - if(O.allowed(chassis.occupant)) - target.attack_hand(chassis.occupant) - return - -*/ - -/datum/mecha_tool/hydraulic_clamp - name = "Hydraulic Clamp" - tool_cooldown = 15 - energy_drain = 10 - var/force = 20 - var/obj/mecha/working/ripley/cargo_holder - - New() - ..() - if(istype(chassis, /obj/mecha/working/ripley)) - cargo_holder = chassis - return - - action(atom/target) - if(!..()) return - if(!cargo_holder) return - if(istype(target,/obj)) - var/obj/O = target - if(!O.anchored) - if(cargo_holder.cargo.len < cargo_holder.cargo_capacity) - chassis.occupant_message("You lift [target] and start to load it into cargo compartment.") - chassis.visible_message("[chassis] lifts [target] and starts to load it into cargo compartment.") - tool_ready = 0 - chassis.cell.use(energy_drain) - O.anchored = 1 - var/T = chassis.loc - spawn(tool_cooldown) - if(chassis) - if(T == chassis.loc && src == chassis.selected_tool) - cargo_holder.cargo += O - O.loc = chassis - O.anchored = 0 - if(istype(O, /obj/machinery/bot))// That's shit-code right here, folks. - O:on = 0 - chassis.occupant_message("[target] succesfully loaded.") - chassis.log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]") - else - chassis.occupant_message("You must hold still while handling objects.") - O.anchored = initial(O.anchored) - tool_ready = 1 - - else - chassis.occupant << "Not enough room in cargo compartment." - else - chassis.occupant << "[target] is firmly secured." - - else if(istype(target,/mob)) - var/mob/M = target - if(M.stat>1) return - if(chassis.occupant.a_intent == "hurt") - M.bruteloss += force - M.oxyloss += round(force/2) - M.updatehealth() - chassis.occupant_message("\red You squeese [target] with [src.name]. Something cracks.") - chassis.visible_message("\red [chassis] squeeses [target].") - else - step_away(M,chassis) - chassis.occupant_message("You push [target] out of the way.") - chassis.visible_message("[chassis] pushes [target] out of the way.") - tool_ready = 0 - chassis.cell.use(energy_drain) - spawn(tool_cooldown) - tool_ready = 1 - return - -/datum/mecha_tool/drill - name = "Drill" - tool_cooldown = 40 - energy_drain = 20 - var/force = 15 - - action(atom/target) - if(!..()) return - tool_ready = 0 - chassis.cell.use(energy_drain) - chassis.visible_message("[chassis] starts to drill [target]", "You hear the drill.") - chassis.occupant_message("You start to drill [target]") - var/T = chassis.loc - spawn(tool_cooldown) - if(chassis) - if(T == chassis.loc && src == chassis.selected_tool) - if(istype(target, /turf/simulated/wall/r_wall)) - chassis.occupant_message("[target] is too durable to drill through.") - else if(istype(target, /turf/simulated/mineral)) - var/turf/simulated/mineral/M = target - chassis.log_message("Drilled through [target]") - M.gets_drilled() - for(var/turf/simulated/mineral/N in range(chassis,1)) - if(get_dir(chassis,N)&chassis.dir) - N.gets_drilled() - else - chassis.log_message("Drilled through [target]") - target.ex_act(2) - tool_ready = 1 - return - - -/datum/mecha_tool/extinguisher - name = "Extinguisher" - tool_cooldown = 7 - energy_drain = 0 - var/datum/reagents/reagents - - - New() - reagents = new/datum/reagents(200) - reagents.my_atom = src - reagents.add_reagent("water", 200) - ..() - return - - action(atom/target) //copypasted from extinguisher. TODO: Rewrite from scratch. - if(!..()) return - if(get_dist(chassis, target)>2) return - tool_ready = 0 - spawn(tool_cooldown) - tool_ready = 1 - if(istype(target, /obj/reagent_dispensers/watertank) && get_dist(chassis,target) <= 1) - var/obj/o = target - o.reagents.trans_to(src, 200) - chassis.occupant_message("\blue Extinguisher refilled") - playsound(chassis, 'refill.ogg', 50, 1, -6) - else - if(src.reagents.total_volume > 0) - playsound(chassis, 'extinguish.ogg', 75, 1, -3) - var/direction = get_dir(chassis,target) - var/turf/T = get_turf(target) - var/turf/T1 = get_step(T,turn(direction, 90)) - var/turf/T2 = get_step(T,turn(direction, -90)) - - var/list/the_targets = list(T,T1,T2) - for(var/a=0, a<5, a++) - spawn(0) - var/obj/effects/water/W = new /obj/effects/water(get_turf(chassis)) - if(!W) - return - var/turf/my_target = pick(the_targets) - var/datum/reagents/R = new/datum/reagents(5) - W.reagents = R - R.my_atom = W - src.reagents.trans_to(W,1) - for(var/b=0, b<5, b++) - if(!W) - return - step_towards(W,my_target) - if(!W) - return - var/turf/W_turf = get_turf(W) - W.reagents.reaction(W_turf) - for(var/atom/atm in W_turf) - W.reagents.reaction(atm) - if(W.loc == my_target) - break - sleep(2) - return - - get_tool_info() - return "[src.name] \[[src.reagents.total_volume]\]" - - proc/on_reagent_change() - return - - -/* -/datum/mecha_tool/gimmick - name = "Gimmick" - tool_cooldown = 10 - tool_ready = 1 - energy_drain = 10 - var/real_tool_type - var/real_tool_obj - - action(atom/target) - if(!..()) return - target.attackby(real_tool_obj,chassis.occupant) - tool_ready = 0 - chassis.cell.use(energy_drain) - spawn(tool_cooldown) - tool_ready = 1 - return - - New() - ..() - real_tool_obj = new real_tool_type(chassis) - return - -/datum/mecha_tool/gimmick/screwdriver - name = "Screwdriver" - tool_cooldown = 10 - tool_ready = 1 - energy_drain = 10 - real_tool_type = /obj/item/weapon/screwdriver - - -/datum/mecha_tool/gimmick/wrench - name = "Wrench" - tool_cooldown = 10 - tool_ready = 1 - energy_drain = 10 - real_tool_type = /obj/item/weapon/wrench - -/datum/mecha_tool/gimmick/wirecutters - name = "Wirecutters" - tool_cooldown = 10 - tool_ready = 1 - energy_drain = 10 - real_tool_type = /obj/item/weapon/wirecutters - -/datum/mecha_tool/gimmick/multitool - name = "Multitool" - tool_cooldown = 10 - tool_ready = 1 - energy_drain = 10 - real_tool_type = /obj/item/device/multitool - -/datum/mecha_tool/gimmick/crowbar - name = "Crowbar" - tool_cooldown = 10 - tool_ready = 1 - energy_drain = 10 - real_tool_type = /obj/item/weapon/crowbar - -/datum/mecha_tool/gimmick/weldingtool - name = "Weldingtool" - tool_cooldown = 10 - tool_ready = 1 - energy_drain = 15 - real_tool_type = /obj/item/weapon/weldingtool - - action(atom/target) - var/obj/item/weapon/weldingtool/W = real_tool_obj - W.welding = 1 - W.reagents.add_reagent("fuel", W.reagents.maximum_volume - W.get_fuel()) - ..() - return -*/ - - - diff --git a/code/game/mecha/working/working.dm b/code/game/mecha/working/working.dm index c0995edfe65..c113d650420 100644 --- a/code/game/mecha/working/working.dm +++ b/code/game/mecha/working/working.dm @@ -2,8 +2,6 @@ deflect_chance = 10 health = 500 req_access = access_heads - var/datum/mecha_tool/selected_tool - var/list/tools = new operation_req_access = list(access_engine,access_robotics) internals_req_access = list(access_engine,access_robotics) var/add_req_access = 1 @@ -14,23 +12,20 @@ new /obj/item/mecha_tracking(src) return - +/* /obj/mecha/working/melee_action(atom/target as obj|mob|turf) if(internal_damage&MECHA_INT_CONTROL_LOST) target = pick(oview(1,src)) if(selected_tool) selected_tool.action(target) return +*/ /obj/mecha/working/range_action(atom/target as obj|mob|turf) return /obj/mecha/working/Topic(href, href_list) ..() - if (href_list["select_tool"]) - var/tool = locate(href_list["select_tool"]) - if(tool) - src.selected_tool = tool if (href_list["unlock_id_upload"]) add_req_access = 1 if (href_list["add_req_access"]) @@ -50,29 +45,15 @@ /obj/mecha/working/get_stats_part() var/output = ..() output += "[src.name] Tools:
" - if(tools.len) - for(var/datum/mecha_tool/MT in tools) - output += "[selected_tool==MT?"":""][MT.get_tool_info()][selected_tool==MT?"":""]
" + if(equipment.len) + for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment) + output += "[selected==MT?"":""][MT.get_equip_info()][selected==MT?"":""]
" else output += "None" output += "
" return output -/obj/mecha/working/check_for_internal_damage(var/list/possible_int_damage,var/ignore_threshold=null) - ..() - if(prob(5) && (ignore_threshold || (src.health*100/initial(src.health))The [destr_tool] is destroyed!") - src.log_append_to_last("[destr_tool] is destroyed.") - src.occupant << sound('critdestr.ogg',volume=50) - return - - /obj/mecha/working/attackby(obj/item/weapon/W as obj, mob/user as mob) if(add_req_access && (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))) var/obj/item/weapon/card/id/id_card diff --git a/icons/misc/mech_construct.dmi b/icons/misc/mech_construct.dmi index b0d3f5d8f5855ef51de97c7fcb926c31ce2916f7..1eddcc3d142e7c675930c2d1f017eccfc6c54a40 100644 GIT binary patch literal 21433 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 diff --git a/maps/tgstation.2.0.3.dmm b/maps/tgstation.2.0.3.dmm index e76c645bb48..9547f647081 100644 --- a/maps/tgstation.2.0.3.dmm +++ b/maps/tgstation.2.0.3.dmm @@ -913,7 +913,7 @@ "arC" = (/obj/machinery/door/airlock/external{name = "West Auxillary Solar Maintenance"; req_access = null; req_access_txt = "13"},/obj/cable{icon_state = "1-2"; d1 = 1; d2 = 2},/turf/simulated/floor/plating,/area/maintenance/auxsolarport) "arD" = (/obj/grille,/obj/window/reinforced{dir = 4},/obj/window/reinforced{dir = 1},/obj/window/reinforced{dir = 8},/turf/simulated/floor/plating,/area/storage/tech) "arE" = (/obj/rack{dir = 8},/obj/item/weapon/circuitboard/aiupload,/turf/simulated/floor,/area/storage/tech) -"arF" = (/obj/rack{dir = 8},/obj/item/weapon/circuitboard/robotics,/turf/simulated/floor,/area/storage/tech) +"arF" = (/obj/rack{dir = 8},/obj/item/weapon/circuitboard/mecha_control{pixel_x = -2; pixel_y = 2},/obj/item/weapon/circuitboard/robotics{pixel_x = 1; pixel_y = -1},/turf/simulated/floor,/area/storage/tech) "arG" = (/obj/machinery/atmospherics/pipe/simple{dir = 5},/turf/simulated/floor/plating,/area/maintenance/fpmaint) "arH" = (/obj/machinery/atmospherics/pipe/manifold,/turf/simulated/floor/plating,/area/maintenance/fpmaint) "arI" = (/obj/machinery/atmospherics/pipe/simple{dir = 4},/obj/machinery/door/airlock/maintenance{req_access_txt = "12"},/turf/simulated/floor/plating,/area/maintenance/fpmaint) diff --git a/tgstation.dme b/tgstation.dme index aa6f4cb3662..32b803f3950 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -53,9 +53,10 @@ #define FILE_DIR "code/game/magic/cultist" #define FILE_DIR "code/game/mecha" #define FILE_DIR "code/game/mecha/combat" -#define FILE_DIR "code/game/mecha/combat/weapons" +#define FILE_DIR "code/game/mecha/equipment" +#define FILE_DIR "code/game/mecha/equipment/tools" +#define FILE_DIR "code/game/mecha/equipment/weapons" #define FILE_DIR "code/game/mecha/working" -#define FILE_DIR "code/game/mecha/working/tools" #define FILE_DIR "code/game/objects" #define FILE_DIR "code/game/objects/alien" #define FILE_DIR "code/game/objects/closets" @@ -429,14 +430,16 @@ #include "code\game\mecha\mecha_control_console.dm" #include "code\game\mecha\mecha_wreckage.dm" #include "code\game\mecha\combat\combat.dm" +#include "code\game\mecha\combat\durand.dm" #include "code\game\mecha\combat\gygax.dm" #include "code\game\mecha\combat\honker.dm" #include "code\game\mecha\combat\marauder.dm" -#include "code\game\mecha\combat\weapons\weapons.dm" +#include "code\game\mecha\equipment\mecha_equipment.dm" +#include "code\game\mecha\equipment\tools\tools.dm" +#include "code\game\mecha\equipment\weapons\weapons.dm" #include "code\game\mecha\working\firefighter.dm" #include "code\game\mecha\working\ripley.dm" #include "code\game\mecha\working\working.dm" -#include "code\game\mecha\working\tools\tools.dm" #include "code\game\objects\assemblies.dm" #include "code\game\objects\blood.dm" #include "code\game\objects\bomb.dm"