From 258f477eb384869320a7b7ae75eb197cda22cb53 Mon Sep 17 00:00:00 2001 From: Tigercat2000 Date: Fri, 12 Aug 2016 05:46:03 -0700 Subject: [PATCH] /tg/ mecha - Part 1 Start of porting the /tg/station mecha update. This commit only cleans up the code and adds the proper dependencies for the mecha. - Removes relative pathing from /datum/events - Updated Process_Spacemove() to use atom/movable/proc/get_spacemove_backup() - Basically just makes launching off of unanchored objects in space an OOP behaviour - Removed styling atrocities and relative pathing from most of the mecha files. - Notable exceptions: - code/game/mecha/mech_bay.dm - code/game/mecha/mech_fabricator.dm - code/game/mecha/mecha_construction_paths.dm - code/game/mecha/mecha_parts.dm - code/game/mecha/mecha_wreckage.dm - code/game/mecha/paintkits.dm - Removed dyndomove/dyndoattackby/dyndobulletact. No more icky dynamic calls. Replaced by specific code for the 3 modules that used it. - Refactored module cooldown. It now uses addtimer, and power usage is hooked directly into the cooldown calls. - Added atom/movable/proc/has_buckled_mobs(). Currently not that useful, but, necessary for porting the multi-buckling system from /tg/. - Split code/game/mecha/equipment/tools/tools.dm into multiple files. - Removed snowflake behaviour from exosuit drill. It now calls turf.drill_act(src). - Different from /tg/: Allows you to drill any wall/floor normally. - Drill no longer gibs mobs. It deals 80 organ damage instead. - Drill can be used to harvest dead mobs. - Removed all global_iterator systems from mecha and mecha equipment. Everything now uses object processing. - Mecha now have a turn sound variable and step sound variable. Updated all subtypes to use these instead of snowflake domove procs. - Removed mecha_do_after, mecha now uses the normal do_after. - Removed enter_after, same as above. - /obj/mecha/Process_Spacemove no longer strangely calls the user's spacemove. - /obj/mecha/return_pressure now uses return_air instead of copypasted cabin air detection. - Same for /obj/mecha/return_temperature - Added /obj/mecha/Exited. Basically, properly clears occupant refs, even if they teleport out/otherwise exit improperly. - Added hooks for mecha action buttons; Didn't implement them yet. - Moved mecha UI to code/game/mecha/mecha_topic.dm - Fixed turfs not updating atmos when ChangeTurf(/turf/space) is used. - Updated visible_message and audible_message. Both now use get_mobs_in_view() to ensure that mobs inside containers can see messages. - Removed /obj/item/mecha_parts/mecha_equipment/tool subtype. It had no use. Any subtypes are now just subtypes of /obj/item/mecha_parts/mecha_equipment. --- _maps/map_files/RandomZLevels/spacebattle.dmm | 6 +- _maps/map_files/cyberiad/z2.dmm | 2 +- code/datums/helper_datums/events.dm | 103 +- code/game/atoms_movable.dm | 19 + code/game/machinery/doors/airlock.dm | 2 +- code/game/mecha/combat/combat.dm | 18 +- code/game/mecha/combat/durand.dm | 16 +- code/game/mecha/combat/gygax.dm | 24 +- code/game/mecha/combat/honker.dm | 11 +- code/game/mecha/combat/marauder.dm | 116 +- code/game/mecha/combat/phazon.dm | 35 +- code/game/mecha/combat/recitence.dm | 2 +- code/game/mecha/equipment/mecha_equipment.dm | 73 +- .../mecha/equipment/tools/medical_tools.dm | 1103 ++++++------- .../mecha/equipment/tools/mining_tools.dm | 136 ++ .../game/mecha/equipment/tools/other_tools.dm | 494 ++++++ code/game/mecha/equipment/tools/tools.dm | 1147 -------------- code/game/mecha/equipment/tools/work_tools.dm | 452 ++++++ code/game/mecha/mecha.dm | 1411 +++++------------ code/game/mecha/mecha_topic.dm | 393 +++++ code/game/mecha/medical/medical.dm | 23 +- code/game/mecha/medical/odysseus.dm | 63 +- code/game/mecha/working/ripley.dm | 84 +- code/game/mecha/working/working.dm | 26 - code/game/objects/buckling.dm | 5 + code/game/turfs/turf.dm | 3 + code/modules/mining/mine_turfs.dm | 5 +- code/modules/mob/mob.dm | 14 +- code/modules/mob/mob_movement.dm | 34 +- .../designs/mechfabricator_designs.dm | 20 +- .../xenoarchaeology/artifact/artifact.dm | 2 +- .../artifact/artifact_hoverpod.dm | 31 +- code/modules/surgery/generic.dm | 2 +- paradise.dme | 5 +- 34 files changed, 2716 insertions(+), 3164 deletions(-) create mode 100644 code/game/mecha/equipment/tools/mining_tools.dm create mode 100644 code/game/mecha/equipment/tools/other_tools.dm delete mode 100644 code/game/mecha/equipment/tools/tools.dm create mode 100644 code/game/mecha/equipment/tools/work_tools.dm create mode 100644 code/game/mecha/mecha_topic.dm diff --git a/_maps/map_files/RandomZLevels/spacebattle.dmm b/_maps/map_files/RandomZLevels/spacebattle.dmm index f398c6134e5..3f824e041db 100644 --- a/_maps/map_files/RandomZLevels/spacebattle.dmm +++ b/_maps/map_files/RandomZLevels/spacebattle.dmm @@ -190,8 +190,8 @@ "dH" = (/obj/item/stack/rods,/turf/simulated/floor/plasteel,/area/awaymission/spacebattle/cruiser) "dI" = (/obj/mecha/medical/odysseus,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) "dJ" = (/obj/mecha/working/ripley/firefighter,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) -"dK" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) -"dL" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/tool/drill,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) +"dK" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) +"dL" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/drill,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) "dM" = (/obj/structure/reagent_dispensers/watertank,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) "dN" = (/obj/structure/reagent_dispensers/fueltank,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) "dO" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/floor/plasteel{icon_state = "bar"},/area/awaymission/spacebattle/cruiser) @@ -209,7 +209,7 @@ "ea" = (/obj/machinery/gateway{dir = 9},/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) "eb" = (/obj/machinery/gateway{dir = 1},/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) "ec" = (/obj/machinery/gateway{dir = 5},/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) -"ed" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) +"ed" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/syringe_gun,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) "ee" = (/obj/structure/closet/crate{name = "Gold Crate"},/obj/item/mecha_parts/mecha_equipment/repair_droid,/turf/simulated/floor/plating,/area/awaymission/spacebattle/cruiser) "ef" = (/mob/living/simple_animal/hostile/syndicate/melee,/turf/simulated/floor/plasteel{icon_state = "bar"},/area/awaymission/spacebattle/cruiser) "eg" = (/obj/structure/closet/l3closet/security,/turf/simulated/floor/plasteel{icon_state = "red"; dir = 4},/area/awaymission/spacebattle/cruiser) diff --git a/_maps/map_files/cyberiad/z2.dmm b/_maps/map_files/cyberiad/z2.dmm index 1938244976c..c8213e50a6f 100644 --- a/_maps/map_files/cyberiad/z2.dmm +++ b/_maps/map_files/cyberiad/z2.dmm @@ -1127,7 +1127,7 @@ "Eb" = (/obj/structure/rack,/obj/item/clothing/shoes/magboots/syndie{pixel_x = -3; pixel_y = 3},/obj/item/clothing/shoes/magboots/advance,/obj/item/clothing/shoes/magboots{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "Ec" = (/obj/structure/rack,/obj/item/clothing/shoes/green{pixel_x = -3; pixel_y = 3},/obj/item/clothing/shoes/centcom,/obj/item/clothing/shoes/syndigaloshes{pixel_x = 3; pixel_y = -3},/obj/item/clothing/shoes/rainbow{pixel_x = -3; pixel_y = 3},/obj/item/clothing/shoes/combat/swat,/obj/item/clothing/shoes/combat{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "Ed" = (/obj/structure/rack,/obj/item/clothing/suit/pirate_black{pixel_x = -3; pixel_y = 3},/obj/item/clothing/suit/blacktrenchcoat,/obj/item/clothing/suit/jacket{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) -"Ee" = (/obj/item/mecha_parts/mecha_equipment/tool/cable_layer,/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill,/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp,/obj/item/mecha_parts/mecha_equipment/tool/rcd,/obj/item/mecha_parts/mecha_equipment/tool/extinguisher,/obj/structure/closet/crate,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) +"Ee" = (/obj/item/mecha_parts/mecha_equipment/cable_layer,/obj/item/mecha_parts/mecha_equipment/drill/diamonddrill,/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp,/obj/item/mecha_parts/mecha_equipment/rcd,/obj/item/mecha_parts/mecha_equipment/extinguisher,/obj/structure/closet/crate,/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "Ef" = (/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/turf/unsimulated/wall{desc = "This window appears to be reinforced, it looks nearly impossible to break."; dir = 4; icon = 'icons/turf/shuttle.dmi'; icon_state = "window5_end"; name = "window"; opacity = 0; tag = "icon-window5 (EAST)"},/area/admin) "Eg" = (/obj/structure/rack,/obj/item/clothing/under/syndicate{pixel_x = -3; pixel_y = 3},/obj/item/clothing/under/syndicate/combat,/obj/item/clothing/under/acj{pixel_x = 3; pixel_y = -3},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) "Eh" = (/obj/structure/mirror{pixel_y = -30},/turf/unsimulated/floor{tag = "icon-floor"; icon_state = "floor"},/area/admin) diff --git a/code/datums/helper_datums/events.dm b/code/datums/helper_datums/events.dm index bb5e76deef3..fa0dccd2a15 100644 --- a/code/datums/helper_datums/events.dm +++ b/code/datums/helper_datums/events.dm @@ -6,62 +6,63 @@ /datum/events var/list/events - New() - ..() - events = new +/datum/events/New() + ..() + events = new - proc/addEventType(event_type as text) - if(!(event_type in events) || !islist(events[event_type])) - events[event_type] = list() - return 1 - return - - - // Arguments: event_type as text, proc_holder as datum, proc_name as text - // Returns: New event, null on error. - proc/addEvent(event_type as text, proc_holder, proc_name as text) - if(!event_type || !proc_holder || !proc_name) - return - addEventType(event_type) - var/list/event = events[event_type] - var/datum/events_event/E = new /datum/events_event(proc_holder,proc_name) - event += E - return E - - // Arguments: event_type as text, any number of additional arguments to pass to event handler - // Returns: null - proc/fireEvent() -// to_chat(world, "Events in [args[1]] called") - var/list/event = listgetindex(events,args[1]) - if(istype(event)) - spawn(-1) - for(var/datum/events_event/E in event) - if(!E.Fire(arglist(args.Copy(2)))) - clearEvent(args[1],E) - return - - // Arguments: event_type as text, E as /datum/events_event - // Returns: 1 if event cleared, null on error - proc/clearEvent(event_type as text, datum/events_event/E) - if(!event_type || !E) - return - var/list/event = listgetindex(events,event_type) - event -= E +/datum/events/proc/addEventType(event_type as text) + if(!(event_type in events) || !islist(events[event_type])) + events[event_type] = list() return 1 + return -/datum/events_event +// Arguments: event_type as text, proc_holder as datum, proc_name as text +// Returns: New event, null on error. +/datum/events/proc/addEvent(event_type as text, proc_holder, proc_name as text) + if(!event_type || !proc_holder || !proc_name) + return + addEventType(event_type) + var/list/event = events[event_type] + var/datum/event/E = new /datum/event(proc_holder,proc_name) + event += E + return E + +// Arguments: event_type as text, any number of additional arguments to pass to event handler +// Returns: null +/datum/events/proc/fireEvent() + //world << "Events in [args[1]] called" + var/list/event = listgetindex(events,args[1]) + if(istype(event)) + spawn(0) + for(var/datum/event/E in event) + if(!E.Fire(arglist(args.Copy(2)))) + clearEvent(args[1],E) + return + +// Arguments: event_type as text, E as /datum/event +// Returns: 1 if event cleared, null on error + +/datum/events/proc/clearEvent(event_type as text, datum/event/E) + if(!event_type || !E) + return + var/list/event = listgetindex(events,event_type) + event -= E + return 1 + + +/datum/event var/listener var/proc_name - New(tlistener,tprocname) - listener = tlistener - proc_name = tprocname - return ..() +/datum/event/New(tlistener,tprocname) + listener = tlistener + proc_name = tprocname + return ..() - proc/Fire() -// to_chat(world, "Event fired") - if(listener) - call(listener,proc_name)(arglist(args)) - return 1 - return \ No newline at end of file +/datum/event/proc/Fire() + //world << "Event fired" + if(listener) + call(listener,proc_name)(arglist(args)) + return 1 + return diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index a903e4ea8ed..0dd6c109170 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -345,3 +345,22 @@ if(buckled_mob == mover) return 1 return ..() + +/atom/movable/proc/get_spacemove_backup() + var/atom/movable/dense_object_backup + for(var/A in orange(1, get_turf(src))) + if(isarea(A)) + continue + else if(isturf(A)) + var/turf/turf = A + if(!turf.density) + continue + return turf + else + var/atom/movable/AM = A + if(!AM.CanPass(src) || AM.density) + if(AM.anchored) + return AM + dense_object_backup = AM + break + . = dense_object_backup diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 29dd5b7c9c1..3f21e952a36 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1001,7 +1001,7 @@ About the new airlock wires panel: to_chat(user, "The hatch is coated with a product that prevents the shaped charge from sticking!") return - if(istype(C, /obj/item/mecha_parts/mecha_equipment/tool/rcd) || istype(C, /obj/item/weapon/rcd)) + if(istype(C, /obj/item/mecha_parts/mecha_equipment/rcd) || istype(C, /obj/item/weapon/rcd)) to_chat(user, "The hatch is made of an advanced compound that cannot be deconstructed using an RCD.") return diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm index d9b26404cad..99db971b420 100644 --- a/code/game/mecha/combat/combat.dm +++ b/code/game/mecha/combat/combat.dm @@ -3,8 +3,6 @@ var/maxsize = 2 internal_damage_threshold = 50 maint_access = 0 - //add_req_access = 0 - //operation_req_access = list(access_hos) damage_absorption = list("brute"=0.7,"fire"=1,"bullet"=0.7,"laser"=0.85,"energy"=1,"bomb"=0.8) var/am = "d3c2fbcadca903a41161ccc9df9cf948" @@ -26,21 +24,13 @@ /obj/mecha/combat/go_out() - if(src.occupant && src.occupant.client) - src.occupant.client.mouse_pointer_icon = initial(src.occupant.client.mouse_pointer_icon) + if(occupant && occupant.client) + occupant.client.mouse_pointer_icon = initial(occupant.client.mouse_pointer_icon) ..() - return /obj/mecha/combat/Topic(href,href_list) ..() - var/datum/topic_input/filter = new (href,href_list) + var/datum/topic_input/filter = new(href, href_list) if(filter.get("close")) am = null - return - /* - if(filter.get("saminput")) - if(md5(filter.get("saminput")) == am) - occupant_message("From the lies of the Antipath, Circuit preserve us.") - am = null - return - */ \ No newline at end of file + return \ No newline at end of file diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm index cfe94888123..57614a8e426 100644 --- a/code/game/mecha/combat/durand.dm +++ b/code/game/mecha/combat/durand.dm @@ -22,17 +22,15 @@ ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack ME.attach(src) - return /obj/mecha/combat/durand/relaymove(mob/user,direction) if(defence) if(world.time - last_message > 20) - src.occupant_message("Unable to move while in defence mode") + occupant_message("Unable to move while in defence mode") last_message = world.time return 0 . = ..() - return /obj/mecha/combat/durand/verb/defence_mode() @@ -40,17 +38,16 @@ set name = "Toggle defence mode" set src = usr.loc set popup_menu = 0 - if(usr!=src.occupant) + if(usr != occupant) return defence = !defence if(defence) deflect_chance = defence_deflect - src.occupant_message("You enable [src] defence mode.") + occupant_message("You enable [src] defence mode.") else deflect_chance = initial(deflect_chance) - src.occupant_message("You disable [src] defence mode.") - src.log_message("Toggled defence mode.") - return + occupant_message("You disable [src] defence mode.") + log_message("Toggled defence mode.") /obj/mecha/combat/durand/get_stats_part() @@ -72,8 +69,7 @@ /obj/mecha/combat/durand/Topic(href, href_list) ..() if(href_list["toggle_defence_mode"]) - src.defence_mode() - return + defence_mode() /obj/mecha/combat/durand/old desc = "A retired, third-generation combat exosuit utilized by the Nanotrasen corporation. Originally developed to combat hostile alien lifeforms." diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm index 09caf2fcaf0..faa2329f5e4 100644 --- a/code/game/mecha/combat/gygax.dm +++ b/code/game/mecha/combat/gygax.dm @@ -24,7 +24,6 @@ ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang ME.attach(src) - return /obj/mecha/combat/gygax/dark desc = "A lightweight exosuit, painted in a dark scheme. This model appears to have some modifications." @@ -51,7 +50,6 @@ ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay ME.attach(src) - return /obj/mecha/combat/gygax/dark/add_cell(var/obj/item/weapon/stock_parts/cell/C=null) if(C) @@ -68,31 +66,30 @@ set name = "Toggle leg actuators overload" set src = usr.loc set popup_menu = 0 - if(usr!=src.occupant) + if(usr != occupant) return if(overload) overload = 0 step_in = initial(step_in) step_energy_drain = initial(step_energy_drain) - src.occupant_message("You disable leg actuators overload.") + occupant_message("You disable leg actuators overload.") else overload = 1 step_in = min(1, round(step_in/2)) step_energy_drain = step_energy_drain*overload_coeff - src.occupant_message("You enable leg actuators overload.") - src.log_message("Toggled leg actuators overload.") - return + occupant_message("You enable leg actuators overload.") + log_message("Toggled leg actuators overload.") -/obj/mecha/combat/gygax/dyndomove(direction) - if(!..()) return +/obj/mecha/combat/gygax/domove(direction) + if(!..()) + return if(overload) health-- - if(health < initial(health) - initial(health)/3) + if(health < initial(health) - initial(health) / 3) overload = 0 step_in = initial(step_in) step_energy_drain = initial(step_energy_drain) - src.occupant_message("Leg actuators damage threshold exceded. Disabling overload.") - return + occupant_message("Leg actuators damage threshold exceded. Disabling overload.") /obj/mecha/combat/gygax/get_stats_part() @@ -114,5 +111,4 @@ /obj/mecha/combat/gygax/Topic(href, href_list) ..() if(href_list["toggle_leg_overload"]) - src.overload() - return \ No newline at end of file + overload() \ No newline at end of file diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm index 4bfd5f9a161..1053b3e9856 100644 --- a/code/game/mecha/combat/honker.dm +++ b/code/game/mecha/combat/honker.dm @@ -24,7 +24,6 @@ ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/mousetrap_mortar ME.attach(src) - return /obj/mecha/combat/honker/get_stats_part() var/integrity = health/initial(health)*100 @@ -45,13 +44,13 @@ HONK pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
HONK temperature: [return_temperature()]°K|[return_temperature() - T0C]°C
Lights: [lights?"on":"off"]
- [src.dna?"DNA-locked:
[src.dna] \[Reset\]
":null] + [dna?"DNA-locked:
[dna] \[Reset\]
":null] "} return output /obj/mecha/combat/honker/get_stats_html() var/output = {" - [src.name] data + [name] data - - -

Health statistics

-
- [get_occupant_dam()] -
-

Reagents in bloodstream

-
- [get_occupant_reagents()] -
-
- [get_available_reagents()] -
- - "} - - proc/get_occupant_dam() - var/t1 - switch(occupant.stat) - if(0) - t1 = "Conscious" - if(1) - t1 = "Unconscious" - if(2) - t1 = "*dead*" - else - t1 = "Unknown" - return {"Health: [occupant.health]% ([t1])
- Core Temperature: [src.occupant.bodytemperature-T0C]°C ([src.occupant.bodytemperature*1.8-459.67]°F)
- Brute Damage: [occupant.getBruteLoss()]%
- Respiratory Damage: [occupant.getOxyLoss()]%
- Toxin Content: [occupant.getToxLoss()]%
- Burn Severity: [occupant.getFireLoss()]%
- "} - - proc/get_occupant_reagents() - if(occupant.reagents) - for(var/datum/reagent/R in occupant.reagents.reagent_list) - if(R.volume > 0) - . += "[R]: [round(R.volume,0.01)]
" - return . || "None" - - proc/get_available_reagents() - var/output - var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/SG = locate(/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun) in chassis - if(SG && SG.reagents && islist(SG.reagents.reagent_list)) - for(var/datum/reagent/R in SG.reagents.reagent_list) - if(R.volume > 0) - output += "Inject [R.name]
" - return output - - - proc/inject_reagent(var/datum/reagent/R,var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/SG) - if(!R || !occupant || !SG || !(SG in chassis.equipment)) - return 0 - var/to_inject = min(R.volume, inject_amount) - if(to_inject && occupant.reagents.get_reagent_amount(R.id) + to_inject <= inject_amount*2) - occupant_message("Injecting [occupant] with [to_inject] units of [R.name].") - log_message("Injecting [occupant] with [to_inject] units of [R.name].") - SG.reagents.trans_id_to(occupant,R.id,to_inject) - update_equip_info() - return - - container_resist(var/mob/living/L) - go_out() - - update_equip_info() - if(..()) - send_byjax(chassis.occupant,"msleeper.browser","lossinfo",get_occupant_dam()) - send_byjax(chassis.occupant,"msleeper.browser","reagents",get_occupant_reagents()) - send_byjax(chassis.occupant,"msleeper.browser","injectwith",get_available_reagents()) - return 1 - return - -/datum/global_iterator/mech_sleeper - - process(var/obj/item/mecha_parts/mecha_equipment/tool/sleeper/S) - if(!S.chassis) - S.set_ready_state(1) - return stop() - if(!S.chassis.has_charge(S.energy_drain)) - S.set_ready_state(1) - S.log_message("Deactivated.") - S.occupant_message("[src] deactivated - no power.") - return stop() - var/mob/living/carbon/M = S.occupant - if(!M) - return - if(M.health > 0) - M.adjustOxyLoss(-1) - M.updatehealth() - M.AdjustStunned(-4) - M.AdjustWeakened(-4) - M.AdjustStunned(-4) - if(M.reagents.get_reagent_amount("epinephrine") < 5) - M.reagents.add_reagent("epinephrine", 5) - S.chassis.use_power(S.energy_drain) - S.update_equip_info() - return - - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer - name = "Cable Layer" - icon_state = "mecha_wire" - var/datum/event/event - var/turf/old_turf - var/obj/structure/cable/last_piece - var/obj/item/stack/cable_coil/cable - var/max_cable = 1000 - - New() - cable = new(src) - cable.amount = 0 - ..() - - can_attach(obj/mecha/working/M) - if(..()) - if(istype(M)) - return 1 - return 0 - - attach() - ..() - event = chassis.events.addEvent("onMove",src,"layCable") - return - - detach() - chassis.events.clearEvent("onMove",event) - return ..() - - Destroy() - chassis.events.clearEvent("onMove",event) - return ..() - - action(var/obj/item/stack/cable_coil/target) - if(!action_checks(target)) - return - var/result = load_cable(target) - var/message - if(isnull(result)) - message = "Unable to load [target] - no cable found." - else if(!result) - message = "Reel is full." - else - message = "[result] meters of cable successfully loaded." - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - occupant_message(message) - return - - Topic(href,href_list) - ..() - if(href_list["toggle"]) - set_ready_state(!equip_ready) - occupant_message("[src] [equip_ready?"dea":"a"]ctivated.") - log_message("[equip_ready?"Dea":"A"]ctivated.") - return - if(href_list["cut"]) - if(cable && cable.amount) - var/m = round(input(chassis.occupant,"Please specify the length of cable to cut","Cut cable",min(cable.amount,30)) as num, 1) - m = min(m, cable.amount) - if(m) - use_cable(m) - var/obj/item/stack/cable_coil/CC = new (get_turf(chassis)) - CC.amount = m - else - occupant_message("There's no more cable on the reel.") - return - - get_equip_info() - var/output = ..() - if(output) - return "[output] \[Cable: [cable ? cable.amount : 0] m\][(cable && cable.amount) ? "- [!equip_ready?"Dea":"A"]ctivate|Cut" : null]" - return - - proc/load_cable(var/obj/item/stack/cable_coil/CC) - if(istype(CC) && CC.amount) - var/cur_amount = cable? cable.amount : 0 - var/to_load = max(max_cable - cur_amount,0) - if(to_load) - to_load = min(CC.amount, to_load) - if(!cable) - cable = new(src) - cable.amount = 0 - cable.amount += to_load - CC.use(to_load) - return to_load - else - return 0 - return - - proc/use_cable(amount) - if(!cable || cable.amount<1) - set_ready_state(1) - occupant_message("Cable depleted, [src] deactivated.") - log_message("Cable depleted, [src] deactivated.") - return - if(cable.amount < amount) - occupant_message("No enough cable to finish the task.") - return - cable.use(amount) + target.forceMove(src) + patient = target + processing_objects.Add(src) update_equip_info() + occupant_message("[target] successfully loaded into [src]. Life support functions engaged.") + chassis.visible_message("[chassis] loads [target] into [src].") + log_message("[target] loaded. Life support functions engaged.") + +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/patient_insertion_check(mob/living/carbon/target) + if(target.buckled) + occupant_message("[target] will not fit into the sleeper because they are buckled to [target.buckled]!") + return + if(target.has_buckled_mobs()) + occupant_message("[target] will not fit into the sleeper because of the creatures attached to it!") + return + if(patient) + occupant_message("The sleeper is already occupied!") + return + return 1 + +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/go_out() + if(!patient) + return + patient.forceMove(get_turf(src)) + occupant_message("[patient] ejected. Life support functions disabled.") + log_message("[patient] ejected. Life support functions disabled.") + processing_objects.Remove(src) + patient = null + update_equip_info() + +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/detach() + if(patient) + occupant_message("Unable to detach [src] - equipment occupied!") + return + processing_objects.Remove(src) + return ..() + +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/get_equip_info() + var/output = ..() + if(output) + var/temp = "" + if(patient) + temp = "
\[Occupant: [patient] ([patient.stat > 1 ? "*DECEASED*" : "Health: [patient.health]%"])\]
View stats|Eject" + return "[output] [temp]" + return + +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/Topic(href,href_list) + ..() + var/datum/topic_input/filter = new /datum/topic_input(href,href_list) + if(filter.get("eject")) + go_out() + if(filter.get("view_stats")) + chassis.occupant << browse(get_patient_stats(),"window=msleeper") + onclose(chassis.occupant, "msleeper") + return + if(filter.get("inject")) + inject_reagent(filter.getType("inject",/datum/reagent),filter.getObj("source")) + return + +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/get_patient_stats() + if(!patient) + return + return {" + + [patient] statistics + + + + +

Health statistics

+
+ [get_patient_dam()] +
+

Reagents in bloodstream

+
+ [get_patient_reagents()] +
+
+ [get_available_reagents()] +
+ + "} + +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/get_patient_dam() + var/t1 + switch(patient.stat) + if(0) + t1 = "Conscious" + if(1) + t1 = "Unconscious" + if(2) + t1 = "*dead*" + else + t1 = "Unknown" + return {"Health: [patient.stat > 1 ? "[t1]" : "[patient.health]% ([t1])"]
+ Core Temperature: [patient.bodytemperature-T0C]°C ([patient.bodytemperature*1.8-459.67]°F)
+ Brute Damage: [patient.getBruteLoss()]%
+ Respiratory Damage: [patient.getOxyLoss()]%
+ Toxin Content: [patient.getToxLoss()]%
+ Burn Severity: [patient.getFireLoss()]%
+ [patient.getCloneLoss() ? "Subject appears to have cellular damage." : ""]
+ [patient.getBrainLoss() ? "Significant brain damage detected." : ""]
+ "} + +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/get_patient_reagents() + if(patient.reagents) + for(var/datum/reagent/R in patient.reagents.reagent_list) + if(R.volume > 0) + . += "[R]: [round(R.volume,0.01)]
" + return . || "None" + +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/get_available_reagents() + var/output + var/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/SG = locate(/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun) in chassis + if(SG && SG.reagents && islist(SG.reagents.reagent_list)) + for(var/datum/reagent/R in SG.reagents.reagent_list) + if(R.volume > 0) + output += "Inject [R.name]
" + return output + + +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/inject_reagent(datum/reagent/R,obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/SG) + if(!R || !patient || !SG || !(SG in chassis.equipment)) + return 0 + var/to_inject = min(R.volume, inject_amount) + if(to_inject && patient.reagents.get_reagent_amount(R.id) + to_inject <= inject_amount*2) + occupant_message("Injecting [patient] with [to_inject] units of [R.name].") + log_message("Injecting [patient] with [to_inject] units of [R.name].") + add_logs(chassis.occupant, patient, "injected", "[name] ([R] - [to_inject] units)") + SG.reagents.trans_id_to(patient,R.id,to_inject) + update_equip_info() + return + +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/update_equip_info() + if(..()) + if(patient) + send_byjax(chassis.occupant,"msleeper.browser","lossinfo",get_patient_dam()) + send_byjax(chassis.occupant,"msleeper.browser","reagents",get_patient_reagents()) + send_byjax(chassis.occupant,"msleeper.browser","injectwith",get_available_reagents()) return 1 + return - proc/reset() - last_piece = null +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/container_resist() + go_out() - proc/dismantleFloor(var/turf/new_turf) - if(istype(new_turf, /turf/simulated/floor)) - var/turf/simulated/floor/T = new_turf - if(!istype(T, /turf/simulated/floor/plating)) - if(!T.broken && !T.burnt) - new T.floor_tile(T) - T.make_plating() - return !new_turf.intact +/obj/item/mecha_parts/mecha_equipment/medical/sleeper/process() + if(..()) + return + if(!chassis.has_charge(energy_drain)) + set_ready_state(1) + log_message("Deactivated.") + occupant_message("[src] deactivated - no power.") + processing_objects.Remove(src) + return + var/mob/living/carbon/M = patient + if(!M) + return + if(M.health > 0) + M.adjustOxyLoss(-1) + M.updatehealth() + M.AdjustStunned(-4) + M.AdjustWeakened(-4) + M.AdjustStunned(-4) + if(M.reagents.get_reagent_amount("epinephrine") < 5) + M.reagents.add_reagent("epinephrine", 5) + chassis.use_power(energy_drain) + update_equip_info() - proc/layCable(var/turf/new_turf) - if(equip_ready || !istype(new_turf) || !dismantleFloor(new_turf)) - return reset() - var/fdirn = turn(chassis.dir,180) - for(var/obj/structure/cable/LC in new_turf) // check to make sure there's not a cable there already - if(LC.d1 == fdirn || LC.d2 == fdirn) - return reset() - if(!use_cable(1)) - return reset() - var/obj/structure/cable/NC = new(new_turf) - NC.cableColor("red") - NC.d1 = 0 - NC.d2 = fdirn - NC.updateicon() - var/datum/powernet/PN - if(last_piece && last_piece.d2 != chassis.dir) - last_piece.d1 = min(last_piece.d2, chassis.dir) - last_piece.d2 = max(last_piece.d2, chassis.dir) - last_piece.updateicon() - PN = last_piece.powernet - - if(!PN) - PN = new() - PN.add_cable(NC) - NC.mergeConnectedNetworks(NC.d2) - - //NC.mergeConnectedNetworksOnTurf() - last_piece = NC - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun - name = "Syringe Gun" - desc = "Exosuit-mounted chem synthesizer with syringe gun. Reagents inside are held in stasis, so no reactions will occur. (Can be attached to: Medical Exosuits)" +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun + name = "exosuit syringe gun" + desc = "Equipment for medical exosuits. A chem synthesizer with syringe gun. Reagents inside are held in stasis, so no reactions will occur." icon = 'icons/obj/guns/projectile.dmi' icon_state = "syringegun" - item_state = "syringegun" - lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi' - righthand_file = 'icons/mob/inhands/guns_righthand.dmi' + flags = NOREACT var/list/syringes var/list/known_reagents var/list/processed_reagents @@ -397,273 +252,271 @@ var/synth_speed = 5 //[num] reagent units per cycle energy_drain = 10 var/mode = 0 //0 - fire syringe, 1 - analyze reagents. - var/datum/global_iterator/mech_synth/synth range = MELEE|RANGED equip_cooldown = 10 - origin_tech = "materials=3;biotech=4;magnets=4;programming=3" + origin_tech = "materials=3;biotech=4;magnets=4" - New() - ..() - flags |= NOREACT - syringes = new - known_reagents = list("epinephrine"="Epinephrine","charcoal"="Charcoal") - processed_reagents = new - create_reagents(max_volume) - synth = new (list(src),0) +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/New() + ..() + create_reagents(max_volume) + syringes = new + known_reagents = list("epinephrine"="Epinephrine","charcoal"="Charcoal") + processed_reagents = new - detach() - synth.stop() - return ..() +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/detach() + processing_objects.Remove(src) + return ..() - critfail() - ..() - flags &= ~NOREACT +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/Destroy() + processing_objects.Remove(src) + return ..() + +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/critfail() + ..() + flags &= ~NOREACT + +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/can_attach(obj/mecha/medical/M) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/get_equip_info() + var/output = ..() + if(output) + return "[output] \[[mode? "Analyze" : "Launch"]\]
\[Syringes: [syringes.len]/[max_syringes] | Reagents: [reagents.total_volume]/[reagents.maximum_volume]\]
Reagents list" + return + +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/action(atom/movable/target) + if(!action_checks(target)) return - - can_attach(obj/mecha/medical/M) - if(..()) - if(istype(M)) - return 1 - return 0 - - get_equip_info() - var/output = ..() - if(output) - return "[output] \[[mode? "Analyze" : "Launch"]\]
\[Syringes: [syringes.len]/[max_syringes] | Reagents: [reagents.total_volume]/[reagents.maximum_volume]\]
Reagents list" + if(istype(target,/obj/item/weapon/reagent_containers/syringe)) + return load_syringe(target) + if(istype(target,/obj/item/weapon/storage))//Loads syringes from boxes + for(var/obj/item/weapon/reagent_containers/syringe/S in target.contents) + load_syringe(S) return - - action(atom/movable/target) - if(!action_checks(target)) - return - if(istype(target,/obj/item/weapon/reagent_containers/syringe)) - return load_syringe(target) - if(istype(target,/obj/item/weapon/storage))//Loads syringes from boxes - for(var/obj/item/weapon/reagent_containers/syringe/S in target.contents) - load_syringe(S) - return - if(mode) - return analyze_reagents(target) - if(!syringes.len) - occupant_message("No syringes loaded.") - return - if(reagents.total_volume<=0) - occupant_message("No available reagents to load syringe with.") - return - set_ready_state(0) - chassis.use_power(energy_drain) - var/turf/trg = get_turf(target) - var/obj/item/weapon/reagent_containers/syringe/S = syringes[1] - S.forceMove(get_turf(chassis)) - reagents.trans_to(S, min(S.volume, reagents.total_volume)) - syringes -= S - S.icon = 'icons/obj/chemical.dmi' - S.icon_state = "syringeproj" - playsound(chassis, 'sound/items/syringeproj.ogg', 50, 1) - log_message("Launched [S] from [src], targeting [target].") - spawn(-1) - src = null //if src is deleted, still process the syringe - for(var/i=0, i<6, i++) - if(!S) - break - if(step_towards(S,trg)) - var/list/mobs = new - for(var/mob/living/carbon/M in S.loc) - mobs += M - var/mob/living/carbon/M = safepick(mobs) - if(M) - S.icon_state = initial(S.icon_state) - S.icon = initial(S.icon) - S.reagents.reaction(M, INGEST) - S.reagents.trans_to(M, S.reagents.total_volume) + if(mode) + return analyze_reagents(target) + if(!syringes.len) + occupant_message("No syringes loaded.") + return + if(reagents.total_volume<=0) + occupant_message("No available reagents to load syringe with.") + return + var/turf/trg = get_turf(target) + var/obj/item/weapon/reagent_containers/syringe/mechsyringe = syringes[1] + mechsyringe.forceMove(get_turf(chassis)) + reagents.trans_to(mechsyringe, min(mechsyringe.volume, reagents.total_volume)) + syringes -= mechsyringe + mechsyringe.icon = 'icons/obj/chemical.dmi' + mechsyringe.icon_state = "syringeproj" + playsound(chassis, 'sound/items/syringeproj.ogg', 50, 1) + log_message("Launched [mechsyringe] from [src], targeting [target].") + var/mob/originaloccupant = chassis.occupant + spawn(0) + src = null //if src is deleted, still process the syringe + for(var/i=0, i<6, i++) + if(!mechsyringe) + break + if(step_towards(mechsyringe,trg)) + var/list/mobs = new + for(var/mob/living/carbon/M in mechsyringe.loc) + mobs += M + var/mob/living/carbon/M = safepick(mobs) + if(M) + var/R + mechsyringe.visible_message(" [M] was hit by the syringe!") + if(M.can_inject(null, 1)) + if(mechsyringe.reagents) + for(var/datum/reagent/A in mechsyringe.reagents.reagent_list) + R += A.id + " (" + R += num2text(A.volume) + ")," + mechsyringe.icon_state = initial(mechsyringe.icon_state) + mechsyringe.icon = initial(mechsyringe.icon) + mechsyringe.reagents.reaction(M, INGEST) + mechsyringe.reagents.trans_to(M, mechsyringe.reagents.total_volume) M.take_organ_damage(2) - S.visible_message(" [M] was hit by the syringe!") - break - else if(S.loc == trg) - S.icon_state = initial(S.icon_state) - S.icon = initial(S.icon) - S.update_icon() - break - else - S.icon_state = initial(S.icon_state) - S.icon = initial(S.icon) - S.update_icon() + add_logs(originaloccupant, M, "shot", "syringegun") break - sleep(1) - do_after_cooldown() - return 1 - - - Topic(href,href_list) - ..() - var/datum/topic_input/filter = new (href,href_list) - if(filter.get("toggle_mode")) - mode = !mode - update_equip_info() - return - if(filter.get("select_reagents")) - processed_reagents.len = 0 - var/m = 0 - var/message - for(var/i=1 to known_reagents.len) - if(m>=synth_speed) + else if(mechsyringe.loc == trg) + mechsyringe.icon_state = initial(mechsyringe.icon_state) + mechsyringe.icon = initial(mechsyringe.icon) + mechsyringe.update_icon() break - var/reagent = filter.get("reagent_[i]") - if(reagent && (reagent in known_reagents)) - message = "[m ? ", " : null][known_reagents[reagent]]" - processed_reagents += reagent - m++ - if(processed_reagents.len) - message += " added to production" - synth.start() - occupant_message(message) - occupant_message("Reagent processing started.") - log_message("Reagent processing started.") - return - if(filter.get("show_reagents")) - chassis.occupant << browse(get_reagents_page(),"window=msyringegun") - if(filter.get("purge_reagent")) - var/reagent = filter.get("purge_reagent") - if(reagent) - reagents.del_reagent(reagent) - return - if(filter.get("purge_all")) - reagents.clear_reagents() - return - return - - proc/get_reagents_page() - var/output = {" - - Reagent Synthesizer - - - - -

Current reagents:

-
- [get_current_reagents()] -
-

Reagents production:

-
- [get_reagents_form()] -
- - - "} - return output - - proc/get_reagents_form() - var/r_list = get_reagents_list() - var/inputs - if(r_list) - inputs += "" - inputs += "" - inputs += "" - var/output = {"
- [r_list || "No known reagents"] - [inputs] -
- [r_list? "Only the first [synth_speed] selected reagent\s will be added to production" : null] - "} - return output - - proc/get_reagents_list() - var/output - for(var/i=1 to known_reagents.len) - var/reagent_id = known_reagents[i] - output += {" [known_reagents[reagent_id]]
"} - return output - - proc/get_current_reagents() - var/output - for(var/datum/reagent/R in reagents.reagent_list) - if(R.volume > 0) - output += "[R]: [round(R.volume,0.001)] - Purge Reagent
" - if(output) - output += "Total: [round(reagents.total_volume,0.001)]/[reagents.maximum_volume] - Purge All" - return output || "None" - - proc/load_syringe(obj/item/weapon/reagent_containers/syringe/S) - if(syringes.len= 2) - occupant_message("The syringe is too far away.") - return 0 - for(var/obj/structure/D in S.loc)//Basic level check for structures in the way (Like grilles and windows) - if(!(D.CanPass(S,src.loc))) - occupant_message("Unable to load syringe.") - return 0 - for(var/obj/machinery/door/D in S.loc)//Checks for doors - if(!(D.CanPass(S,src.loc))) - occupant_message("Unable to load syringe.") - return 0 - S.reagents.trans_to(src, S.reagents.total_volume) - S.forceMove(src) - syringes += S - occupant_message("Syringe loaded.") - update_equip_info() - return 1 - occupant_message("The [src] syringe chamber is full.") - return 0 - - proc/analyze_reagents(atom/A) - if(get_dist(src,A) >= 4) - occupant_message("The object is too far away.") - return 0 - if(!A.reagents || istype(A,/mob)) - occupant_message("No reagent info gained from [A].") - return 0 - occupant_message("Analyzing reagents...") - for(var/datum/reagent/R in A.reagents.reagent_list) - if(R.reagent_state == 2 && add_known_reagent(R.id,R.name)) - occupant_message("Reagent analyzed, identified as [R.name] and added to database.") - send_byjax(chassis.occupant,"msyringegun.browser","reagents_form",get_reagents_form()) - occupant_message("Analyzis complete.") - return 1 - - proc/add_known_reagent(r_id,r_name) - set_ready_state(0) - do_after_cooldown() - if(!(r_id in known_reagents)) - known_reagents += r_id - known_reagents[r_id] = r_name - return 1 - return 0 + else + mechsyringe.icon_state = initial(mechsyringe.icon_state) + mechsyringe.icon = initial(mechsyringe.icon) + mechsyringe.update_icon() + break + sleep(1) + return 1 - update_equip_info() - if(..()) - send_byjax(chassis.occupant,"msyringegun.browser","reagents",get_current_reagents()) - send_byjax(chassis.occupant,"msyringegun.browser","reagents_form",get_reagents_form()) - return 1 - return - - on_reagent_change() - ..() +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/Topic(href,href_list) + ..() + var/datum/topic_input/filter = new (href,href_list) + if(filter.get("toggle_mode")) + mode = !mode update_equip_info() return + if(filter.get("select_reagents")) + processed_reagents.len = 0 + var/m = 0 + var/message + for(var/i=1 to known_reagents.len) + if(m>=synth_speed) + break + var/reagent = filter.get("reagent_[i]") + if(reagent && (reagent in known_reagents)) + message = "[m ? ", " : null][known_reagents[reagent]]" + processed_reagents += reagent + m++ + if(processed_reagents.len) + message += " added to production" + processing_objects.Add(src) + occupant_message(message) + occupant_message("Reagent processing started.") + log_message("Reagent processing started.") + return + if(filter.get("show_reagents")) + chassis.occupant << browse(get_reagents_page(),"window=msyringegun") + if(filter.get("purge_reagent")) + var/reagent = filter.get("purge_reagent") + if(reagent) + reagents.del_reagent(reagent) + return + if(filter.get("purge_all")) + reagents.clear_reagents() + return + return -/datum/global_iterator/mech_synth - delay = 100 +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/get_reagents_page() + var/output = {" + + Reagent Synthesizer + + + + +

Current reagents:

+
+ [get_current_reagents()] +
+

Reagents production:

+
+ [get_reagents_form()] +
+ + + "} + return output - process(var/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun/S) - if(!S.chassis) - return stop() - var/energy_drain = S.energy_drain*10 - if(!S.processed_reagents.len || S.reagents.total_volume >= S.reagents.maximum_volume || !S.chassis.has_charge(energy_drain)) - S.occupant_message("Reagent processing stopped.") - S.log_message("Reagent processing stopped.") - return stop() - if(anyprob(S.reliability)) - S.critfail() - var/amount = S.synth_speed / S.processed_reagents.len - for(var/reagent in S.processed_reagents) - S.reagents.add_reagent(reagent,amount) - S.chassis.use_power(energy_drain) +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/get_reagents_form() + var/r_list = get_reagents_list() + var/inputs + if(r_list) + inputs += "" + inputs += "" + inputs += "" + var/output = {"
+ [r_list || "No known reagents"] + [inputs] +
+ [r_list? "Only the first [synth_speed] selected reagent\s will be added to production" : null] + "} + return output + +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/get_reagents_list() + var/output + for(var/i=1 to known_reagents.len) + var/reagent_id = known_reagents[i] + output += {" [known_reagents[reagent_id]]
"} + return output + +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/get_current_reagents() + var/output + for(var/datum/reagent/R in reagents.reagent_list) + if(R.volume > 0) + output += "[R]: [round(R.volume,0.001)] - Purge Reagent
" + if(output) + output += "Total: [round(reagents.total_volume,0.001)]/[reagents.maximum_volume] - Purge All" + return output || "None" + +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/load_syringe(obj/item/weapon/reagent_containers/syringe/S) + if(syringes.len= 2) + occupant_message("The syringe is too far away.") + return 0 + for(var/obj/structure/D in S.loc)//Basic level check for structures in the way (Like grilles and windows) + if(!(D.CanPass(S,src.loc))) + occupant_message("Unable to load syringe.") + return 0 + for(var/obj/machinery/door/D in S.loc)//Checks for doors + if(!(D.CanPass(S,src.loc))) + occupant_message("Unable to load syringe.") + return 0 + S.reagents.trans_to(src, S.reagents.total_volume) + S.forceMove(src) + syringes += S + occupant_message("Syringe loaded.") + update_equip_info() return 1 + occupant_message("The [src] syringe chamber is full.") + return 0 + +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/analyze_reagents(atom/A) + if(get_dist(src,A) >= 4) + occupant_message("The object is too far away.") + return 0 + if(!A.reagents || istype(A,/mob)) + occupant_message("No reagent info gained from [A].") + return 0 + occupant_message("Analyzing reagents...") + for(var/datum/reagent/R in A.reagents.reagent_list) + if(R.reagent_state == 2 && add_known_reagent(R.id,R.name)) + occupant_message("Reagent analyzed, identified as [R.name] and added to database.") + send_byjax(chassis.occupant,"msyringegun.browser","reagents_form",get_reagents_form()) + occupant_message("Analyzis complete.") + return 1 + +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/proc/add_known_reagent(r_id,r_name) + if(!(r_id in known_reagents)) + known_reagents += r_id + known_reagents[r_id] = r_name + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/update_equip_info() + if(..()) + send_byjax(chassis.occupant,"msyringegun.browser","reagents",get_current_reagents()) + send_byjax(chassis.occupant,"msyringegun.browser","reagents_form",get_reagents_form()) + return 1 + return + +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/on_reagent_change() + ..() + update_equip_info() + return + + +/obj/item/mecha_parts/mecha_equipment/medical/syringe_gun/process() + if(..()) + return + if(!processed_reagents.len || reagents.total_volume >= reagents.maximum_volume || !chassis.has_charge(energy_drain)) + occupant_message("Reagent processing stopped.") + log_message("Reagent processing stopped.") + processing_objects.Remove(src) + return + var/amount = synth_speed / processed_reagents.len + for(var/reagent in processed_reagents) + reagents.add_reagent(reagent,amount) + chassis.use_power(energy_drain) + diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm new file mode 100644 index 00000000000..4f7211282c9 --- /dev/null +++ b/code/game/mecha/equipment/tools/mining_tools.dm @@ -0,0 +1,136 @@ +// Drill, Diamond drill, Mining scanner + +/obj/item/mecha_parts/mecha_equipment/drill + name = "exosuit drill" + desc = "Equipment for engineering and combat exosuits. This is the drill that'll pierce the heavens!" + icon_state = "mecha_drill" + equip_cooldown = 30 + energy_drain = 10 + force = 15 + +/obj/item/mecha_parts/mecha_equipment/drill/action(atom/target) + if(!action_checks(target)) + return + if(istype(target, /turf/space)) + return + if(isobj(target)) + var/obj/target_obj = target + if(target_obj.unacidable) + return + target.visible_message("[chassis] starts to drill [target].", + "[chassis] starts to drill [target]...", + blind_message = "You hear drilling.") + if(do_after_cooldown(target)) + if(isturf(target)) + var/turf/T = target + T.drill_act(src) + else + log_message("Drilled through [target]") + if(isliving(target)) + if(istype(src , /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill)) + drill_mob(target, chassis.occupant, 120) + else + drill_mob(target, chassis.occupant) + else + target.ex_act(2) + +/turf/proc/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill) + return + +/turf/simulated/floor/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill) + ex_act(1) + +/turf/simulated/wall/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill) + ex_act(2) + +/turf/simulated/wall/r_wall/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill) + if(istype(drill, /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill)) + if(drill.do_after_cooldown(src))//To slow down how fast mechs can drill through the station + drill.log_message("Drilled through [src]") + ex_act(3) + else + drill.occupant_message("[src] is too durable to drill through.") + +/turf/simulated/mineral/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill) + for(var/turf/simulated/mineral/M in range(drill.chassis, 1)) + if(get_dir(drill.chassis, M) & drill.chassis.dir) + M.gets_drilled() + drill.log_message("Drilled through [src]") + drill.move_ores() + +/turf/simulated/floor/plating/airless/asteroid/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill) + if(istype(drill, /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill)) + for(var/turf/simulated/floor/plating/airless/asteroid/M in range(1, src)) + M.gets_drilled() + else + for(var/turf/simulated/floor/plating/airless/asteroid/M in range(1, drill.chassis)) + if(get_dir(drill.chassis, M) & drill.chassis.dir) + M.gets_drilled() + drill.log_message("Drilled through [src]") + drill.move_ores() + +/obj/item/mecha_parts/mecha_equipment/drill/proc/move_ores() + if(locate(/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp) in chassis.equipment) + var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo + if(ore_box) + for(var/obj/item/weapon/ore/ore in range(1, chassis)) + if(get_dir(chassis, ore) & chassis.dir) + ore.Move(ore_box) + +/obj/item/mecha_parts/mecha_equipment/drill/can_attach(obj/mecha/M) + if(..()) + if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/drill/proc/drill_mob(mob/living/target, mob/user, var/drill_damage=80) + target.visible_message("[chassis] drills [target] with [src].", \ + "[chassis] drills [target] with [src].") + add_logs(user, target, "attacked", "[name]", "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(damtype)])") + if(target.stat == DEAD && target.butcher_results) + target.harvest(chassis) // Butcher the mob with our drill. + else + target.take_organ_damage(drill_damage) + + if(target) + target.Paralyse(10) + target.updatehealth() + + +/obj/item/mecha_parts/mecha_equipment/drill/diamonddrill + name = "diamond-tipped exosuit drill" + desc = "Equipment for engineering and combat exosuits. This is an upgraded version of the drill that'll pierce the heavens!" + icon_state = "mecha_diamond_drill" + origin_tech = "materials=4;engineering=4" + equip_cooldown = 20 + force = 15 + + +/obj/item/mecha_parts/mecha_equipment/mining_scanner + name = "exosuit mining scanner" + desc = "Equipment for engineering and combat exosuits. It will automatically check surrounding rock for useful minerals." + icon_state = "mecha_analyzer" + origin_tech = "materials=3;engineering=2" + selectable = 0 + equip_cooldown = 30 + var/scanning = 0 + +/obj/item/mecha_parts/mecha_equipment/mining_scanner/New() + processing_objects.Add(src) + +/obj/item/mecha_parts/mecha_equipment/mining_scanner/process() + if(!loc) + processing_objects.Remove(src) + qdel(src) + if(scanning) + return + if(istype(loc,/obj/mecha/working)) + var/obj/mecha/working/mecha = loc + if(!mecha.occupant) + return + var/list/occupant = list() + occupant |= mecha.occupant + scanning = 1 + mineral_scan_pulse(occupant,get_turf(loc)) + spawn(equip_cooldown) + scanning = 0 diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm new file mode 100644 index 00000000000..e57ee9ba8a2 --- /dev/null +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -0,0 +1,494 @@ +// Teleporter, Wormhole generator, Gravitational catapult, Armor booster modules, +// Repair droid, Tesla Energy relay, Generators + +////////////////////////////////////////////// TELEPORTER /////////////////////////////////////////////// + +/obj/item/mecha_parts/mecha_equipment/teleporter + name = "mounted teleporter" + desc = "An exosuit module that allows exosuits to teleport to any position in view." + icon_state = "mecha_teleport" + origin_tech = "bluespace=10" + equip_cooldown = 150 + energy_drain = 1000 + range = RANGED + +/obj/item/mecha_parts/mecha_equipment/teleporter/action(atom/target) + if(!action_checks(target) || !is_teleport_allowed(loc.z)) + return + var/turf/T = get_turf(target) + if(T) + do_teleport(chassis, T, 4) + return 1 + + + +////////////////////////////////////////////// WORMHOLE GENERATOR ////////////////////////////////////////// + +/obj/item/mecha_parts/mecha_equipment/wormhole_generator + name = "mounted wormhole generator" + desc = "An exosuit module that allows generating of small quasi-stable wormholes." + icon_state = "mecha_wholegen" + origin_tech = "bluespace=3" + equip_cooldown = 50 + energy_drain = 300 + range = RANGED + +/obj/item/mecha_parts/mecha_equipment/wormhole_generator/action(atom/target) + if(!action_checks(target) || !is_teleport_allowed(loc.z)) + return + var/list/theareas = get_areas_in_range(100, chassis) + if(!theareas.len) + return + var/area/thearea = pick(theareas) + var/list/L = list() + var/turf/pos = get_turf(src) + for(var/turf/T in get_area_turfs(thearea.type)) + if(!T.density && pos.z == T.z) + 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 + var/obj/effect/portal/P = new /obj/effect/portal(get_turf(target), target_turf) + P.icon = 'icons/obj/objects.dmi' + P.failchance = 0 + P.icon_state = "anom" + P.name = "wormhole" + message_admins("[key_name_admin(chassis.occupant, chassis.occupant.client)](?) (FLW) used a Wormhole Generator in ([loc.x],[loc.y],[loc.z] - JMP)",0,1) + log_game("[key_name(chassis.occupant)] used a Wormhole Generator in ([loc.x],[loc.y],[loc.z])") + src = null + spawn(rand(150,300)) + qdel(P) + return 1 + +/////////////////////////////////////// GRAVITATIONAL CATAPULT /////////////////////////////////////////// + +/obj/item/mecha_parts/mecha_equipment/gravcatapult + name = "mounted gravitational catapult" + desc = "An exosuit mounted Gravitational Catapult." + icon_state = "mecha_teleport" + origin_tech = "bluespace=2;magnets=3" + equip_cooldown = 10 + energy_drain = 100 + range = MELEE|RANGED + var/atom/movable/locked + var/mode = 1 //1 - gravsling 2 - gravpush + +/obj/item/mecha_parts/mecha_equipment/gravcatapult/action(atom/movable/target) + if(!action_checks(target)) + return + switch(mode) + if(1) + if(!locked) + if(!istype(target) || target.anchored) + occupant_message("Unable to lock on [target]") + return + locked = target + occupant_message("Locked on [target]") + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",get_equip_info()) + else if(target!=locked) + if(locked in view(chassis)) + locked.throw_at(target, 14, 1.5) + locked = null + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",get_equip_info()) + return 1 + else + locked = null + occupant_message("Lock on [locked] disengaged.") + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",get_equip_info()) + if(2) + var/list/atoms = list() + if(isturf(target)) + atoms = range(3, target) + else + atoms = orange(3, target) + for(var/atom/movable/A in atoms) + if(A.anchored) continue + spawn(0) + var/iter = 5-get_dist(A,target) + for(var/i=0 to iter) + step_away(A,target) + sleep(2) + var/turf/T = get_turf(target) + log_game("[chassis.occupant.ckey]([chassis.occupant]) used a Gravitational Catapult in ([T.x],[T.y],[T.z])") + return 1 + + +/obj/item/mecha_parts/mecha_equipment/gravcatapult/get_equip_info() + return "[..()] [mode==1?"([locked||"Nothing"])":null] \[S|P\]" + +/obj/item/mecha_parts/mecha_equipment/gravcatapult/Topic(href, href_list) + ..() + if(href_list["mode"]) + mode = text2num(href_list["mode"]) + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",get_equip_info()) + return + +//////////////////////////// ARMOR BOOSTER MODULES ////////////////////////////////////////////////////////// + +/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster //what is that noise? A BAWWW from TK mutants. + name = "Armor Booster Module (Close Combat Weaponry)" + desc = "Boosts exosuit armor against armed melee attacks. Requires energy to operate." + icon_state = "mecha_abooster_ccw" + origin_tech = "materials=3" + equip_cooldown = 10 + energy_drain = 50 + range = 0 + var/deflect_coeff = 1.15 + var/damage_coeff = 0.8 + selectable = 0 + +/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/proc/attack_react(mob/user as mob) + if(action_checks(user)) + start_cooldown() + return 1 + + +/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster + name = "Armor Booster Module (Ranged Weaponry)" + desc = "Boosts exosuit armor against ranged attacks. Completely blocks taser shots. Requires energy to operate." + icon_state = "mecha_abooster_proj" + origin_tech = "materials=4" + equip_cooldown = 10 + energy_drain = 50 + range = 0 + var/deflect_coeff = 1.15 + var/damage_coeff = 0.8 + selectable = 0 + +/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/proc/projectile_react() + if(action_checks(src)) + start_cooldown() + return 1 + + +////////////////////////////////// REPAIR DROID ////////////////////////////////////////////////// + +/obj/item/mecha_parts/mecha_equipment/repair_droid + name = "Repair Droid" + desc = "Automated repair droid. Scans exosuit for damage and repairs it. Can fix almost all types of external or internal damage." + icon_state = "repair_droid" + origin_tech = "magnets=3;programming=3" + equip_cooldown = 20 + energy_drain = 100 + range = 0 + var/health_boost = 1 + var/icon/droid_overlay + var/list/repairable_damage = list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH) + selectable = 0 + +/obj/item/mecha_parts/mecha_equipment/repair_droid/Destroy() + processing_objects.Remove(src) + if(chassis) + chassis.overlays -= droid_overlay + return ..() + +/obj/item/mecha_parts/mecha_equipment/repair_droid/attach(obj/mecha/M) + ..() + droid_overlay = new(icon, icon_state = "repair_droid") + M.overlays += droid_overlay + +/obj/item/mecha_parts/mecha_equipment/repair_droid/detach() + chassis.overlays -= droid_overlay + processing_objects.Remove(src) + +/obj/item/mecha_parts/mecha_equipment/repair_droid/get_equip_info() + if(!chassis) return + return "*  [name] - [equip_ready?"A":"Dea"]ctivate" + + +/obj/item/mecha_parts/mecha_equipment/repair_droid/Topic(href, href_list) + ..() + if(href_list["toggle_repairs"]) + chassis.overlays -= droid_overlay + if(equip_ready) + processing_objects.Add(src) + droid_overlay = new(icon, icon_state = "repair_droid_a") + log_message("Activated.") + set_ready_state(0) + else + processing_objects.Remove(src) + droid_overlay = new(icon, icon_state = "repair_droid") + log_message("Deactivated.") + set_ready_state(1) + chassis.overlays += droid_overlay + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",get_equip_info()) + + +/obj/item/mecha_parts/mecha_equipment/repair_droid/process() + if(!chassis) + processing_objects.Remove(src) + set_ready_state(1) + return + var/h_boost = health_boost + var/repaired = 0 + if(chassis.internal_damage & MECHA_INT_SHORT_CIRCUIT) + h_boost *= -2 + else if(chassis.internal_damage && prob(15)) + for(var/int_dam_flag in repairable_damage) + if(chassis.internal_damage & int_dam_flag) + chassis.clearInternalDamage(int_dam_flag) + repaired = 1 + break + if(health_boost<0 || chassis.health < initial(chassis.health)) + chassis.health += min(health_boost, initial(chassis.health)-chassis.health) + repaired = 1 + if(repaired) + if(!chassis.use_power(energy_drain)) + processing_objects.Remove(src) + set_ready_state(1) + else //no repair needed, we turn off + processing_objects.Remove(src) + set_ready_state(1) + chassis.overlays -= droid_overlay + droid_overlay = new(icon, icon_state = "repair_droid") + chassis.overlays += droid_overlay + +/////////////////////////////////// TESLA ENERGY RELAY //////////////////////////////////////////////// + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay + name = "exosuit energy relay" + desc = "An exosuit module that wirelessly drains energy from any available power channel in area. The performance index is quite low." + icon_state = "tesla" + origin_tech = "magnets=4;powerstorage=4;engineering=4" + energy_drain = 0 + range = 0 + var/coeff = 100 + var/list/use_channels = list(EQUIP,ENVIRON,LIGHT) + selectable = 0 + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/Destroy() + processing_objects.Remove(src) + return ..() + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/detach() + processing_objects.Remove(src) + ..() + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_charge() + if(equip_ready) //disabled + return + var/area/A = get_area(chassis) + var/pow_chan = get_power_channel(A) + if(pow_chan) + return 1000 //making magic + + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_power_channel(var/area/A) + var/pow_chan + if(A) + for(var/c in use_channels) + if(A.powered(c)) + pow_chan = c + break + return pow_chan + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/Topic(href, href_list) + ..() + if(href_list["toggle_relay"]) + if(equip_ready) //inactive + processing_objects.Add(src) + set_ready_state(0) + log_message("Activated.") + else + processing_objects.Remove(src) + set_ready_state(1) + log_message("Deactivated.") + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/get_equip_info() + if(!chassis) return + return "*  [name] - [equip_ready?"A":"Dea"]ctivate" + + +/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/process() + if(!chassis || chassis.internal_damage & MECHA_INT_SHORT_CIRCUIT) + processing_objects.Remove(src) + set_ready_state(1) + return + var/cur_charge = chassis.get_charge() + if(isnull(cur_charge) || !chassis.cell) + processing_objects.Remove(src) + set_ready_state(1) + occupant_message("No powercell detected.") + return + if(cur_charge < chassis.cell.maxcharge) + var/area/A = get_area(chassis) + if(A) + var/pow_chan + for(var/c in list(EQUIP,ENVIRON,LIGHT)) + if(A.powered(c)) + pow_chan = c + break + if(pow_chan) + var/delta = min(20, chassis.cell.maxcharge-cur_charge) + chassis.give_power(delta) + A.use_power(delta*coeff, pow_chan) + +/////////////////////////////////////////// GENERATOR ///////////////////////////////////////////// + +/obj/item/mecha_parts/mecha_equipment/generator + name = "exosuit plasma converter" + desc = "An exosuit module that generates power using solid plasma as fuel. Pollutes the environment." + icon_state = "tesla" + origin_tech = "plasmatech=2;powerstorage=2;engineering=2" + range = MELEE + var/coeff = 100 + var/fuel_type = MAT_PLASMA + var/max_fuel = 150000 + var/fuel_name = "plasma" // Our fuel name as a string + var/fuel_amount = 0 + var/fuel_per_cycle_idle = 10 + var/fuel_per_cycle_active = 100 + var/power_per_cycle = 30 + +/obj/item/mecha_parts/mecha_equipment/generator/New() + ..() + generator_init() + +/obj/item/mecha_parts/mecha_equipment/generator/Destroy() + processing_objects.Remove(src) + return ..() + +/obj/item/mecha_parts/mecha_equipment/generator/proc/generator_init() + fuel_amount = 0 + +/obj/item/mecha_parts/mecha_equipment/generator/detach() + processing_objects.Remove(src) + ..() + +/obj/item/mecha_parts/mecha_equipment/generator/Topic(href, href_list) + ..() + if(href_list["toggle"]) + if(equip_ready) //inactive + set_ready_state(0) + processing_objects.Add(src) + log_message("Activated.") + else + set_ready_state(1) + processing_objects.Remove(src) + log_message("Deactivated.") + +/obj/item/mecha_parts/mecha_equipment/generator/get_equip_info() + var/output = ..() + if(output) + return "[output] \[[fuel_name]: [round(fuel_amount,0.1)] cm3\] - [equip_ready?"A":"Dea"]ctivate" + +/obj/item/mecha_parts/mecha_equipment/generator/action(target) + if(chassis) + var/result = load_fuel(target) + if(result) + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",get_equip_info()) + +/obj/item/mecha_parts/mecha_equipment/generator/proc/load_fuel(var/obj/item/I) + if(istype(I) && (fuel_type in I.materials)) + if(istype(I, /obj/item/stack/sheet)) + var/obj/item/stack/sheet/P = I + var/to_load = max(max_fuel - P.amount*P.perunit,0) + if(to_load) + var/units = min(max(round(to_load / P.perunit),1),P.amount) + if(units) + var/added_fuel = units * P.perunit + fuel_amount += added_fuel + P.use(units) + occupant_message("[units] unit\s of [fuel_name] successfully loaded.") + return added_fuel + else + occupant_message("Unit is full.") + return 0 + else // Some other object containing our fuel's type, so we just eat it (ores mainly) + var/to_load = max(min(I.materials[fuel_type], max_fuel - fuel_amount),0) + if(to_load == 0) + return 0 + fuel_amount += to_load + qdel(I) + return to_load + + else if(istype(I, /obj/structure/ore_box)) + var/fuel_added = 0 + for(var/baz in I.contents) + var/obj/item/O = baz + if(fuel_type in O.materials) + fuel_added = load_fuel(O) + break + return fuel_added + + else + occupant_message("[fuel_name] traces in target minimal! [I] cannot be used as fuel.") + return + +/obj/item/mecha_parts/mecha_equipment/generator/attackby(weapon,mob/user, params) + load_fuel(weapon) + +/obj/item/mecha_parts/mecha_equipment/generator/critfail() + ..() + var/turf/simulated/T = get_turf(src) + if(!istype(T)) + return + var/datum/gas_mixture/GM = new + if(prob(10)) + GM.toxins += 100 + GM.temperature = 1500+T0C //should be enough to start a fire + T.visible_message("[src] suddenly disgorges a cloud of heated plasma.") + qdel(src) + else + GM.toxins += 5 + GM.temperature = istype(T) ? T.air.return_temperature() : T20C + T.visible_message("[src] suddenly disgorges a cloud of plasma.") + T.assume_air(GM) + +/obj/item/mecha_parts/mecha_equipment/generator/process() + if(!chassis) + processing_objects.Remove(src) + set_ready_state(1) + return + if(fuel_amount<=0) + processing_objects.Remove(src) + log_message("Deactivated - no fuel.") + set_ready_state(1) + return + var/cur_charge = chassis.get_charge() + if(isnull(cur_charge)) + set_ready_state(1) + occupant_message("No powercell detected.") + log_message("Deactivated.") + processing_objects.Remove(src) + return + var/use_fuel = fuel_per_cycle_idle + if(cur_charge < chassis.cell.maxcharge) + use_fuel = fuel_per_cycle_active + chassis.give_power(power_per_cycle) + fuel_amount -= min(use_fuel, fuel_amount) + update_equip_info() + return 1 + + +/obj/item/mecha_parts/mecha_equipment/generator/nuclear + name = "exonuclear reactor" + desc = "An exosuit module that generates power using uranium as fuel. Pollutes the environment." + icon_state = "tesla" + origin_tech = "powerstorage=4;engineering=4" + fuel_name = "uranium" // Our fuel name as a string + fuel_type = MAT_URANIUM + max_fuel = 50000 + fuel_per_cycle_idle = 10 + fuel_per_cycle_active = 30 + power_per_cycle = 50 + var/rad_per_cycle = 0.3 + +/obj/item/mecha_parts/mecha_equipment/generator/nuclear/generator_init() + fuel_amount = 0 + +/obj/item/mecha_parts/mecha_equipment/generator/nuclear/critfail() + return + +/obj/item/mecha_parts/mecha_equipment/generator/nuclear/process() + if(..()) + for(var/mob/living/carbon/M in view(chassis)) + M.apply_effect((rad_per_cycle * 3),IRRADIATE,0) \ No newline at end of file diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm deleted file mode 100644 index d945e1cbb7f..00000000000 --- a/code/game/mecha/equipment/tools/tools.dm +++ /dev/null @@ -1,1147 +0,0 @@ -/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp - name = "Hydraulic Clamp" - icon_state = "mecha_clamp" - equip_cooldown = 15 - energy_drain = 10 - var/dam_force = 20 - var/obj/mecha/working/ripley/cargo_holder - - can_attach(obj/mecha/working/ripley/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 - - attach(obj/mecha/M as obj) - ..() - cargo_holder = M - return - - action(atom/target) - if(!action_checks(target)) return - if(!cargo_holder) return - if(istype(target, /obj/structure/stool)) return - - if(istype(target,/obj)) - var/obj/O = target - if(!O.anchored) - if(cargo_holder.cargo.len < cargo_holder.cargo_capacity) - 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.") - set_ready_state(0) - chassis.use_power(energy_drain) - O.anchored = 1 - var/T = chassis.loc - if(do_after_cooldown(target)) - if(T == chassis.loc && src == chassis.selected) - cargo_holder.cargo += O - O.loc = chassis - O.anchored = 0 - occupant_message("[target] succesfully loaded.") - log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]") - else - occupant_message("You must hold still while handling objects.") - O.anchored = initial(O.anchored) - else - occupant_message("Not enough room in cargo compartment.") - else - occupant_message("[target] is firmly secured.") - - else if(istype(target,/mob/living)) - var/mob/living/M = target - if(M.stat>1) return - if(chassis.occupant.a_intent == I_HARM) - M.take_overall_damage(dam_force) - M.adjustOxyLoss(round(dam_force/2)) - M.updatehealth() - occupant_message("\red You squeeze [target] with [src.name]. Something cracks.") - chassis.visible_message("\red [chassis] squeezes [target].") - else - step_away(M,chassis) - occupant_message("You push [target] out of the way.") - chassis.visible_message("[chassis] pushes [target] out of the way.") - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/drill - name = "Drill" - desc = "This is the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)" - icon_state = "mecha_drill" - equip_cooldown = 30 - energy_drain = 10 - force = 15 - - action(atom/target) - if(!action_checks(target)) return - if(isobj(target)) - var/obj/target_obj = target - if(!target_obj.vars.Find("unacidable") || target_obj.unacidable) return - set_ready_state(0) - chassis.use_power(energy_drain) - chassis.visible_message("[chassis] starts to drill [target]", "You hear the drill.") - occupant_message("You start to drill [target]") - var/T = chassis.loc - var/C = target.loc //why are these backwards? we may never know -Pete - if(do_after_cooldown(target)) - if(T == chassis.loc && src == chassis.selected) - if(istype(target, /turf/simulated/wall/r_wall)) - occupant_message("[target] is too durable to drill through.") - else if(istype(target, /turf/simulated/mineral)) - for(var/turf/simulated/mineral/M in range(chassis,1)) - if(get_dir(chassis,M)&chassis.dir) - M.gets_drilled() - log_message("Drilled through [target]") - if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) - var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo - if(ore_box) - for(var/obj/item/weapon/ore/ore in range(chassis,1)) - if(get_dir(chassis,ore)&chassis.dir) - ore.Move(ore_box) - else if(istype(target, /turf/simulated/floor/plating/airless/asteroid)) - for(var/turf/simulated/floor/plating/airless/asteroid/M in range(chassis,1)) - if(get_dir(chassis,M)&chassis.dir) - M.gets_drilled() - log_message("Drilled through [target]") - if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) - var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo - if(ore_box) - for(var/obj/item/weapon/ore/ore in range(chassis,1)) - if(get_dir(chassis,ore)&chassis.dir) - ore.Move(ore_box) - else if(target.loc == C) - if(istype(target, /mob/living)) - var/mob/living/M = target - M.attack_log +="\[[time_stamp()]\] Mech Drilled by [chassis.occupant.name] ([chassis.occupant.ckey]) with [src.name]" - chassis.occupant.attack_log += "\[[time_stamp()]\] Mech Drilled [M.name] ([M.ckey]) with [src.name]" - log_attack("[chassis.occupant.name] ([chassis.occupant.ckey]) mech drilled [M.name] ([M.ckey]) with [src.name]" ) - if(!iscarbon(chassis.occupant)) - M.LAssailant = null - else - M.LAssailant = chassis.occupant - log_message("Drilled through [target]") - target.ex_act(2) - return 1 - - can_attach(obj/mecha/M as obj) - if(..()) - if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill - name = "Diamond Drill" - desc = "This is an upgraded version of the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)" - icon_state = "mecha_diamond_drill" - origin_tech = "materials=4;engineering=3" - equip_cooldown = 20 - force = 15 - - action(atom/target) - if(!action_checks(target)) return - if(isobj(target)) - var/obj/target_obj = target - if(target_obj.unacidable) return - set_ready_state(0) - chassis.use_power(energy_drain) - chassis.visible_message("[chassis] starts to drill [target]", "You hear the drill.") - occupant_message("You start to drill [target]") - var/T = chassis.loc - var/C = target.loc //why are these backwards? we may never know -Pete - if(do_after_cooldown(target)) - if(T == chassis.loc && src == chassis.selected) - if(istype(target, /turf/simulated/wall/r_wall)) - if(do_after_cooldown(target))//To slow down how fast mechs can drill through the station - log_message("Drilled through [target]") - target.ex_act(3) - else if(istype(target, /turf/simulated/mineral)) - for(var/turf/simulated/mineral/M in range(chassis,1)) - if(get_dir(chassis,M)&chassis.dir) - M.gets_drilled() - log_message("Drilled through [target]") - if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) - var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo - if(ore_box) - for(var/obj/item/weapon/ore/ore in range(chassis,1)) - if(get_dir(chassis,ore)&chassis.dir) - ore.Move(ore_box) - else if(istype(target,/turf/simulated/floor/plating/airless/asteroid)) - for(var/turf/simulated/floor/plating/airless/asteroid/M in range(target,1)) - M.gets_drilled() - log_message("Drilled through [target]") - if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) - var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo - if(ore_box) - for(var/obj/item/weapon/ore/ore in range(target,1)) - ore.Move(ore_box) - else if(target.loc == C) - if(istype(target, /mob/living)) - var/mob/living/M = target - M.attack_log +="\[[time_stamp()]\] Mech Drilled by [chassis.occupant.name] ([chassis.occupant.ckey]) with [src.name]" - chassis.occupant.attack_log += "\[[time_stamp()]\] Mech Drilled [M.name] ([M.ckey]) with [src.name]" - log_attack("[chassis.occupant.name] ([chassis.occupant.ckey]) mech drilled [M.name] ([M.ckey]) with [src.name]" ) - if(!iscarbon(chassis.occupant)) - M.LAssailant = null - else - M.LAssailant = chassis.occupant - log_message("Drilled through [target]") - target.ex_act(2) - return 1 - - can_attach(obj/mecha/M as obj) - if(..()) - if(istype(M, /obj/mecha/working) || istype(M, /obj/mecha/combat)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/extinguisher - name = "Extinguisher" - desc = "Exosuit-mounted extinguisher (Can be attached to: Engineering exosuits)" - icon_state = "mecha_exting" - equip_cooldown = 5 - energy_drain = 0 - range = MELEE|RANGED - - New() - reagents = new/datum/reagents(1000) - reagents.my_atom = src - reagents.add_reagent("water", 1000) - ..() - return - - action(atom/target) //copypasted from extinguisher. TODO: Rewrite from scratch. - if(!action_checks(target) || get_dist(chassis, target)>3) return - if(get_dist(chassis, target)>2) return - set_ready_state(0) - if(do_after_cooldown(target)) - if(istype(target, /obj/structure/reagent_dispensers/watertank) && get_dist(chassis,target) <= 1) - var/obj/o = target - o.reagents.trans_to(src, 1000) - occupant_message("\blue Extinguisher refilled") - playsound(chassis, 'sound/effects/refill.ogg', 50, 1, -6) - else - if(src.reagents.total_volume > 0) - playsound(chassis, 'sound/effects/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) - spawn(0) - for(var/a=0, a<5, a++) - var/obj/effect/effect/water/W = new /obj/effect/effect/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<4, 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 - - can_attach(obj/mecha/working/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 - - -/obj/item/mecha_parts/mecha_equipment/tool/rcd - name = "Mounted RCD" - desc = "An exosuit-mounted Rapid Construction Device. (Can be attached to: Any exosuit)" - icon_state = "mecha_rcd" - origin_tech = "materials=4;bluespace=3;magnets=4;powerstorage=4" - equip_cooldown = 10 - energy_drain = 250 - range = MELEE|RANGED - var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock. - var/canRwall = 0 - - New() - rcd_list += src - ..() - - Destroy() - rcd_list -= src - return ..() - - action(atom/target) - if(istype(target, /turf/space/transit))//>implying these are ever made -Sieve - return - if(!istype(target, /turf) && !istype(target, /obj/machinery/door/airlock)) - target = get_turf(target) - if(!action_checks(target) || get_dist(chassis, target)>3) return - playsound(chassis, 'sound/machines/click.ogg', 50, 1) - //meh - switch(mode) - if(0) - if(istype(target, /turf/simulated/wall)) - if(istype(target, /turf/simulated/wall/r_wall) && !canRwall) - return 0 - occupant_message("Deconstructing [target]...") - set_ready_state(0) - if(do_after_cooldown(target)) - chassis.spark_system.start() - target:ChangeTurf(/turf/simulated/floor/plating) - playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) - chassis.use_power(energy_drain) - else if(istype(target, /turf/simulated/floor)) - occupant_message("Deconstructing [target]...") - set_ready_state(0) - if(do_after_cooldown(target)) - chassis.spark_system.start() - target:ChangeTurf(/turf/space) - playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) - chassis.use_power(energy_drain) - else if(istype(target, /obj/machinery/door/airlock)) - occupant_message("Deconstructing [target]...") - set_ready_state(0) - if(do_after_cooldown(target)) - chassis.spark_system.start() - qdel(target) - playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) - chassis.use_power(energy_drain) - if(1) - if(istype(target, /turf/space)) - occupant_message("Building Floor...") - set_ready_state(0) - if(do_after_cooldown(target)) - target:ChangeTurf(/turf/simulated/floor/plating) - playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) - chassis.spark_system.start() - chassis.use_power(energy_drain*2) - else if(istype(target, /turf/simulated/floor)) - occupant_message("Building Wall...") - set_ready_state(0) - if(do_after_cooldown(target)) - target:ChangeTurf(/turf/simulated/wall) - playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) - chassis.spark_system.start() - chassis.use_power(energy_drain*2) - if(2) - if(istype(target, /turf/simulated/floor)) - occupant_message("Building Airlock...") - set_ready_state(0) - if(do_after_cooldown(target)) - chassis.spark_system.start() - var/obj/machinery/door/airlock/T = new /obj/machinery/door/airlock(target) - T.autoclose = 1 - playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) - playsound(target, 'sound/effects/sparks2.ogg', 50, 1) - chassis.use_power(energy_drain*2) - return - - - Topic(href,href_list) - ..() - if(href_list["mode"]) - mode = text2num(href_list["mode"]) - switch(mode) - if(0) - occupant_message("Switched RCD to Deconstruct.") - if(1) - occupant_message("Switched RCD to Construct.") - if(2) - occupant_message("Switched RCD to Construct Airlock.") - return - - get_equip_info() - return "[..()] \[D|C|A\]" - - - - -/obj/item/mecha_parts/mecha_equipment/teleporter - name = "Teleporter" - desc = "An exosuit module that allows exosuits to teleport to any position in view." - icon_state = "mecha_teleport" - origin_tech = "bluespace=10" - equip_cooldown = 150 - energy_drain = 1000 - range = RANGED - - action(atom/target) - if(!action_checks(target) || !is_teleport_allowed(src.loc.z)) return - var/turf/T = get_turf(target) - if(T) - set_ready_state(0) - chassis.use_power(energy_drain) - do_teleport(chassis, T, 4) - do_after_cooldown() - return - - -/obj/item/mecha_parts/mecha_equipment/wormhole_generator - name = "Wormhole Generator" - desc = "An exosuit module that allows generating of small quasi-stable wormholes." - icon_state = "mecha_wholegen" - origin_tech = "bluespace=3" - equip_cooldown = 50 - energy_drain = 300 - range = RANGED - - - action(atom/target) - if(!action_checks(target) || !is_teleport_allowed(src.loc.z)) 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() - var/turf/pos = get_turf(src) - for(var/turf/T in get_area_turfs(thearea.type)) - if(!T.density && pos.z == T.z) - 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.use_power(energy_drain) - set_ready_state(0) - var/obj/effect/portal/P = new /obj/effect/portal(get_turf(target), target_turf) - P.icon = 'icons/obj/objects.dmi' - P.failchance = 0 - P.icon_state = "anom" - P.name = "wormhole" - message_admins("[key_name_admin(chassis.occupant, chassis.occupant.client)](?) (FLW) used a Wormhole Generator in ([loc.x],[loc.y],[loc.z] - JMP)",0,1) - log_game("[key_name(chassis.occupant)] used a Wormhole Generator in ([loc.x],[loc.y],[loc.z])") - do_after_cooldown() - src = null - spawn(rand(150,300)) - qdel(P) - return - -/obj/item/mecha_parts/mecha_equipment/gravcatapult - name = "Gravitational Catapult" - desc = "An exosuit mounted Gravitational Catapult." - icon_state = "mecha_teleport" - origin_tech = "bluespace=2;magnets=3" - equip_cooldown = 10 - energy_drain = 100 - range = MELEE|RANGED - var/atom/movable/locked - var/mode = 1 //1 - gravsling 2 - gravpush - - - action(atom/movable/target) - switch(mode) - if(1) - if(!action_checks(target) && !locked) return - if(!locked) - if(!istype(target) || target.anchored) - occupant_message("Unable to lock on [target]") - return - locked = target - occupant_message("Locked on [target]") - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - return - else if(target!=locked) - if(locked in view(chassis)) - locked.throw_at(target, 14, 1.5, chassis) - locked = null - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - else - locked = null - occupant_message("Lock on [locked] disengaged.") - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - if(2) - if(!action_checks(target)) return - var/list/atoms = list() - if(isturf(target)) - atoms = range(target,3) - else - atoms = orange(target,3) - for(var/atom/movable/A in atoms) - if(A.anchored) continue - spawn(0) - var/iter = 5-get_dist(A,target) - for(var/i=0 to iter) - step_away(A,target) - sleep(2) - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - return - - get_equip_info() - return "[..()] [mode==1?"([locked||"Nothing"])":null] \[S|P\]" - - Topic(href, href_list) - ..() - if(href_list["mode"]) - mode = text2num(href_list["mode"]) - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - return - - -/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster //what is that noise? A BAWWW from TK mutants. - name = "Armor Booster Module (Close Combat Weaponry)" - desc = "Boosts exosuit armor against armed melee attacks. Requires energy to operate." - icon_state = "mecha_abooster_ccw" - origin_tech = "materials=3" - equip_cooldown = 10 - energy_drain = 50 - range = 0 - var/deflect_coeff = 1.15 - var/damage_coeff = 0.8 - - can_attach(obj/mecha/M as obj) - if(..()) - if(!istype(M, /obj/mecha/combat/honker)) - if(!M.proc_res["dynattackby"]) - return 1 - return 0 - - attach(obj/mecha/M as obj) - ..() - chassis.proc_res["dynattackby"] = src - return - - detach() - chassis.proc_res["dynattackby"] = null - ..() - return - - get_equip_info() - if(!chassis) return - return "* [src.name]" - - proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob, params) - if(!action_checks(user)) - return chassis.dynattackby(W,user, params) - chassis.log_message("Attacked by [W]. Attacker - [user]") - if(prob(chassis.deflect_chance*deflect_coeff)) - to_chat(user, "\red The [W] bounces off [chassis] armor.") - chassis.log_append_to_last("Armor saved.") - else - chassis.occupant_message("[user] hits [chassis] with [W].") - user.visible_message("[user] hits [chassis] with [W].", "You hit [src] with [W].") - chassis.take_damage(round(W.force*damage_coeff),W.damtype) - chassis.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - return - - -/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster - name = "Armor Booster Module (Ranged Weaponry)" - desc = "Boosts exosuit armor against ranged attacks. Completely blocks taser shots. Requires energy to operate." - icon_state = "mecha_abooster_proj" - origin_tech = "materials=4" - equip_cooldown = 10 - energy_drain = 50 - range = 0 - var/deflect_coeff = 1.15 - var/damage_coeff = 0.8 - - can_attach(obj/mecha/M as obj) - if(..()) - if(!istype(M, /obj/mecha/combat/honker)) - if(!M.proc_res["dynbulletdamage"] && !M.proc_res["dynhitby"]) - return 1 - return 0 - - attach(obj/mecha/M as obj) - ..() - chassis.proc_res["dynbulletdamage"] = src - chassis.proc_res["dynhitby"] = src - return - - detach() - chassis.proc_res["dynbulletdamage"] = null - chassis.proc_res["dynhitby"] = null - ..() - return - - get_equip_info() - if(!chassis) return - return "* [src.name]" - - proc/dynbulletdamage(var/obj/item/projectile/Proj) - if(!action_checks(src)) - return chassis.dynbulletdamage(Proj) - if(prob(chassis.deflect_chance*deflect_coeff)) - chassis.occupant_message("\blue The armor deflects incoming projectile.") - chassis.visible_message("The [chassis.name] armor deflects the projectile") - chassis.log_append_to_last("Armor saved.") - else - chassis.take_damage(round(Proj.damage*src.damage_coeff),Proj.flag) - chassis.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - Proj.on_hit(chassis) - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - return - - proc/dynhitby(atom/movable/A) - if(!action_checks(A)) - return chassis.dynhitby(A) - if(prob(chassis.deflect_chance*deflect_coeff) || istype(A, /mob/living) || istype(A, /obj/item/mecha_parts/mecha_tracking)) - chassis.occupant_message("\blue The [A] bounces off the armor.") - chassis.visible_message("The [A] bounces off the [chassis] armor") - chassis.log_append_to_last("Armor saved.") - if(istype(A, /mob/living)) - var/mob/living/M = A - M.take_organ_damage(10) - else if(istype(A, /obj)) - var/obj/O = A - if(O.throwforce) - chassis.take_damage(round(O.throwforce*damage_coeff)) - chassis.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - return - - -/obj/item/mecha_parts/mecha_equipment/repair_droid - name = "Repair Droid" - desc = "Automated repair droid. Scans exosuit for damage and repairs it. Can fix almost all types of external or internal damage." - icon_state = "repair_droid" - origin_tech = "magnets=3;programming=3" - equip_cooldown = 20 - energy_drain = 100 - range = 0 - var/health_boost = 2 - var/datum/global_iterator/pr_repair_droid - var/icon/droid_overlay - var/list/repairable_damage = list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH) - - New() - ..() - pr_repair_droid = new /datum/global_iterator/mecha_repair_droid(list(src),0) - pr_repair_droid.set_delay(equip_cooldown) - return - - attach(obj/mecha/M as obj) - ..() - droid_overlay = new(src.icon, icon_state = "repair_droid") - M.overlays += droid_overlay - return - - Destroy() - chassis.overlays -= droid_overlay - return ..() - - detach() - chassis.overlays -= droid_overlay - pr_repair_droid.stop() - ..() - return - - get_equip_info() - if(!chassis) return - return "* [src.name] - [pr_repair_droid.active()?"Dea":"A"]ctivate" - - - Topic(href, href_list) - ..() - if(href_list["toggle_repairs"]) - chassis.overlays -= droid_overlay - if(pr_repair_droid.toggle()) - droid_overlay = new(src.icon, icon_state = "repair_droid_a") - log_message("Activated.") - else - droid_overlay = new(src.icon, icon_state = "repair_droid") - log_message("Deactivated.") - set_ready_state(1) - chassis.overlays += droid_overlay - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - return - - -/datum/global_iterator/mecha_repair_droid - - process(var/obj/item/mecha_parts/mecha_equipment/repair_droid/RD as obj) - if(!RD.chassis) - stop() - RD.set_ready_state(1) - return - var/health_boost = RD.health_boost - var/repaired = 0 - if(RD.chassis.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) - health_boost *= -2 - else if(RD.chassis.hasInternalDamage() && prob(15)) - for(var/int_dam_flag in RD.repairable_damage) - if(RD.chassis.hasInternalDamage(int_dam_flag)) - RD.chassis.clearInternalDamage(int_dam_flag) - repaired = 1 - break - if(health_boost<0 || RD.chassis.health < initial(RD.chassis.health)) - RD.chassis.health += min(health_boost, initial(RD.chassis.health)-RD.chassis.health) - repaired = 1 - if(repaired) - if(RD.chassis.use_power(RD.energy_drain)) - RD.set_ready_state(0) - else - stop() - RD.set_ready_state(1) - return - else - RD.set_ready_state(1) - return - - -/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay - name = "Energy Relay" - desc = "Wirelessly drains energy from any available power channel in area. The performance index is quite low." - icon_state = "tesla" - origin_tech = "magnets=4;powerstorage=3" - equip_cooldown = 10 - energy_drain = 0 - range = 0 - var/datum/global_iterator/pr_energy_relay - var/coeff = 100 - var/list/use_channels = list(EQUIP,ENVIRON,LIGHT) - - New() - ..() - pr_energy_relay = new /datum/global_iterator/mecha_energy_relay(list(src),0) - pr_energy_relay.set_delay(equip_cooldown) - return - - detach() - pr_energy_relay.stop() -// chassis.proc_res["dynusepower"] = null - chassis.proc_res["dyngetcharge"] = null - ..() - return - - attach(obj/mecha/M) - ..() - chassis.proc_res["dyngetcharge"] = src -// chassis.proc_res["dynusepower"] = src - return - - can_attach(obj/mecha/M) - if(..()) - if(!M.proc_res["dyngetcharge"])// && !M.proc_res["dynusepower"]) - return 1 - return 0 - - proc/dyngetcharge() - if(equip_ready) //disabled - return chassis.dyngetcharge() - var/area/A = get_area(chassis) - var/pow_chan = get_power_channel(A) - var/charge = 0 - if(pow_chan) - charge = 1000 //making magic - else - return chassis.dyngetcharge() - return charge - - proc/get_power_channel(var/area/A) - var/pow_chan - if(A) - for(var/c in use_channels) - if(A.powered(c)) - pow_chan = c - break - return pow_chan - - Topic(href, href_list) - ..() - if(href_list["toggle_relay"]) - if(pr_energy_relay.toggle()) - set_ready_state(0) - log_message("Activated.") - else - set_ready_state(1) - log_message("Deactivated.") - return - - get_equip_info() - if(!chassis) return - return "* [src.name] - [pr_energy_relay.active()?"Dea":"A"]ctivate" - -/* proc/dynusepower(amount) - if(!equip_ready) //enabled - var/area/A = get_area(chassis) - var/pow_chan = get_power_channel(A) - if(pow_chan) - A.master.use_power(amount*coeff, pow_chan) - return 1 - return chassis.dynusepower(amount)*/ - -/datum/global_iterator/mecha_energy_relay - - process(var/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/ER) - if(!ER.chassis || ER.chassis.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) - stop() - ER.set_ready_state(1) - return - var/cur_charge = ER.chassis.get_charge() - if(isnull(cur_charge) || !ER.chassis.cell) - stop() - ER.set_ready_state(1) - ER.occupant_message("No powercell detected.") - return - if(cur_charge3\] - [pr_mech_generator.active()?"Dea":"A"]ctivate" - return - - action(target) - if(chassis) - var/result = load_fuel(target) - var/message - if(isnull(result)) - message = "[fuel_name] traces in target minimal. [target] cannot be used as fuel." - else if(!result) - message = "Unit is full." - else - message = "[result] unit\s of [fuel_name] successfully loaded." - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - occupant_message(message) - return - - proc/load_fuel(var/obj/item/I) - if(istype(I) && (fuel_type in I.materials)) - if(istype(I, /obj/item/stack/sheet)) - var/obj/item/stack/sheet/P = I - var/to_load = max(max_fuel - P.amount*P.perunit,0) - if(to_load) - var/units = min(max(round(to_load / P.perunit),1),P.amount) - if(units) - var/added_fuel = units * P.perunit - fuel_amount += added_fuel - P.use(units) - return added_fuel - else - return 0 - else // Some other object containing our fuel's type, so we just eat it (ores mainly) - var/to_load = max(min(I.materials[fuel_type], max_fuel - fuel_amount),0) - if(to_load == 0) - return 0 - fuel_amount += to_load - qdel(I) - return to_load - else if(istype(I, /obj/structure/ore_box)) - var/fuel_added = 0 - for(var/baz in I.contents) // Istypeless loop - var/obj/item/O = baz - if(fuel_type in O.materials) - fuel_added = load_fuel(O) - break - return fuel_added - return - - attackby(weapon,mob/user, params) - var/result = load_fuel(weapon) - var/weapon_name = "[weapon]" - if(isnull(result)) - user.visible_message("[user] tries to shove [weapon_name] into [src], but \the [src] rejects it.","[fuel_name] traces in target minimal. [weapon_name] cannot be used as fuel.") - else if(!result) - to_chat(user, "Unit is full.") - else - user.visible_message("[user] loads [src] with \the [weapon_name].","[result] unit\s of [fuel_name] successfully loaded.") - return - - critfail() - ..() - var/turf/simulated/T = get_turf(src) - if(!T) - return - var/datum/gas_mixture/GM = new - if(prob(10)) - GM.toxins += 100 - GM.temperature = 1500+T0C //should be enough to start a fire - T.visible_message("The [src] suddenly disgorges a cloud of heated plasma.") - qdel(src) - else - GM.toxins += 5 - GM.temperature = istype(T) ? T.air.temperature : T20C - T.visible_message("The [src] suddenly disgorges a cloud of plasma.") - T.assume_air(GM) - return - -/datum/global_iterator/mecha_generator - - process(var/obj/item/mecha_parts/mecha_equipment/generator/EG) - if(!EG.chassis) - stop() - EG.set_ready_state(1) - return 0 - if(EG.fuel_amount<=0) - stop() - EG.log_message("Deactivated - no fuel.") - EG.set_ready_state(1) - return 0 - if(anyprob(EG.reliability)) - EG.critfail() - stop() - return 0 - var/cur_charge = EG.chassis.get_charge() - if(isnull(cur_charge)) - EG.set_ready_state(1) - EG.occupant_message("No powercell detected.") - EG.log_message("Deactivated.") - stop() - return 0 - var/use_fuel = EG.fuel_per_cycle_idle - if(cur_charge[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) - else - chassis.occupant_message("Not enough room in cargo compartment.") - else - chassis.occupant_message("[target] is firmly secured.") - - else if(istype(target,/mob/living)) - var/mob/living/M = target - if(M.stat>1) return - if(chassis.occupant.a_intent == I_HARM) - chassis.occupant_message("\red You obliterate [target] with [src.name], leaving blood and guts everywhere.") - chassis.visible_message("\red [chassis] destroys [target] in an unholy fury.") - if(chassis.occupant.a_intent == I_DISARM) - chassis.occupant_message("\red You tear [target]'s limbs off with [src.name].") - chassis.visible_message("\red [chassis] rips [target]'s arms off.") - else - step_away(M,chassis) - chassis.occupant_message("You smash into [target], sending them flying.") - chassis.visible_message("[chassis] tosses [target] like a piece of paper.") - set_ready_state(0) - chassis.use_power(energy_drain) - do_after_cooldown() - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/mining_scanner - name = "exosuit mining scanner" - desc = "Equipment for engineering and combat exosuits. It will automatically check surrounding rock for useful minerals." - icon_state = "mecha_analyzer" - origin_tech = "materials=3;engineering=2" - equip_cooldown = 30 - var/scanning = 0 - -/obj/item/mecha_parts/mecha_equipment/tool/mining_scanner/New() - processing_objects.Add(src) - -/obj/item/mecha_parts/mecha_equipment/tool/mining_scanner/process() - if(!loc) - processing_objects.Remove(src) - qdel(src) - if(scanning) - return - if(istype(loc,/obj/mecha/working)) - var/obj/mecha/working/mecha = loc - if(!mecha.occupant) - return - var/list/occupant = list() - occupant |= mecha.occupant - scanning = 1 - mineral_scan_pulse(occupant,get_turf(loc)) - spawn(equip_cooldown) - scanning = 0 - - -/obj/item/mecha_parts/mecha_equipment/tool/mimercd - name = "Mounted MRCD" - desc = "An exosuit-mounted Mime Rapid Construction Device. (Can be attached to: Recitence)" - icon_state = "mecha_rcd" - origin_tech = "materials=4;bluespace=3;magnets=4;powerstorage=4" - equip_cooldown = 10 - energy_drain = 250 - range = MELEE|RANGED - -/obj/item/mecha_parts/mecha_equipment/tool/mimercd/can_attach(obj/mecha/combat/recitence/M as obj) - if(..()) - if(istype(M)) - return 1 - return 0 - -/obj/item/mecha_parts/mecha_equipment/tool/mimercd/action(atom/target) - if(istype(target, /turf/space/transit))//>implying these are ever made -Sieve - return - if(!istype(target, /turf) && !istype(target, /obj/machinery/door/airlock)) - target = get_turf(target) - if(!action_checks(target) || get_dist(chassis, target)>3) - return - - if(istype(target, /turf/simulated/floor)) - occupant_message("Building Wall...") - set_ready_state(0) - if(do_after_cooldown(target)) - new /obj/structure/barricade/mime/mrcd(target) - chassis.spark_system.start() - chassis.use_power(energy_drain*2) diff --git a/code/game/mecha/equipment/tools/work_tools.dm b/code/game/mecha/equipment/tools/work_tools.dm new file mode 100644 index 00000000000..4ff69a0d34e --- /dev/null +++ b/code/game/mecha/equipment/tools/work_tools.dm @@ -0,0 +1,452 @@ +//Hydraulic clamp, Kill clamp, Extinguisher, RCD, Mime RCD, Cable layer. + +/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp + name = "hydraulic clamp" + desc = "Equipment for engineering exosuits. Lifts objects and loads them into cargo." + icon_state = "mecha_clamp" + equip_cooldown = 15 + energy_drain = 10 + var/dam_force = 20 + var/obj/mecha/working/ripley/cargo_holder + +/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/attach(obj/mecha/M) + ..() + cargo_holder = M + return + +/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/detach(atom/moveto = null) + ..() + cargo_holder = null + +/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/action(atom/target) + if(!action_checks(target)) + 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.visible_message("[chassis] lifts [target] and starts to load it into cargo compartment.") + O.anchored = 1 + if(do_after_cooldown(target)) + cargo_holder.cargo += O + O.loc = chassis + O.anchored = 0 + occupant_message("[target] successfully loaded.") + log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]") + else + O.anchored = initial(O.anchored) + else + occupant_message("Not enough room in cargo compartment!") + else + occupant_message("[target] is firmly secured!") + + else if(istype(target,/mob/living)) + var/mob/living/M = target + if(M.stat == DEAD) return + if(chassis.occupant.a_intent == I_HARM) + M.take_overall_damage(dam_force) + if(!M) + return + M.adjustOxyLoss(round(dam_force/2)) + M.updatehealth() + target.visible_message("[chassis] squeezes [target].", \ + "[chassis] squeezes [target].",\ + "You hear something crack.") + add_logs(chassis.occupant, M, "attacked", "[name]", "(INTENT: [uppertext(chassis.occupant.a_intent)]) (DAMTYE: [uppertext(damtype)])") + start_cooldown() + else + step_away(M,chassis) + occupant_message("You push [target] out of the way.") + chassis.visible_message("[chassis] pushes [target] out of the way.") + return 1 + + + +//This is pretty much just for the death-ripley +/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/kill + name = "\improper KILL CLAMP" + desc = "They won't know what clamped them!" + energy_drain = 0 + +/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/kill/action(atom/target) + if(!action_checks(target)) 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.visible_message("[chassis] lifts [target] and starts to load it into cargo compartment.") + O.anchored = 1 + if(do_after_cooldown(target)) + cargo_holder.cargo += O + O.loc = chassis + O.anchored = 0 + occupant_message("[target] successfully loaded.") + log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]") + else + O.anchored = initial(O.anchored) + else + occupant_message("Not enough room in cargo compartment!") + else + occupant_message("[target] is firmly secured!") + + else if(istype(target,/mob/living)) + var/mob/living/M = target + if(M.stat == DEAD) return + if(chassis.occupant.a_intent == I_HARM) + target.visible_message("[chassis] destroys [target] in an unholy fury.", + "[chassis] destroys [target] in an unholy fury.") + M.gib() + /*if(chassis.occupant.a_intent == I_DISARM) + target.visible_message("[chassis] rips [target]'s arms off.", + "[chassis] rips [target]'s arms off.")*/ + else + step_away(M,chassis) + target.visible_message("[chassis] tosses [target] like a piece of paper.") + return 1 + + +/obj/item/mecha_parts/mecha_equipment/extinguisher + name = "exosuit extinguisher" + desc = "Equipment for engineering exosuits. A rapid-firing high capacity fire extinguisher." + icon_state = "mecha_exting" + equip_cooldown = 5 + energy_drain = 0 + range = MELEE|RANGED + +/obj/item/mecha_parts/mecha_equipment/extinguisher/New() + create_reagents(1000) + reagents.add_reagent("water", 1000) + ..() + return + +/obj/item/mecha_parts/mecha_equipment/extinguisher/action(atom/target) //copypasted from extinguisher. TODO: Rewrite from scratch. + if(!action_checks(target) || get_dist(chassis, target)>3) + return + + if(istype(target, /obj/structure/reagent_dispensers/watertank) && get_dist(chassis,target) <= 1) + var/obj/structure/reagent_dispensers/watertank/WT = target + WT.reagents.trans_to(src, 1000) + occupant_message("Extinguisher refilled.") + playsound(chassis, 'sound/effects/refill.ogg', 50, 1, -6) + else + if(reagents.total_volume > 0) + playsound(chassis, 'sound/effects/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) + spawn(0) + for(var/a=0, a<5, a++) + var/obj/effect/effect/water/W = new /obj/effect/effect/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 + reagents.trans_to(W,1) + for(var/b=0, b<4, 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 + +/obj/item/mecha_parts/mecha_equipment/extinguisher/get_equip_info() + return "[..()] \[[src.reagents.total_volume]\]" + +/obj/item/mecha_parts/mecha_equipment/extinguisher/on_reagent_change() + return + +/obj/item/mecha_parts/mecha_equipment/extinguisher/can_attach(obj/mecha/working/M) + if(..()) + if(istype(M)) + return 1 + return 0 + + +/obj/item/mecha_parts/mecha_equipment/rcd + name = "Mounted RCD" + desc = "An exosuit-mounted Rapid Construction Device. (Can be attached to: Any exosuit)" + icon_state = "mecha_rcd" + origin_tech = "materials=4;bluespace=3;magnets=4;powerstorage=4" + equip_cooldown = 10 + energy_drain = 250 + range = MELEE|RANGED + var/mode = 0 //0 - deconstruct, 1 - wall or floor, 2 - airlock. + var/canRwall = 0 + +/obj/item/mecha_parts/mecha_equipment/rcd/New() + rcd_list += src + ..() + +/obj/item/mecha_parts/mecha_equipment/rcd/Destroy() + rcd_list -= src + return ..() + +/obj/item/mecha_parts/mecha_equipment/rcd/action(atom/target) + if(istype(target, /turf/space/transit))//>implying these are ever made -Sieve + return + + if(!istype(target, /turf) && !istype(target, /obj/machinery/door/airlock)) + target = get_turf(target) + + if(!action_checks(target) || get_dist(chassis, target)>3) + return + playsound(chassis, 'sound/machines/click.ogg', 50, 1) + + switch(mode) + if(0) + if(istype(target, /turf/simulated/wall)) + if(istype(target, /turf/simulated/wall/r_wall) && !canRwall) + return 0 + var/turf/simulated/wall/W = target + occupant_message("Deconstructing [target]...") + if(do_after_cooldown(W)) + chassis.spark_system.start() + W.ChangeTurf(/turf/simulated/floor/plating) + playsound(W, 'sound/items/Deconstruct.ogg', 50, 1) + else if(istype(target, /turf/simulated/floor)) + var/turf/simulated/floor/F = target + occupant_message("Deconstructing [target]...") + if(do_after_cooldown(F)) + chassis.spark_system.start() + F.ChangeTurf(/turf/space) + F.air_update_turf() + playsound(F, 'sound/items/Deconstruct.ogg', 50, 1) + else if(istype(target, /obj/machinery/door/airlock)) + occupant_message("Deconstructing [target]...") + if(do_after_cooldown(target)) + chassis.spark_system.start() + qdel(target) + playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) + if(1) + if(istype(target, /turf/space)) + var/turf/space/S = target + occupant_message("Building Floor...") + if(do_after_cooldown(S)) + S.ChangeTurf(/turf/simulated/floor/plating) + playsound(S, 'sound/items/Deconstruct.ogg', 50, 1) + chassis.spark_system.start() + else if(istype(target, /turf/simulated/floor)) + var/turf/simulated/floor/F = target + occupant_message("Building Wall...") + if(do_after_cooldown(F)) + F.ChangeTurf(/turf/simulated/wall) + playsound(F, 'sound/items/Deconstruct.ogg', 50, 1) + chassis.spark_system.start() + if(2) + if(istype(target, /turf/simulated/floor)) + occupant_message("Building Airlock...") + if(do_after_cooldown(target)) + chassis.spark_system.start() + var/obj/machinery/door/airlock/T = new /obj/machinery/door/airlock(target) + T.autoclose = 1 + playsound(target, 'sound/items/Deconstruct.ogg', 50, 1) + playsound(target, 'sound/effects/sparks2.ogg', 50, 1) + + +/obj/item/mecha_parts/mecha_equipment/rcd/Topic(href,href_list) + ..() + if(href_list["mode"]) + mode = text2num(href_list["mode"]) + switch(mode) + if(0) + occupant_message("Switched RCD to Deconstruct.") + if(1) + occupant_message("Switched RCD to Construct.") + if(2) + occupant_message("Switched RCD to Construct Airlock.") + +/obj/item/mecha_parts/mecha_equipment/rcd/get_equip_info() + return "[..()] \[D|C|A\]" + + +/obj/item/mecha_parts/mecha_equipment/mimercd + name = "mounted MRCD" + desc = "An exosuit-mounted Mime Rapid Construction Device. (Can be attached to: Recitence)" + icon_state = "mecha_rcd" + origin_tech = "materials=4;bluespace=3;magnets=4;powerstorage=4" + equip_cooldown = 10 + energy_drain = 250 + range = MELEE|RANGED + +/obj/item/mecha_parts/mecha_equipment/mimercd/can_attach(obj/mecha/combat/recitence/M) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/mimercd/action(atom/target) + if(istype(target, /turf/space/transit))//>implying these are ever made -Sieve + return + if(!istype(target, /turf)) + target = get_turf(target) + if(!action_checks(target) || get_dist(chassis, target)>3) + return + + if(istype(target, /turf/simulated/floor)) + occupant_message("Building Wall...") + if(do_after_cooldown(target)) + new /obj/structure/barricade/mime/mrcd(target) + chassis.spark_system.start() + + + +/obj/item/mecha_parts/mecha_equipment/cable_layer + name = "cable layer" + desc = "Equipment for engineering exosuits. Lays cable along the exosuit's path." + icon_state = "mecha_wire" + var/datum/event/event + var/turf/old_turf + var/obj/structure/cable/last_piece + var/obj/item/stack/cable_coil/cable + var/max_cable = 1000 + +/obj/item/mecha_parts/mecha_equipment/cable_layer/New() + cable = new(src) + cable.amount = 0 + ..() + +/obj/item/mecha_parts/mecha_equipment/cable_layer/can_attach(obj/mecha/working/M) + if(..()) + if(istype(M)) + return 1 + return 0 + +/obj/item/mecha_parts/mecha_equipment/cable_layer/attach() + ..() + event = chassis.events.addEvent("onMove",src,"layCable") + return + +/obj/item/mecha_parts/mecha_equipment/cable_layer/detach() + chassis.events.clearEvent("onMove",event) + return ..() + +/obj/item/mecha_parts/mecha_equipment/cable_layer/Destroy() + chassis.events.clearEvent("onMove",event) + return ..() + +/obj/item/mecha_parts/mecha_equipment/cable_layer/action(var/obj/item/stack/cable_coil/target) + if(!action_checks(target)) + return + if(istype(target) && target.amount) + var/cur_amount = cable? cable.amount : 0 + var/to_load = max(max_cable - cur_amount,0) + if(to_load) + to_load = min(target.amount, to_load) + if(!cable) + cable = new(src) + cable.amount = 0 + cable.amount += to_load + target.use(to_load) + occupant_message("[to_load] meters of cable successfully loaded.") + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) + else + occupant_message("Reel is full.") + else + occupant_message("Unable to load [target] - no cable found.") + + +/obj/item/mecha_parts/mecha_equipment/cable_layer/Topic(href,href_list) + ..() + if(href_list["toggle"]) + set_ready_state(!equip_ready) + occupant_message("[src] [equip_ready?"dea":"a"]ctivated.") + log_message("[equip_ready?"Dea":"A"]ctivated.") + return + if(href_list["cut"]) + if(cable && cable.amount) + var/m = round(input(chassis.occupant,"Please specify the length of cable to cut","Cut cable",min(cable.amount,30)) as num, 1) + m = min(m, cable.amount) + if(m) + use_cable(m) + var/obj/item/stack/cable_coil/CC = new (get_turf(chassis)) + CC.amount = m + else + occupant_message("There's no more cable on the reel.") + return + +/obj/item/mecha_parts/mecha_equipment/cable_layer/get_equip_info() + var/output = ..() + if(output) + return "[output] \[Cable: [cable ? cable.amount : 0] m\][(cable && cable.amount) ? "- [!equip_ready?"Dea":"A"]ctivate|Cut" : null]" + return + +/obj/item/mecha_parts/mecha_equipment/cable_layer/proc/use_cable(amount) + if(!cable || cable.amount<1) + set_ready_state(1) + occupant_message("Cable depleted, [src] deactivated.") + log_message("Cable depleted, [src] deactivated.") + return + if(cable.amount < amount) + occupant_message("No enough cable to finish the task.") + return + cable.use(amount) + update_equip_info() + return 1 + +/obj/item/mecha_parts/mecha_equipment/cable_layer/proc/reset() + last_piece = null + +/obj/item/mecha_parts/mecha_equipment/cable_layer/proc/dismantleFloor(var/turf/new_turf) + if(istype(new_turf, /turf/simulated/floor)) + var/turf/simulated/floor/T = new_turf + if(!istype(T, /turf/simulated/floor/plating)) + if(!T.broken && !T.burnt) + new T.floor_tile(T) + T.make_plating() + return !new_turf.intact + +/obj/item/mecha_parts/mecha_equipment/cable_layer/proc/layCable(var/turf/new_turf) + if(equip_ready || !istype(new_turf) || !dismantleFloor(new_turf)) + return reset() + var/fdirn = turn(chassis.dir,180) + for(var/obj/structure/cable/LC in new_turf) // check to make sure there's not a cable there already + if(LC.d1 == fdirn || LC.d2 == fdirn) + return reset() + if(!use_cable(1)) + return reset() + var/obj/structure/cable/NC = new(new_turf) + NC.cableColor("red") + NC.d1 = 0 + NC.d2 = fdirn + NC.updateicon() + + var/datum/powernet/PN + if(last_piece && last_piece.d2 != chassis.dir) + last_piece.d1 = min(last_piece.d2, chassis.dir) + last_piece.d2 = max(last_piece.d2, chassis.dir) + last_piece.updateicon() + PN = last_piece.powernet + + if(!PN) + PN = new() + powernets += PN + NC.powernet = PN + PN.cables += NC + NC.mergeConnectedNetworks(NC.d2) + + //NC.mergeConnectedNetworksOnTurf() + last_piece = NC + return 1 + diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index c425ec0edef..69189e51456 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -58,10 +58,6 @@ var/list/operation_req_access = list()//required access level for mecha operation var/list/internals_req_access = list(access_engine,access_robotics)//required access level to open cell compartment - var/datum/global_iterator/pr_int_temp_processor //normalizes internal air mixture temperature - var/datum/global_iterator/pr_give_air //moves air from tank to cabin - var/datum/global_iterator/pr_internal_damage //processes internal damage - var/wreckage var/list/equipment = new @@ -70,7 +66,9 @@ var/datum/events/events var/turf/crashing = null - var/stepsound = 'sound/mecha/mechturn.ogg' + + var/stepsound = 'sound/mecha/mechstep.ogg' + var/turnsound = 'sound/mecha/mechturn.ogg' var/melee_cooldown = 10 var/melee_can_hit = 1 @@ -83,16 +81,18 @@ icon_state += "-open" add_radio() add_cabin() + if(!add_airtank()) //we check this here in case mecha does not have an internal tank available by default - WIP removeVerb(/obj/mecha/verb/connect_to_port) removeVerb(/obj/mecha/verb/toggle_internal_tank) + spark_system.set_up(2, 0, src) spark_system.attach(src) add_cell() - add_iterators() + + processing_objects.Add(src) removeVerb(/obj/mecha/verb/disconnect_from_port) - log_message("[src.name] created.") - loc.Entered(src) + log_message("[src] created.") mechas_list += src //global mech list prepare_huds() var/datum/atom_hud/data/diagnostic/diag_hud = huds[DATA_HUD_DIAGNOSTIC] @@ -100,7 +100,6 @@ diag_hud_set_mechhealth() diag_hud_set_mechcell() diag_hud_set_mechstat() - return //////////////////////// ////// Helpers ///////// @@ -140,29 +139,6 @@ radio.icon_state = icon_state radio.subspace_transmission = 1 -/obj/mecha/proc/add_iterators() - pr_int_temp_processor = new /datum/global_iterator/mecha_preserve_temp(list(src)) - pr_give_air = new /datum/global_iterator/mecha_tank_give_air(list(src)) - pr_internal_damage = new /datum/global_iterator/mecha_internal_damage(list(src),0) - -/obj/mecha/proc/mecha_do_after(delay as num) - sleep(delay) - if(src) - return 1 - return 0 - -/obj/mecha/proc/enter_after(delay as num, var/mob/user as mob, var/numticks = 5) - var/delayfraction = delay/numticks - - var/turf/T = user.loc - - for(var/i = 0, iMaintenance protocols in effect.") @@ -230,28 +180,30 @@ return if(src == target) return - var/dir_to_target = get_dir(src,target) - if(dir_to_target && !(dir_to_target & src.dir))//wrong direction + + var/dir_to_target = get_dir(src, target) + if(dir_to_target && !(dir_to_target & dir))//wrong direction return + if(hasInternalDamage(MECHA_INT_CONTROL_LOST)) target = safepick(view(3,target)) if(!target) return + if(!target.Adjacent(src)) if(selected && selected.is_ranged()) selected.action(target, params) else if(selected && selected.is_melee()) selected.action(target, params) else - if(internal_damage&MECHA_INT_CONTROL_LOST) - target = safepick(oview(1,src)) - if(!melee_can_hit || !istype(target, /atom)) + if(internal_damage & MECHA_INT_CONTROL_LOST) + target = safepick(oview(1, src)) + if(!melee_can_hit || !isatom(target)) return target.mech_melee_attack(src) melee_can_hit = 0 - if(mecha_do_after(melee_cooldown)) + spawn(melee_cooldown) melee_can_hit = 1 - return /obj/mecha/proc/mech_toxin_damage(mob/living/target) playsound(src, 'sound/effects/spray2.ogg', 50, 1) @@ -293,54 +245,65 @@ events.fireEvent("onMove",get_turf(src)) /obj/mecha/Process_Spacemove(var/movement_dir = 0) - if(occupant) - return occupant.Process_Spacemove(movement_dir) //We'll just say you used the clamp to grab the wall - return ..() + . = ..() + if(.) + return 1 -/obj/mecha/relaymove(mob/user,direction) - if(user != src.occupant) //While not "realistic", this piece is player friendly. + var/atom/movable/backup = get_spacemove_backup() + if(backup) + if(istype(backup) && movement_dir && !backup.anchored) + if(backup.newtonian_move(turn(movement_dir, 180))) + if(occupant) + to_chat(occupant, "You push off of [backup] to propel yourself.") + return 1 + +/obj/mecha/relaymove(mob/user, direction) + if(!direction) + return + if(user != occupant) //While not "realistic", this piece is player friendly. user.forceMove(get_turf(src)) - to_chat(user, "You climb out from [src]") + to_chat(user, "You climb out from [src].") return 0 if(connected_port) if(world.time - last_message > 20) - src.occupant_message("Unable to move while connected to the air system port") + occupant_message("Unable to move while connected to the air system port!") last_message = world.time return 0 if(state) - occupant_message("Maintenance protocols in effect") + occupant_message("Maintenance protocols in effect.") return return domove(direction) - + /obj/mecha/proc/domove(direction) - return call((proc_res["dyndomove"]||src), "dyndomove")(direction) - -/obj/mecha/proc/dyndomove(direction) if(!can_move) return 0 if(!Process_Spacemove(direction)) return 0 if(!has_charge(step_energy_drain)) return 0 + var/move_result = 0 - if(hasInternalDamage(MECHA_INT_CONTROL_LOST)) + if(internal_damage & MECHA_INT_CONTROL_LOST) move_result = mechsteprand() - else if(src.dir!=direction) + else if(dir != direction) move_result = mechturn(direction) else move_result = mechstep(direction) + + can_move = 0 + spawn(step_in) + can_move = 1 + if(move_result) - can_move = 0 use_power(step_energy_drain) - if(mecha_do_after(step_in)) - can_move = 1 return 1 return 0 + /obj/mecha/proc/mechturn(direction) dir = direction - if(stepsound) - playsound(src,stepsound,40,1) + if(turnsound) + playsound(src,turnsound,40,1) return 1 /obj/mecha/proc/mechstep(direction) @@ -354,12 +317,13 @@ if(result && stepsound) playsound(src,stepsound,40,1) return result + + -/obj/mecha/Bump(var/atom/obstacle) -// src.inertia_dir = null - if(src.throwing)//high velocity mechas in your face! +/obj/mecha/Bump(var/atom/obstacle, bump_allowed) + if(throwing) //high velocity mechas in your face! var/breakthrough = 0 - if(istype(obstacle, /obj/structure/window/)) + if(istype(obstacle, /obj/structure/window)) qdel(obstacle) breakthrough = 1 @@ -385,7 +349,7 @@ else if(istype(obstacle, /obj/structure/reagent_dispensers/fueltank)) obstacle.ex_act(1) - else if(istype(obstacle, /mob/living)) + else if(isliving(obstacle)) var/mob/living/L = obstacle var/hit_sound = list('sound/weapons/genhit1.ogg','sound/weapons/genhit2.ogg','sound/weapons/genhit3.ogg') if(L.flags & GODMODE) @@ -400,34 +364,34 @@ breakthrough = 1 else - src.throwing = 0//so mechas don't get stuck when landing after being sent by a Mass Driver - src.crashing = null + throwing = 0 //so mechas don't get stuck when landing after being sent by a Mass Driver + crashing = null if(breakthrough) if(crashing) spawn(1) - src.throw_at(crashing, 50, src.throw_speed) + throw_at(crashing, 50, throw_speed) else spawn(1) crashing = get_distant_turf(get_turf(src), dir, 3)//don't use get_dir(src, obstacle) or the mech will stop if he bumps into a one-direction window on his tile. - src.throw_at(crashing, 50, src.throw_speed) + throw_at(crashing, 50, throw_speed) - if(istype(obstacle, /obj)) - var/obj/O = obstacle - if(istype(O, /obj/effect/portal)) //derpfix - src.anchored = 0 - O.Bumped(src) - spawn(0)//countering portal teleport spawn(0), hurr - src.anchored = 1 - else if(!O.anchored) - step(obstacle,src.dir) - 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 + if(bump_allowed) + if(..()) + return + if(isobj(obstacle)) + var/obj/O = obstacle + if(istype(O, /obj/effect/portal)) //derpfix + anchored = 0 + O.Bumped(src) + spawn(0) //countering portal teleport spawn(0), hurr + anchored = 1 + else if(!O.anchored) + step(obstacle, dir) + else if(ismob(obstacle)) + step(obstacle, dir) + /////////////////////////////////// //////// Internal damage //////// @@ -436,7 +400,7 @@ /obj/mecha/proc/check_for_internal_damage(var/list/possible_int_damage,var/ignore_threshold=null) if(!islist(possible_int_damage) || isemptylist(possible_int_damage)) return if(prob(20)) - if(ignore_threshold || src.health*100/initial(src.health)Life support system reactivated.") - pr_int_temp_processor.start() + occupant_message("Life support system reactivated.") if(MECHA_INT_FIRE) - occupant_message("Internal fire extinquished.") + occupant_message("Internal fire extinquished.") if(MECHA_INT_TANK_BREACH) - occupant_message("Damaged internal tank has been sealed.") + occupant_message("Damaged internal tank has been sealed.") diag_hud_set_mechstat() - return //////////////////////////////////////// @@ -496,8 +456,8 @@ /obj/mecha/proc/update_health() - if(src.health > 0) - src.spark_system.start() + if(health > 0) + spark_system.start() diag_hud_set_mechhealth() else qdel(src) @@ -506,108 +466,109 @@ /obj/mecha/attack_hand(mob/living/user as mob) user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src) - src.log_message("Attack by hand/paw. Attacker - [user].",1) + log_message("Attack by hand/paw. Attacker - [user].",1) - - if((HULK in user.mutations) && !prob(src.deflect_chance)) - src.take_damage(15) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - user.visible_message("[user] hits [src.name], doing some damage.", "You hit [src.name] with all your might. The metal creaks and bends.") + if((HULK in user.mutations) && !prob(deflect_chance)) + take_damage(15) + check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + user.visible_message("[user] hits [name], doing some damage.", + "You hit [name] with all your might. The metal creaks and bends.") else - user.visible_message("[user] hits [src.name]. Nothing happens","You hit [src.name] with no visible effect.") - src.log_append_to_last("Armor saved.") + user.visible_message("[user] hits [name]. Nothing happens","You hit [name] with no visible effect.") + log_append_to_last("Armor saved.") return /obj/mecha/attack_alien(mob/living/user as mob) - src.log_message("Attack by alien. Attacker - [user].",1) + log_message("Attack by alien. Attacker - [user].",1) user.changeNext_move(CLICK_CD_MELEE) user.do_attack_animation(src) - if(!prob(src.deflect_chance)) - src.take_damage(15) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) + if(!prob(deflect_chance)) + take_damage(15) + check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + playsound(loc, 'sound/weapons/slash.ogg', 50, 1, -1) to_chat(user, "\red You slash at the armored suit!") - visible_message("\red The [user] slashes at [src.name]'s armor!") + visible_message("\red The [user] slashes at [name]'s armor!") else - src.log_append_to_last("Armor saved.") - playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) + log_append_to_last("Armor saved.") + playsound(loc, 'sound/weapons/slash.ogg', 50, 1, -1) to_chat(user, "\green Your claws had no effect!") - src.occupant_message("\blue The [user]'s claws are stopped by the armor.") - visible_message("\blue The [user] rebounds off [src.name]'s armor!") + occupant_message("\blue The [user]'s claws are stopped by the armor.") + visible_message("\blue The [user] rebounds off [name]'s armor!") return /obj/mecha/attack_animal(mob/living/simple_animal/user as mob) - src.log_message("Attack by simple animal. Attacker - [user].",1) + log_message("Attack by simple animal. Attacker - [user].",1) if(user.melee_damage_upper == 0) user.custom_emote(1, "[user.friendly] [src]") else user.do_attack_animation(src) - if(!prob(src.deflect_chance)) + if(!prob(deflect_chance)) var/damage = rand(user.melee_damage_lower, user.melee_damage_upper) - src.take_damage(damage) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + take_damage(damage) + check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) visible_message("[user] [user.attacktext] [src]!") user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") else - src.log_append_to_last("Armor saved.") - playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) - src.occupant_message("\blue The [user]'s attack is stopped by the armor.") - visible_message("\blue The [user] rebounds off [src.name]'s armor!") - user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") + log_append_to_last("Armor saved.") + playsound(loc, 'sound/weapons/slash.ogg', 50, 1, -1) + occupant_message("\blue The [user]'s attack is stopped by the armor.") + visible_message("\blue The [user] rebounds off [name]'s armor!") + user.attack_log += text("\[[time_stamp()]\] attacked [name]") return /obj/mecha/hitby(atom/movable/A as mob|obj) //wrapper ..() - src.log_message("Hit by [A].",1) - call((proc_res["dynhitby"]||src), "dynhitby")(A) - return + log_message("Hit by [A].",1) -/obj/mecha/proc/dynhitby(atom/movable/A) + var/def_coeff = 1 + var/dam_coeff = 1 + var/counter_tracking = 0 + for(var/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/B in equipment) + if(B.projectile_react()) + def_coeff = B.deflect_coeff + dam_coeff = B.damage_coeff + counter_tracking = 1 + break if(istype(A, /obj/item/mecha_parts/mecha_tracking)) - A.forceMove(src) - src.visible_message("The [A] fastens firmly to [src].") - return - if(prob(src.deflect_chance) || istype(A, /mob)) - src.occupant_message("\blue The [A] bounces off the armor.") - src.visible_message("The [A] bounces off the [src.name] armor") - src.log_append_to_last("Armor saved.") - if(istype(A, /mob/living)) + if(!counter_tracking) + A.forceMove(src) + visible_message("The [A] fastens firmly to [src].") + return + + if(prob(deflect_chance * def_coeff) || ismob(A)) + occupant_message("[A] bounces off the armor.") + visible_message("[A] bounces off the [src]\s armor!") + log_append_to_last("Armor saved.") + if(isliving(A)) var/mob/living/M = A - M.take_organ_damage(10) - else if(istype(A, /obj)) + M.take_organ_damage(10) + + if(isobj(A)) var/obj/O = A if(O.throwforce) - src.take_damage(O.throwforce) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - return + take_damage(O.throwforce * dam_coeff) + check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) /obj/mecha/bullet_act(var/obj/item/projectile/Proj) //wrapper - src.log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).",1) - call((proc_res["dynbulletdamage"]||src), "dynbulletdamage")(Proj) //calls equipment - ..() - return + log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).",1) -/obj/mecha/proc/dynbulletdamage(var/obj/item/projectile/Proj) - if(prob(src.deflect_chance)) - src.occupant_message("\blue The armor deflects incoming projectile.") - src.visible_message("The [src.name] armor deflects the projectile") - src.log_append_to_last("Armor saved.") - return - var/ignore_threshold - if(Proj.flag == "taser") - use_power(200) - return - if(istype(Proj, /obj/item/projectile/beam/pulse)) - ignore_threshold = 1 - if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) - src.take_damage(Proj.damage,Proj.flag) - src.visible_message("[src.name] is hit by [Proj].") - src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),ignore_threshold) + var/deflection = 1 + var/dam_coeff = 1 + for(var/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/B in equipment) + if(B.projectile_react()) + deflection = B.deflect_coeff + dam_coeff = B.damage_coeff + break + + if(prob(deflect_chance & deflection) && (Proj.damage_type == BRUTE || Proj.damage_type == BURN)) + visible_message("[src] is hit by [Proj].") + take_damage(Proj.damage * dam_coeff, Proj.flag) + check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT)) Proj.on_hit(src) - return + /obj/mecha/Destroy() go_out() @@ -615,19 +576,11 @@ if(isAI(M)) M.gib() //AIs are loaded into the mech computer itself. When the mech dies, so does the AI. Forever. else - M.Move(loc) + M.forceMove(loc) if(prob(30)) explosion(get_turf(loc), 0, 0, 1, 3) - if(istype(src, /obj/mecha/working/ripley/)) - var/obj/mecha/working/ripley/R = src - if(R.cargo) - for(var/obj/O in R.cargo) //Dump contents of stored cargo - O.forceMove(loc) - R.cargo -= O - loc.Entered(O) - if(wreckage) var/obj/effect/decal/mecha_wreckage/WR = new wreckage(loc) for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) @@ -654,65 +607,43 @@ qdel(cell) if(internal_tank) qdel(internal_tank) + + processing_objects.Remove(src) equipment.Cut() cell = null internal_tank = null - - qdel(pr_int_temp_processor) - qdel(pr_give_air) - qdel(pr_internal_damage) + if(loc) + loc.assume_air(cabin_air) + air_update_turf() + else + qdel(cabin_air) + cabin_air = null qdel(spark_system) - pr_int_temp_processor = null - pr_give_air = null - pr_internal_damage = null spark_system = null mechas_list -= src //global mech list return ..() /obj/mecha/ex_act(severity) - src.log_message("Affected by explosion of severity: [severity].",1) - if(prob(src.deflect_chance)) + log_message("Affected by explosion of severity: [severity].",1) + if(prob(deflect_chance)) severity++ - src.log_append_to_last("Armor saved, changing severity to [severity].") + log_append_to_last("Armor saved, changing severity to [severity].") switch(severity) - if(1.0) + if(1) qdel(src) - if(2.0) + if(2) if(prob(30)) qdel(src) else - src.take_damage(initial(src.health)/2) - src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) - if(3.0) + take_damage(initial(health)/2) + check_for_internal_damage(list(MECHA_INT_FIRE, MECHA_INT_TEMP_CONTROL, MECHA_INT_TANK_BREACH, MECHA_INT_CONTROL_LOST, MECHA_INT_SHORT_CIRCUIT), 1) + if(3) if(prob(5)) qdel(src) else - src.take_damage(initial(src.health)/5) - src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) - return - -/*Will fix later -Sieve -/obj/mecha/attack_blob(mob/user as mob) - src.log_message("Attack by blob. Attacker - [user].",1) - if(!prob(src.deflect_chance)) - src.take_damage(6) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - playsound(src.loc, 'sound/effects/blobattack.ogg', 50, 1, -1) - to_chat(user, "\red You smash at the armored suit!") - for(var/mob/V in viewers(src)) - if(V.client && !(V.blinded)) - V.show_message("\red The [user] smashes against [src.name]'s armor!", 1) - else - src.log_append_to_last("Armor saved.") - playsound(src.loc, 'sound/effects/blobattack.ogg', 50, 1, -1) - to_chat(user, "\green Your attack had no effect!") - src.occupant_message("\blue The [user]'s attack is stopped by the armor.") - for(var/mob/V in viewers(src)) - if(V.client && !(V.blinded)) - V.show_message("\blue The [user] rebounds off the [src.name] armor!", 1) - return -*/ + take_damage(initial(health) / 5) + check_for_internal_damage(list(MECHA_INT_FIRE, MECHA_INT_TEMP_CONTROL, MECHA_INT_TANK_BREACH, MECHA_INT_CONTROL_LOST, MECHA_INT_SHORT_CIRCUIT), 1) //TODO /obj/mecha/blob_act() @@ -721,45 +652,23 @@ /obj/mecha/emp_act(severity) if(get_charge()) - use_power((cell.charge/2)/severity) - take_damage(50 / severity,"energy") - src.log_message("EMP detected",1) - check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT),1) - return + use_power((cell.charge / 2) / severity) + take_damage(50 / severity, "energy") + log_message("EMP detected", 1) + check_for_internal_damage(list(MECHA_INT_FIRE, MECHA_INT_TEMP_CONTROL, MECHA_INT_CONTROL_LOST, MECHA_INT_SHORT_CIRCUIT), 1) /obj/mecha/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature>src.max_temperature) - src.log_message("Exposed to dangerous temperature.",1) - src.take_damage(5,"fire") - src.check_for_internal_damage(list(MECHA_INT_FIRE, MECHA_INT_TEMP_CONTROL)) - return - -/obj/mecha/proc/dynattackby(obj/item/weapon/W as obj, mob/living/user as mob, params) - src.log_message("Attacked by [W]. Attacker - [user]") - user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src) - if(prob(src.deflect_chance)) - to_chat(user, "\red The [W] bounces off [src.name] armor.") - src.log_append_to_last("Armor saved.") -/* - for(var/mob/V in viewers(src)) - if(V.client && !(V.blinded)) - V.show_message("The [W] bounces off [src.name] armor.", 1) -*/ - else - src.occupant_message("[user] hits [src] with [W].") - user.visible_message("[user] hits [src] with [W].", "You hit [src] with [W].") - src.take_damage(W.force,W.damtype) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - return + if(exposed_temperature > max_temperature) + log_message("Exposed to dangerous temperature.", 1) + take_damage(5, "fire") + check_for_internal_damage(list(MECHA_INT_FIRE, MECHA_INT_TEMP_CONTROL)) ////////////////////// ////// AttackBy ////// ////////////////////// -/obj/mecha/attackby(obj/item/weapon/W as obj, mob/user as mob, params) - - if(istype(W, /obj/item/device/mmi) || istype(W, /obj/item/device/mmi/posibrain)) +/obj/mecha/attackby(obj/item/weapon/W, mob/user, params) + if(istype(W, /obj/item/device/mmi)) if(mmi_move_inside(W,user)) to_chat(user, "[src]-MMI interface initialized successfuly") else @@ -770,13 +679,15 @@ var/obj/item/mecha_parts/mecha_equipment/E = W spawn() if(E.can_attach(src)) - user.drop_item() + if(!user.drop_item()) + return E.attach(src) - user.visible_message("[user] attaches [W] to [src]", "You attach [W] to [src]") + user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src].") else - to_chat(user, "You were unable to attach [W] to [src]") + to_chat(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(W.GetID()) if(add_req_access || maint_access) if(internals_access_allowed(usr)) var/obj/item/weapon/card/id/id_card @@ -788,10 +699,11 @@ output_maintenance_dialog(id_card, user) return else - to_chat(user, "\red Invalid ID: Access denied.") + to_chat(user, "Invalid ID: Access denied.") else - to_chat(user, "\red Maintenance protocols disabled by operator.") - else if(istype(W, /obj/item/weapon/wrench)) + to_chat(user, "Maintenance protocols disabled by operator.") + + else if(iswrench(W)) if(state==1) state = 2 to_chat(user, "You undo the securing bolts.") @@ -799,7 +711,8 @@ state = 1 to_chat(user, "You tighten the securing bolts.") return - else if(istype(W, /obj/item/weapon/crowbar)) + + else if(iscrowbar(W)) if(state==2) state = 3 to_chat(user, "You open the hatch to the power unit") @@ -815,7 +728,6 @@ go_out() return - else if(istype(W, /obj/item/stack/cable_coil)) if(state == 3 && hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) var/obj/item/stack/cable_coil/CC = W @@ -826,58 +738,61 @@ else to_chat(user, "There's not enough wire to finish the task.") return - else if(istype(W, /obj/item/weapon/screwdriver)) + + else if(isscrewdriver(W) && user.a_intent != I_HARM) if(hasInternalDamage(MECHA_INT_TEMP_CONTROL)) clearInternalDamage(MECHA_INT_TEMP_CONTROL) - to_chat(user, "You repair the damaged temperature controller.") - else if(state==3 && src.cell) - src.cell.forceMove(src.loc) - src.cell = null + to_chat(user, "You repair the damaged temperature controller.") + else if(state==3 && cell) + cell.forceMove(loc) + cell = null state = 4 - to_chat(user, "You unscrew and pry out the powercell.") - src.log_message("Powercell removed") - else if(state==4 && src.cell) + to_chat(user, "You unscrew and pry out the powercell.") + log_message("Powercell removed") + else if(state==4 && cell) state=3 - to_chat(user, "You screw the cell in place") + to_chat(user, "You screw the cell in place.") return else if(istype(W, /obj/item/weapon/stock_parts/cell)) if(state==4) - if(!src.cell) - to_chat(user, "You install the powercell") - user.drop_item() + if(!cell) + if(!user.drop_item()) + return + to_chat(user, "You install the powercell.") W.forceMove(src) - src.cell = W - src.log_message("Powercell installed") + cell = W + log_message("Powercell installed") else - to_chat(user, "There's already a powercell installed.") + to_chat(user, "There's already a powercell installed.") return - else if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != I_HARM) + else if(iswelder(W) && user.a_intent != I_HARM) var/obj/item/weapon/weldingtool/WT = W - if(WT.remove_fuel(0,user)) - if(hasInternalDamage(MECHA_INT_TANK_BREACH)) - clearInternalDamage(MECHA_INT_TANK_BREACH) - to_chat(user, "\blue You repair the damaged gas tank.") + if(healthYou repair the damaged gas tank.
") + else + user.visible_message("[user] repairs some damage to [name].") + health += min(10, initial(health)-health) + else + to_chat(user, "The welder must be on for this task!") + return 1 else - return - if(src.healthThe [name] is at full integrity!") + return 1 else if(istype(W, /obj/item/mecha_parts/mecha_tracking)) if(!user.unEquip(W)) to_chat(user, "\the [W] is stuck to your hand, you cannot put it in \the [src]") return W.forceMove(src) - user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src]") + user.visible_message("[user] attaches [W] to [src].", "You attach [W] to [src].") return else if(istype(W, /obj/item/weapon/paintkit)) - if(occupant) to_chat(user, "You can't customize a mech while someone is piloting it - that would be unsafe!") return @@ -886,7 +801,7 @@ var/found = null for(var/type in P.allowed_types) - if(type==src.initial_icon) + if(type == initial_icon) found = 1 break @@ -896,43 +811,41 @@ user.visible_message("[user] opens [P] and spends some quality time customising [src].") - src.name = P.new_name - src.desc = P.new_desc - src.initial_icon = P.new_icon - src.reset_icon() + name = P.new_name + desc = P.new_desc + initial_icon = P.new_icon + reset_icon() user.drop_item() qdel(P) else - call((proc_res["dynattackby"]||src), "dynattackby")(W,user) -/* - src.log_message("Attacked by [W]. Attacker - [user]") - if(prob(src.deflect_chance)) - to_chat(user, "\red The [W] bounces off [src.name] armor.") - src.log_append_to_last("Armor saved.") -/* - for(var/mob/V in viewers(src)) - if(V.client && !(V.blinded)) - V.show_message("The [W] bounces off [src.name] armor.", 1) -*/ - else - src.occupant_message("[user] hits [src] with [W].") - user.visible_message("[user] hits [src] with [W].", "You hit [src] with [W].") - src.take_damage(W.force,W.damtype) - src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) -*/ - diag_hud_set_mechhealth() - diag_hud_set_mechcell() - diag_hud_set_mechstat() - return + return attacked_by(W, user) + +/obj/mecha/proc/attacked_by(obj/item/I, mob/user) + log_message("Attacked by [I]. Attacker - [user]") + var/deflection = deflect_chance + var/dam_coeff = 1 + for(var/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/B in equipment) + if(B.attack_react(user)) + deflection *= B.deflect_coeff + dam_coeff *= B.damage_coeff + break + if(prob(deflection)) + to_chat(user, "[I] bounces off [src]\s armor.") + log_append_to_last("Armor saved.") + else + user.visible_message("[user] hits [src] with [I].", "You hit [src] with [I].") + take_damage(round(I.force * dam_coeff), I.damtype) + check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + /obj/mecha/emag_act(user as mob) if(istype(src, /obj/mecha/working/ripley) && emagged == 0) emagged = 1 to_chat(usr, "\blue You slide the card through the [src]'s ID slot.") - playsound(src.loc, "sparks", 100, 1) - src.desc += "
The mech's equipment slots spark dangerously!" + playsound(loc, "sparks", 100, 1) + desc += "
The mech's equipment slots spark dangerously!" else to_chat(usr, "\red The [src]'s ID slot rejects the card.") return @@ -1033,7 +946,6 @@ var/turf/T = get_turf(src) if(T) . = T.return_air() - return /obj/mecha/remove_air(amount) if(use_internal_tank) @@ -1042,7 +954,6 @@ var/turf/T = get_turf(src) if(T) return T.remove_air(amount) - return /obj/mecha/return_air() if(use_internal_tank) @@ -1050,25 +961,15 @@ return get_turf_air() /obj/mecha/proc/return_pressure() - . = 0 - if(use_internal_tank) - . = cabin_air.return_pressure() - else - var/datum/gas_mixture/t_air = get_turf_air() - if(t_air) - . = t_air.return_pressure() - return + var/datum/gas_mixture/t_air = return_air() + if(t_air) + . = t_air.return_pressure() //skytodo: //No idea what you want me to do here, mate. /obj/mecha/proc/return_temperature() - . = 0 - if(use_internal_tank) - . = cabin_air.return_temperature() - else - var/datum/gas_mixture/t_air = get_turf_air() - if(t_air) - . = t_air.return_temperature() - return + var/datum/gas_mixture/t_air = return_air() + if(t_air) + . = t_air.return_temperature() /obj/mecha/proc/connect(obj/machinery/atmospherics/unary/portables_connector/new_port) //Make sure not already connected to something else @@ -1076,7 +977,7 @@ return 0 //Make sure are close enough for a valid connection - if(new_port.loc != src.loc) + if(new_port.loc != loc) return 0 //Perform the connection @@ -1093,7 +994,7 @@ connected_port.connected_device = null connected_port = null - src.log_message("Disconnected from gas port.") + log_message("Disconnected from gas port.") return 1 /obj/mecha/portableConnectorReturnAir() @@ -1110,21 +1011,21 @@ set category = "Exosuit Interface" set src = usr.loc set popup_menu = 0 - if(!src.occupant) return - if(usr!=src.occupant) + if(!occupant) return + if(usr!=occupant) return var/obj/machinery/atmospherics/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/unary/portables_connector/) in loc if(possible_port) if(connect(possible_port)) - src.occupant_message("\blue [name] connects to the port.") - src.verbs += /obj/mecha/verb/disconnect_from_port - src.verbs -= /obj/mecha/verb/connect_to_port + occupant_message("\blue [name] connects to the port.") + verbs += /obj/mecha/verb/disconnect_from_port + verbs -= /obj/mecha/verb/connect_to_port return else - src.occupant_message("\red [name] failed to connect to the port.") + occupant_message("\red [name] failed to connect to the port.") return else - src.occupant_message("Nothing happens") + occupant_message("Nothing happens") /obj/mecha/verb/disconnect_from_port() @@ -1132,15 +1033,15 @@ set category = "Exosuit Interface" set src = usr.loc set popup_menu = 0 - if(!src.occupant) return - if(usr!=src.occupant) + if(!occupant) return + if(usr!=occupant) return if(disconnect()) - src.occupant_message("\blue [name] disconnects from the port.") - src.verbs -= /obj/mecha/verb/disconnect_from_port - src.verbs += /obj/mecha/verb/connect_to_port + occupant_message("\blue [name] disconnects from the port.") + verbs -= /obj/mecha/verb/disconnect_from_port + verbs += /obj/mecha/verb/connect_to_port else - src.occupant_message("\red [name] is not connected to the port at the moment.") + occupant_message("\red [name] is not connected to the port at the moment.") /obj/mecha/verb/toggle_lights() set name = "Toggle Lights" @@ -1151,7 +1052,7 @@ lights = !lights if(lights) set_light(light_range + lights_power) else set_light(light_range - lights_power) - src.occupant_message("Toggled lights [lights?"on":"off"].") + occupant_message("Toggled lights [lights?"on":"off"].") log_message("Toggled lights [lights?"on":"off"].") return @@ -1161,98 +1062,103 @@ set category = "Exosuit Interface" set src = usr.loc set popup_menu = 0 - if(usr!=src.occupant) + if(usr!=occupant) return use_internal_tank = !use_internal_tank - src.occupant_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].") - src.log_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].") + occupant_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].") + log_message("Now taking air from [use_internal_tank?"internal airtank":"environment"].") return -/obj/mecha/MouseDrop_T(mob/M as mob, mob/user as mob) - if(user.restrained() || user.stat || user.weakened || user.stunned || user.paralysis || user.resting) //are you cuffed, dying, lying, stunned or other +/obj/mecha/MouseDrop_T(mob/M, mob/user) + if(user.incapacitated()) return if(user != M) return - src.log_message("[user] tries to move in.") - if(src.occupant) - to_chat(usr, "The [src.name] is already occupied!") - src.log_append_to_last("Permission denied.") + log_message("[user] tries to move in.") + if(occupant) + to_chat(user, "The [src] is already occupied!") + log_append_to_last("Permission denied.") return var/passed - if(src.dna) - if(user.stat || ishuman(user)) - if(user.dna.unique_enzymes==src.dna) + if(dna) + if(ishuman(user)) + if(user.dna.unique_enzymes == dna) passed = 1 - else if(src.operation_allowed(user)) + else if(operation_allowed(user)) passed = 1 if(!passed) to_chat(user, "Access denied.") - src.log_append_to_last("Permission denied.") + log_append_to_last("Permission denied.") + return + if(user.buckled) + to_chat(user, "You are currently buckled and cannot move.") + log_append_to_last("Permission denied.") + return + if(user.has_buckled_mobs()) //mob attached to us + to_chat(user, "You can't enter the exosuit with other creatures attached to you!") return for(var/mob/living/carbon/slime/S in range(1,user)) if(S.Victim == user) to_chat(user, "You're too busy getting your life sucked out of you.") return - visible_message("[user] starts to climb into [src.name]") + visible_message("[user] starts to climb into [src]") - if(enter_after(40,user)) - if(!src.occupant) + if(do_after(user, 40, target = src)) + if(health <= 0) + to_chat(user, "You cannot get in the [name], it has been destroyed!") + else if(occupant) + to_chat(user, "[occupant] was faster! Try better next time, loser.") + else if(user.buckled) + to_chat(user, "You can't enter the exosuit while buckled.") + else if(user.has_buckled_mobs()) + to_chat(user, "You can't enter the exosuit with other creatures attached to you!") + else moved_inside(user) - else if(src.occupant!=user) - to_chat(user, "[src.occupant] was faster. Try better next time, loser.") else - to_chat(user, "You stop entering the exosuit.") - return + to_chat(user, "You stop entering the exosuit!") /obj/mecha/proc/moved_inside(var/mob/living/carbon/human/H as mob) if(H && H.client && H in range(1)) - H.reset_view(src) - /* - H.client.perspective = EYE_PERSPECTIVE - H.client.eye = src - */ + occupant = H H.stop_pulling() H.forceMove(src) - src.occupant = H - src.add_fingerprint(H) - src.forceMove(src.loc) - src.log_append_to_last("[H] moved in as pilot.") - src.icon_state = src.reset_icon() + H.reset_view(src) + add_fingerprint(H) + //GrantActions(H, human_occupant=1) + forceMove(loc) + log_append_to_last("[H] moved in as pilot.") + icon_state = reset_icon() dir = dir_in playsound(src, 'sound/machines/windowdoor.ogg', 50, 1) if(!hasInternalDamage()) - occupant << sound('sound/mecha/nominal.ogg',volume=50) + occupant << sound('sound/mecha/nominal.ogg', volume = 50) return 1 else return 0 /obj/mecha/proc/mmi_move_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob) if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client) - to_chat(user, "Consciousness matrix not detected.") + to_chat(user, "Consciousness matrix not detected!") return 0 else if(mmi_as_oc.brainmob.stat) - to_chat(user, "Beta-rhythm below acceptable level.") + to_chat(user, "Beta-rhythm below acceptable level!") return 0 else if(occupant) - to_chat(user, "Occupant detected.") + to_chat(user, "Occupant detected!") return 0 - else if(dna && dna!=mmi_as_oc.brainmob.dna.unique_enzymes) - to_chat(user, "Stop it!") + else if(dna && dna != mmi_as_oc.brainmob.dna.unique_enzymes) + to_chat(user, "Access denied. [name] is secured with a DNA lock.") return 0 - //Added a message here since people assume their first click failed or something./N -// to_chat(user, "Installing MMI, please stand by.") - visible_message("\blue [usr] starts to insert an MMI into [src.name]") - - if(enter_after(40,user)) + if(do_after(user, 40, target = src)) if(!occupant) return mmi_moved_inside(mmi_as_oc,user) else - to_chat(user, "Occupant detected.") + to_chat(user, "Occupant detected!") else - to_chat(user, "You stop inserting the MMI.") + to_chat(user, "You stop inserting the MMI.") return 0 /obj/mecha/proc/mmi_moved_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob) @@ -1277,14 +1183,14 @@ brainmob.canmove = 1 mmi_as_oc.loc = src mmi_as_oc.mecha = src - src.verbs -= /obj/mecha/verb/eject - src.Entered(mmi_as_oc) - src.Move(src.loc) - src.icon_state = src.reset_icon() + verbs -= /obj/mecha/verb/eject + Entered(mmi_as_oc) + Move(loc) + icon_state = reset_icon() dir = dir_in - src.log_message("[mmi_as_oc] moved in as pilot.") + log_message("[mmi_as_oc] moved in as pilot.") if(!hasInternalDamage()) - to_chat(src.occupant, sound('sound/mecha/nominal.ogg',volume=50)) + to_chat(occupant, sound('sound/mecha/nominal.ogg',volume=50)) return 1 else return 0 @@ -1306,88 +1212,65 @@ set category = "Exosuit Interface" set src = usr.loc set popup_menu = 0 - if(usr!=src.occupant) + if(usr!=occupant) return - //pr_update_stats.start() - src.occupant << browse(src.get_stats_html(), "window=exosuit") + occupant << browse(get_stats_html(), "window=exosuit") return -/* -/obj/mecha/verb/force_eject() - set category = "Object" - set name = "Force Eject" - set src in view(5) - src.go_out() - return -*/ - /obj/mecha/verb/eject() set name = "Eject" set category = "Exosuit Interface" set src = usr.loc set popup_menu = 0 - if(usr!=src.occupant) + if(usr != occupant) return - src.go_out() + go_out() add_fingerprint(usr) - return -/obj/mecha/proc/go_out(var/forced) - if(!src.occupant) return +/obj/mecha/Exited(atom/movable/M, atom/newloc) + if(occupant && occupant == M) // The occupant exited the mech without calling go_out() + go_out(1, newloc) + +/obj/mecha/proc/go_out(var/forced, var/atom/newloc = loc) + if(!occupant) + return var/atom/movable/mob_container + occupant.clear_alert("charge") + occupant.clear_alert("mech damage") if(ishuman(occupant)) - mob_container = src.occupant + mob_container = occupant + //RemoveActions(occupant, human_occupant=1) else if(istype(occupant, /mob/living/carbon/brain)) var/mob/living/carbon/brain/brain = occupant + //RemoveActions(brain) mob_container = brain.container else if(isAI(occupant) && forced) //This should only happen if there are multiple AIs in a round, and at least one is Malf. + //RemoveActions(occupant) occupant.gib() //If one Malf decides to steal a mech from another AI (even other Malfs!), they are destroyed, as they have nowhere to go when replaced. occupant = null return else return - if(mob_container.forceMove(src.loc))//ejecting mob container - /* - if(ishuman(occupant) && (return_pressure() > HAZARD_HIGH_PRESSURE)) - use_internal_tank = 0 - var/datum/gas_mixture/environment = get_turf_air() - if(environment) - var/env_pressure = environment.return_pressure() - var/pressure_delta = (cabin.return_pressure() - env_pressure) - //Can not have a pressure delta that would cause environment pressure > tank pressure + var/mob/living/L = occupant + occupant = null //we need it null when forceMove calls Exited(). + if(mob_container.forceMove(newloc))//ejecting mob container + log_message("[mob_container] moved out.") + L << browse(null, "window=exosuit") - var/transfer_moles = 0 - if(pressure_delta > 0) - transfer_moles = pressure_delta*environment.volume/(cabin.return_temperature() * R_IDEAL_GAS_EQUATION) - - //Actually transfer the gas - var/datum/gas_mixture/removed = cabin.air_contents.remove(transfer_moles) - loc.assume_air(removed) - - occupant.SetStunned(5) - occupant.SetWeakened(5) - to_chat(occupant, "You were blown out of the mech!") - */ - src.log_message("[mob_container] moved out.") - occupant.reset_view() - /* - if(src.occupant.client) - src.occupant.client.eye = src.occupant.client.mob - src.occupant.client.perspective = MOB_PERSPECTIVE - */ - src.occupant << browse(null, "window=exosuit") - if(istype(mob_container, /obj/item/device/mmi) || istype(mob_container, /obj/item/device/mmi/posibrain)) + if(istype(mob_container, /obj/item/device/mmi)) var/obj/item/device/mmi/mmi = mob_container if(mmi.brainmob) - occupant.loc = mmi + L.loc = mmi + L.reset_view() mmi.mecha = null - src.occupant.canmove = 0 - src.verbs += /obj/mecha/verb/eject - src.occupant = null - src.icon_state = src.reset_icon()+"-open" - src.dir = dir_in - return + mmi.update_icon() + L.canmove = 0 + icon_state = initial(icon_state)+"-open" + dir = dir_in + + if(L && L.client) + L.client.view = world.view ///////////////////////// ////// Access stuff ///// @@ -1397,14 +1280,14 @@ if(!ishuman(H)) return 0 for(var/ID in list(H.get_active_hand(), H.wear_id, H.belt)) - if(src.check_access(ID,src.operation_req_access)) + if(check_access(ID,operation_req_access)) return 1 return 0 /obj/mecha/proc/internals_access_allowed(mob/living/carbon/human/H) for(var/atom/ID in list(H.get_active_hand(), H.wear_id, H.belt)) - if(src.check_access(ID,src.internals_req_access)) + if(check_access(ID,internals_req_access)) return 1 return 0 @@ -1419,410 +1302,16 @@ I = pda.id if(!istype(I) || !I.access) //not ID or no access return 0 - if(access_list==src.operation_req_access) + if(access_list==operation_req_access) for(var/req in access_list) if(!(req in I.access)) //doesn't have this access return 0 - else if(access_list==src.internals_req_access) + else if(access_list==internals_req_access) for(var/req in access_list) if(req in I.access) return 1 return 1 - -//////////////////////////////////// -///// Rendering stats window /////// -//////////////////////////////////// - -/obj/mecha/proc/get_stats_html() - var/output = {" - [src.name] data - - - - -
- [src.get_stats_part()] -
-
- [src.get_equipment_list()] -
-
-
- [src.get_commands()] -
- - - "} - return output - - -/obj/mecha/proc/report_internal_damage() - var/output = null - var/list/dam_reports = list( - "[MECHA_INT_FIRE]" = "INTERNAL FIRE", - "[MECHA_INT_TEMP_CONTROL]" = "LIFE SUPPORT SYSTEM MALFUNCTION", - "[MECHA_INT_TANK_BREACH]" = "GAS TANK BREACH", - "[MECHA_INT_CONTROL_LOST]" = "COORDINATION SYSTEM CALIBRATION FAILURE - Recalibrate", - "[MECHA_INT_SHORT_CIRCUIT]" = "SHORT CIRCUIT" - ) - for(var/tflag in dam_reports) - var/intdamflag = text2num(tflag) - if(hasInternalDamage(intdamflag)) - output += dam_reports[tflag] - output += "
" - if(return_pressure() > WARNING_HIGH_PRESSURE) - output += "DANGEROUSLY HIGH CABIN PRESSURE
" - return output - - -/obj/mecha/proc/get_stats_part() - var/integrity = health/initial(health)*100 - var/cell_charge = get_charge() - var/tank_pressure = internal_tank ? round(internal_tank.return_pressure(),0.01) : "None" - var/tank_temperature = internal_tank ? internal_tank.return_temperature() : "Unknown" - var/cabin_pressure = round(return_pressure(),0.01) - var/output = {"[report_internal_damage()] - [integrity<30?"DAMAGE LEVEL CRITICAL
":null] - Integrity: [integrity]%
- Powercell charge: [isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]
- Air source: [use_internal_tank?"Internal Airtank":"Environment"]
- Airtank pressure: [tank_pressure]kPa
- Airtank temperature: [tank_temperature]°K|[tank_temperature - T0C]°C
- Cabin pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
- Cabin temperature: [return_temperature()]°K|[return_temperature() - T0C]°C
- Lights: [lights?"on":"off"]
- [src.dna?"DNA-locked:
[src.dna] \[Reset\]
":null] - "} - return output - -/obj/mecha/proc/get_commands() - var/output = {"
-
Electronics
- -
-
-
Airtank
- -
- -
[get_equipment_menu()]
-
- [(/obj/mecha/verb/eject in src.verbs)?"Eject
":null] - "} - return output - -/obj/mecha/proc/get_equipment_menu() //outputs mecha html equipment menu - var/output - if(equipment.len) - output += {"
-
Equipment
-
" - return output - -/obj/mecha/proc/get_equipment_list() //outputs mecha equipment list in html - if(!equipment.len) - return - var/output = "Equipment:
" - for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment) - output += "
[MT.get_equip_info()]
" - output += "
" - return output - - -/obj/mecha/proc/get_log_html() - var/output = "[src.name] Log" - for(var/list/entry in log) - output += {"
[time2text(entry["time"],"DDD MMM DD hh:mm:ss")] 2555
-
[entry["message"]]
- "} - output += "" - return output - - -/obj/mecha/proc/output_access_dialog(obj/item/weapon/card/id/id_card, mob/user) - if(!id_card || !user) return - var/output = {" - - - -

Following keycodes are present in this system:

"} - for(var/a in operation_req_access) - output += "[get_access_desc(a)] - Delete
" - output += "

Following keycodes were detected on portable device:

" - for(var/a in id_card.access) - if(a in operation_req_access) continue - var/a_name = get_access_desc(a) - if(!a_name) continue //there's some strange access without a name - output += "[a_name] - Add
" - output += "
Finish (Warning! The ID upload panel will be locked. It can be unlocked only through Exosuit Interface.)" - output += "" - user << browse(output, "window=exosuit_add_access") - onclose(user, "exosuit_add_access") - return - -/obj/mecha/proc/output_maintenance_dialog(obj/item/weapon/card/id/id_card,mob/user) - if(!id_card || !user) return - var/output = {" - - - - - [add_req_access?"Edit operation keycodes":null] - [maint_access?"Initiate maintenance protocol":null] - [(state>0) ?"Set Cabin Air Pressure":null] - - "} - user << browse(output, "window=exosuit_maint_console") - onclose(user, "exosuit_maint_console") - return - - -//////////////////////////////// -/////// Messages and Log /////// -//////////////////////////////// - -/obj/mecha/proc/occupant_message(message as text) - if(message) - if(src.occupant && src.occupant.client) - to_chat(src.occupant, "[bicon(src)] [message]") - return - -/obj/mecha/proc/log_message(message as text,red=null) - log.len++ - log[log.len] = list("time"=world.timeofday,"message"="[red?"":null][message][red?"":null]") - return log.len - -/obj/mecha/proc/log_append_to_last(message as text,red=null) - var/list/last_entry = src.log[src.log.len] - last_entry["message"] += "
[red?"":null][message][red?"":null]" - return - - -///////////////// -///// Topic ///// -///////////////// - -/obj/mecha/Topic(href, href_list) - ..() - if(href_list["update_content"]) - if(usr != src.occupant) return - send_byjax(src.occupant,"exosuit.browser","content",src.get_stats_part()) - return - if(href_list["close"]) - return - if(usr.stat > 0) - return - var/datum/topic_input/filter = new /datum/topic_input(href,href_list) - if(href_list["select_equip"]) - if(usr != src.occupant) return - var/obj/item/mecha_parts/mecha_equipment/equip = filter.getObj("select_equip") - if(equip) - src.selected = equip - src.occupant_message("You switch to [equip]") - src.visible_message("[src] raises [equip]") - send_byjax(src.occupant,"exosuit.browser","eq_list",src.get_equipment_list()) - return - if(href_list["eject"]) - if(usr != src.occupant) return - src.eject() - return - if(href_list["toggle_lights"]) - if(usr != src.occupant) return - src.toggle_lights() - return - if(href_list["toggle_airtank"]) - if(usr != src.occupant) return - src.toggle_internal_tank() - return - if(href_list["rmictoggle"]) - if(usr != src.occupant) return - radio.broadcasting = !radio.broadcasting - send_byjax(src.occupant,"exosuit.browser","rmicstate",(radio.broadcasting?"Engaged":"Disengaged")) - return - if(href_list["rspktoggle"]) - if(usr != src.occupant) return - radio.listening = !radio.listening - send_byjax(src.occupant,"exosuit.browser","rspkstate",(radio.listening?"Engaged":"Disengaged")) - return - if(href_list["rfreq"]) - if(usr != src.occupant) return - var/new_frequency = (radio.frequency + filter.getNum("rfreq")) - if((radio.frequency < PUBLIC_LOW_FREQ || radio.frequency > PUBLIC_HIGH_FREQ)) - new_frequency = sanitize_frequency(new_frequency) - radio.set_frequency(new_frequency) - send_byjax(src.occupant,"exosuit.browser","rfreq","[format_frequency(radio.frequency)]") - return - if(href_list["port_disconnect"]) - if(usr != src.occupant) return - src.disconnect_from_port() - return - if(href_list["port_connect"]) - if(usr != src.occupant) return - src.connect_to_port() - return - if(href_list["view_log"]) - if(usr != src.occupant) return - src.occupant << browse(src.get_log_html(), "window=exosuit_log") - onclose(occupant, "exosuit_log") - return - if(href_list["change_name"]) - if(usr != src.occupant) return - var/newname = strip_html_simple(input(occupant,"Choose new exosuit name","Rename exosuit",initial(name)) as text, MAX_NAME_LEN) - if(newname && trim(newname)) - name = newname - else - alert(occupant, "nope.avi") - return - if(href_list["toggle_id_upload"]) - if(usr != src.occupant) return - add_req_access = !add_req_access - send_byjax(src.occupant,"exosuit.browser","t_id_upload","[add_req_access?"L":"Unl"]ock ID upload panel") - return - if(href_list["toggle_maint_access"]) - if(usr != src.occupant) return - if(state) - occupant_message("Maintenance protocols in effect") - return - maint_access = !maint_access - send_byjax(src.occupant,"exosuit.browser","t_maint_access","[maint_access?"Forbid":"Permit"] maintenance protocols") - return - if(href_list["req_access"] && add_req_access) - if(!in_range(src, usr)) return - output_access_dialog(filter.getObj("id_card"),filter.getMob("user")) - return - if(href_list["maint_access"] && maint_access) - if(!in_range(src, usr)) return - var/mob/user = filter.getMob("user") - if(user) - if(state==0) - state = 1 - to_chat(user, "The securing bolts are now exposed.") - else if(state==1) - state = 0 - to_chat(user, "The securing bolts are now hidden.") - output_maintenance_dialog(filter.getObj("id_card"),user) - return - if(href_list["set_internal_tank_valve"] && state >=1) - if(!in_range(src, usr)) return - var/mob/user = filter.getMob("user") - if(user) - var/new_pressure = input(user,"Input new output pressure","Pressure setting",internal_tank_valve) as num - if(new_pressure) - internal_tank_valve = new_pressure - to_chat(user, "The internal pressure valve has been set to [internal_tank_valve]kPa.") - if(href_list["add_req_access"] && add_req_access && filter.getObj("id_card")) - if(!in_range(src, usr)) return - operation_req_access += filter.getNum("add_req_access") - output_access_dialog(filter.getObj("id_card"),filter.getMob("user")) - return - if(href_list["del_req_access"] && add_req_access && filter.getObj("id_card")) - if(!in_range(src, usr)) return - operation_req_access -= filter.getNum("del_req_access") - output_access_dialog(filter.getObj("id_card"),filter.getMob("user")) - return - if(href_list["finish_req_access"]) - if(!in_range(src, usr)) return - add_req_access = 0 - var/mob/user = filter.getMob("user") - user << browse(null,"window=exosuit_add_access") - return - if(href_list["dna_lock"]) - if(usr != src.occupant) - return - if(src.occupant && !iscarbon(src.occupant)) - to_chat(src.occupant, "You do not have any DNA!") - return - src.dna = src.occupant.dna.unique_enzymes - src.occupant_message("You feel a prick as the needle takes your DNA sample.") - return - if(href_list["reset_dna"]) - if(usr != src.occupant) return - src.dna = null - if(href_list["repair_int_control_lost"]) - if(usr != src.occupant) return - src.occupant_message("Recalibrating coordination system.") - src.log_message("Recalibration of coordination system started.") - var/T = src.loc - if(mecha_do_after(100)) - if(T == src.loc) - src.clearInternalDamage(MECHA_INT_CONTROL_LOST) - src.occupant_message("Recalibration successful.") - src.log_message("Recalibration of coordination system finished with 0 errors.") - else - src.occupant_message("Recalibration failed.") - src.log_message("Recalibration of coordination system failed with 1 error.",1) - - //debug - /* - if(href_list["debug"]) - if(href_list["set_i_dam"]) - setInternalDamage(filter.getNum("set_i_dam")) - if(href_list["clear_i_dam"]) - clearInternalDamage(filter.getNum("clear_i_dam")) - return - */ - - return - /////////////////////// ///// Power stuff ///// /////////////////////// @@ -1834,9 +1323,9 @@ return call((proc_res["dyngetcharge"]||src), "dyngetcharge")() /obj/mecha/proc/dyngetcharge()//returns null if no powercell, else returns cell.charge - if(!src.cell) return + if(!cell) return diag_hud_set_mechcell() - return max(0, src.cell.charge) + return max(0, cell.charge) /obj/mecha/proc/use_power(amount) return call((proc_res["dynusepower"]||src), "dynusepower")(amount) @@ -1872,122 +1361,88 @@ //////// Mecha global iterators //////// ////////////////////////////////////////// +/obj/mecha/process() + process_internal_damage() + regulate_temp() + give_air() + update_huds() -/datum/global_iterator/mecha_preserve_temp //normalizing cabin air temperature to 20 degrees celsium - delay = 20 - - process(var/obj/mecha/mecha) - if(mecha.cabin_air && mecha.cabin_air.return_volume() > 0) - var/delta = mecha.cabin_air.temperature - T20C - mecha.cabin_air.temperature -= max(-10, min(10, round(delta/4,0.1))) +/obj/mecha/proc/process_internal_damage() + if(!internal_damage) return -/datum/global_iterator/mecha_tank_give_air - delay = 15 + if(internal_damage & MECHA_INT_FIRE) + if(!(internal_damage & MECHA_INT_TEMP_CONTROL) && prob(5)) + clearInternalDamage(MECHA_INT_FIRE) + if(internal_tank) + var/datum/gas_mixture/int_tank_air = internal_tank.return_air() + if(int_tank_air.return_pressure() > internal_tank.maximum_pressure && !(internal_damage & MECHA_INT_TANK_BREACH)) + setInternalDamage(MECHA_INT_TANK_BREACH) - process(var/obj/mecha/mecha) - if(mecha.internal_tank) - var/datum/gas_mixture/tank_air = mecha.internal_tank.return_air() - var/datum/gas_mixture/cabin_air = mecha.cabin_air + if(int_tank_air && int_tank_air.return_volume() > 0) + int_tank_air.temperature = min(6000 + T0C, cabin_air.return_temperature() + rand(10, 15)) - var/release_pressure = mecha.internal_tank_valve - var/cabin_pressure = cabin_air.return_pressure() - var/pressure_delta = min(release_pressure - cabin_pressure, (tank_air.return_pressure() - cabin_pressure)/2) - var/transfer_moles = 0 - if(pressure_delta > 0) //cabin pressure lower than release pressure - if(tank_air.return_temperature() > 0) - transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) - var/datum/gas_mixture/removed = tank_air.remove(transfer_moles) - cabin_air.merge(removed) - else if(pressure_delta < 0) //cabin pressure higher than release pressure - var/datum/gas_mixture/t_air = mecha.get_turf_air() - pressure_delta = cabin_pressure - release_pressure - if(t_air) - pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta) - if(pressure_delta > 0) //if location pressure is lower than cabin pressure - transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) - var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles) - if(t_air) - t_air.merge(removed) - else //just delete the cabin gas, we're in space or some shit - qdel(removed) - else - return stop() + if(cabin_air && cabin_air.return_volume()>0) + cabin_air.temperature = min(6000+T0C, cabin_air.return_temperature()+rand(10,15)) + if(cabin_air.return_temperature() > max_temperature/2) + take_damage(4/round(max_temperature/cabin_air.return_temperature(),0.1),"fire") + + if(internal_damage & MECHA_INT_TANK_BREACH) //remove some air from internal tank + if(internal_tank) + var/datum/gas_mixture/int_tank_air = internal_tank.return_air() + var/datum/gas_mixture/leaked_gas = int_tank_air.remove_ratio(0.10) + if(loc) + loc.assume_air(leaked_gas) + air_update_turf() + else + qdel(leaked_gas) + + if(internal_damage & MECHA_INT_SHORT_CIRCUIT) + if(get_charge()) + spark_system.start() + cell.charge -= min(20,cell.charge) + cell.maxcharge -= min(20,cell.maxcharge) + +/obj/mecha/proc/regulate_temp() + if(internal_damage & MECHA_INT_TEMP_CONTROL) return + if(cabin_air && cabin_air.return_volume() > 0) + var/delta = cabin_air.temperature - T20C + cabin_air.temperature -= max(-10, min(10, round(delta / 4, 0.1))) -/datum/global_iterator/mecha_internal_damage // processing internal damage - - process(var/obj/mecha/mecha) - if(!mecha.hasInternalDamage()) - return stop() - if(mecha.hasInternalDamage(MECHA_INT_FIRE)) - if(!mecha.hasInternalDamage(MECHA_INT_TEMP_CONTROL) && prob(5)) - mecha.clearInternalDamage(MECHA_INT_FIRE) - if(mecha.internal_tank) - if(mecha.internal_tank.return_pressure()>mecha.internal_tank.maximum_pressure && !(mecha.hasInternalDamage(MECHA_INT_TANK_BREACH))) - mecha.setInternalDamage(MECHA_INT_TANK_BREACH) - var/datum/gas_mixture/int_tank_air = mecha.internal_tank.return_air() - if(int_tank_air && int_tank_air.return_volume()>0) //heat the air_contents - int_tank_air.temperature = min(6000+T0C, int_tank_air.temperature+rand(10,15)) - if(mecha.cabin_air && mecha.cabin_air.return_volume()>0) - mecha.cabin_air.temperature = min(6000+T0C, mecha.cabin_air.return_temperature()+rand(10,15)) - if(mecha.cabin_air.return_temperature()>mecha.max_temperature/2) - mecha.take_damage(4/round(mecha.max_temperature/mecha.cabin_air.return_temperature(),0.1),"fire") - if(mecha.hasInternalDamage(MECHA_INT_TEMP_CONTROL)) //stop the mecha_preserve_temp loop datum - mecha.pr_int_temp_processor.stop() - if(mecha.hasInternalDamage(MECHA_INT_TANK_BREACH)) //remove some air from internal tank - if(mecha.internal_tank) - var/datum/gas_mixture/int_tank_air = mecha.internal_tank.return_air() - var/datum/gas_mixture/leaked_gas = int_tank_air.remove_ratio(0.10) - if(mecha.loc && hascall(mecha.loc,"assume_air")) - mecha.loc.assume_air(leaked_gas) - else - qdel(leaked_gas) - if(mecha.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) - if(mecha.get_charge()) - mecha.spark_system.start() - mecha.cell.charge -= min(20,mecha.cell.charge) - mecha.cell.maxcharge -= min(20,mecha.cell.maxcharge) +/obj/mecha/proc/give_air() + if(!internal_tank) return + var/datum/gas_mixture/tank_air = internal_tank.return_air() -///////////// + var/release_pressure = internal_tank_valve + var/cabin_pressure = cabin_air.return_pressure() + var/pressure_delta = min(release_pressure - cabin_pressure, (tank_air.return_pressure() - cabin_pressure)/2) + var/transfer_moles = 0 + if(pressure_delta > 0) //cabin pressure lower than release pressure + if(tank_air.return_temperature() > 0) + transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) + var/datum/gas_mixture/removed = tank_air.remove(transfer_moles) + cabin_air.merge(removed) + else if(pressure_delta < 0) //cabin pressure higher than release pressure + var/datum/gas_mixture/t_air = return_air() + pressure_delta = cabin_pressure - release_pressure + if(t_air) + pressure_delta = min(cabin_pressure - t_air.return_pressure(), pressure_delta) + if(pressure_delta > 0) //if location pressure is lower than cabin pressure + transfer_moles = pressure_delta*cabin_air.return_volume()/(cabin_air.return_temperature() * R_IDEAL_GAS_EQUATION) + var/datum/gas_mixture/removed = cabin_air.remove(transfer_moles) + if(t_air) + t_air.merge(removed) + else //just delete the cabin gas, we're in space or some shit + qdel(removed) -//debug -/* -/obj/mecha/verb/test_int_damage() - set name = "Test internal damage" - set category = "Exosuit Interface" - set src in view(0) - if(!occupant) return - if(usr!=occupant) - return - var/output = {" - - - -

Set:

- MECHA_INT_FIRE
- MECHA_INT_TEMP_CONTROL
- MECHA_INT_SHORT_CIRCUIT
- MECHA_INT_TANK_BREACH
- MECHA_INT_CONTROL_LOST
-
-

Clear:

- MECHA_INT_FIRE
- MECHA_INT_TEMP_CONTROL
- MECHA_INT_SHORT_CIRCUIT
- MECHA_INT_TANK_BREACH
- MECHA_INT_CONTROL_LOST
- - "} - - occupant << browse(output, "window=ex_debug") - //src.health = initial(src.health)/2.2 - //src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) - return -*/ +/obj/mecha/proc/update_huds() + diag_hud_set_mechhealth() + diag_hud_set_mechcell() + diag_hud_set_mechstat() /obj/mecha/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list()) diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm new file mode 100644 index 00000000000..c24a85b6967 --- /dev/null +++ b/code/game/mecha/mecha_topic.dm @@ -0,0 +1,393 @@ + +//////////////////////////////////// +///// Rendering stats window /////// +//////////////////////////////////// + +/obj/mecha/proc/get_stats_html() + var/output = {" + [name] data + + + + +
+ [get_stats_part()] +
+
+ [get_equipment_list()] +
+
+
+ [get_commands()] +
+ + + "} + return output + + +/obj/mecha/proc/report_internal_damage() + var/output = null + var/list/dam_reports = list( + "[MECHA_INT_FIRE]" = "INTERNAL FIRE", + "[MECHA_INT_TEMP_CONTROL]" = "LIFE SUPPORT SYSTEM MALFUNCTION", + "[MECHA_INT_TANK_BREACH]" = "GAS TANK BREACH", + "[MECHA_INT_CONTROL_LOST]" = "COORDINATION SYSTEM CALIBRATION FAILURE - Recalibrate", + "[MECHA_INT_SHORT_CIRCUIT]" = "SHORT CIRCUIT" + ) + for(var/tflag in dam_reports) + var/intdamflag = text2num(tflag) + if(hasInternalDamage(intdamflag)) + output += dam_reports[tflag] + output += "
" + if(return_pressure() > WARNING_HIGH_PRESSURE) + output += "DANGEROUSLY HIGH CABIN PRESSURE
" + return output + + +/obj/mecha/proc/get_stats_part() + var/integrity = health/initial(health)*100 + var/cell_charge = get_charge() + var/tank_pressure = internal_tank ? round(internal_tank.return_pressure(),0.01) : "None" + var/tank_temperature = internal_tank ? internal_tank.return_temperature() : "Unknown" + var/cabin_pressure = round(return_pressure(),0.01) + var/output = {"[report_internal_damage()] + [integrity<30?"DAMAGE LEVEL CRITICAL
":null] + Integrity: [integrity]%
+ Powercell charge: [isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]
+ Air source: [use_internal_tank?"Internal Airtank":"Environment"]
+ Airtank pressure: [tank_pressure]kPa
+ Airtank temperature: [tank_temperature]°K|[tank_temperature - T0C]°C
+ Cabin pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
+ Cabin temperature: [return_temperature()]°K|[return_temperature() - T0C]°C
+ Lights: [lights?"on":"off"]
+ [dna?"DNA-locked:
[dna] \[Reset\]
":null] + "} + return output + +/obj/mecha/proc/get_commands() + var/output = {"
+
Electronics
+ +
+
+
Airtank
+ +
+ +
[get_equipment_menu()]
+
+ [(/obj/mecha/verb/eject in verbs)?"Eject
":null] + "} + return output + +/obj/mecha/proc/get_equipment_menu() //outputs mecha html equipment menu + var/output + if(equipment.len) + output += {"
+
Equipment
+
" + return output + +/obj/mecha/proc/get_equipment_list() //outputs mecha equipment list in html + if(!equipment.len) + return + var/output = "Equipment:
" + for(var/obj/item/mecha_parts/mecha_equipment/MT in equipment) + output += "
[MT.get_equip_info()]
" + output += "
" + return output + + +/obj/mecha/proc/get_log_html() + var/output = "[name] Log" + for(var/list/entry in log) + output += {"
[time2text(entry["time"],"DDD MMM DD hh:mm:ss")] 2555
+
[entry["message"]]
+ "} + output += "" + return output + + +/obj/mecha/proc/output_access_dialog(obj/item/weapon/card/id/id_card, mob/user) + if(!id_card || !user) return + var/output = {" + + + +

Following keycodes are present in this system:

"} + for(var/a in operation_req_access) + output += "[get_access_desc(a)] - Delete
" + output += "

Following keycodes were detected on portable device:

" + for(var/a in id_card.access) + if(a in operation_req_access) continue + var/a_name = get_access_desc(a) + if(!a_name) continue //there's some strange access without a name + output += "[a_name] - Add
" + output += "
Finish (Warning! The ID upload panel will be locked. It can be unlocked only through Exosuit Interface.)" + output += "" + user << browse(output, "window=exosuit_add_access") + onclose(user, "exosuit_add_access") + return + +/obj/mecha/proc/output_maintenance_dialog(obj/item/weapon/card/id/id_card,mob/user) + if(!id_card || !user) return + var/output = {" + + + + + [add_req_access?"Edit operation keycodes":null] + [maint_access?"Initiate maintenance protocol":null] + [(state>0) ?"Set Cabin Air Pressure":null] + + "} + user << browse(output, "window=exosuit_maint_console") + onclose(user, "exosuit_maint_console") + return + + +//////////////////////////////// +/////// Messages and Log /////// +//////////////////////////////// + +/obj/mecha/proc/occupant_message(message as text) + if(message) + if(occupant && occupant.client) + to_chat(occupant, "[bicon(src)] [message]") + return + +/obj/mecha/proc/log_message(message as text,red=null) + log.len++ + log[log.len] = list("time"=world.timeofday,"message"="[red?"":null][message][red?"":null]") + return log.len + +/obj/mecha/proc/log_append_to_last(message as text,red=null) + var/list/last_entry = log[log.len] + last_entry["message"] += "
[red?"":null][message][red?"":null]" + return + + +///////////////// +///// Topic ///// +///////////////// + +/obj/mecha/Topic(href, href_list) + ..() + if(href_list["update_content"]) + if(usr != occupant) return + send_byjax(occupant,"exosuit.browser","content",get_stats_part()) + return + if(href_list["close"]) + return + if(usr.stat > 0) + return + var/datum/topic_input/filter = new /datum/topic_input(href,href_list) + if(href_list["select_equip"]) + if(usr != occupant) return + var/obj/item/mecha_parts/mecha_equipment/equip = filter.getObj("select_equip") + if(equip) + selected = equip + occupant_message("You switch to [equip]") + visible_message("[src] raises [equip]") + send_byjax(occupant,"exosuit.browser","eq_list",get_equipment_list()) + return + if(href_list["eject"]) + if(usr != occupant) return + eject() + return + if(href_list["toggle_lights"]) + if(usr != occupant) return + toggle_lights() + return + if(href_list["toggle_airtank"]) + if(usr != occupant) return + toggle_internal_tank() + return + if(href_list["rmictoggle"]) + if(usr != occupant) return + radio.broadcasting = !radio.broadcasting + send_byjax(occupant,"exosuit.browser","rmicstate",(radio.broadcasting?"Engaged":"Disengaged")) + return + if(href_list["rspktoggle"]) + if(usr != occupant) return + radio.listening = !radio.listening + send_byjax(occupant,"exosuit.browser","rspkstate",(radio.listening?"Engaged":"Disengaged")) + return + if(href_list["rfreq"]) + if(usr != occupant) return + var/new_frequency = (radio.frequency + filter.getNum("rfreq")) + if((radio.frequency < PUBLIC_LOW_FREQ || radio.frequency > PUBLIC_HIGH_FREQ)) + new_frequency = sanitize_frequency(new_frequency) + radio.set_frequency(new_frequency) + send_byjax(occupant,"exosuit.browser","rfreq","[format_frequency(radio.frequency)]") + return + if(href_list["port_disconnect"]) + if(usr != occupant) return + disconnect_from_port() + return + if(href_list["port_connect"]) + if(usr != occupant) return + connect_to_port() + return + if(href_list["view_log"]) + if(usr != occupant) return + occupant << browse(get_log_html(), "window=exosuit_log") + onclose(occupant, "exosuit_log") + return + if(href_list["change_name"]) + if(usr != occupant) return + var/newname = strip_html_simple(input(occupant,"Choose new exosuit name","Rename exosuit",initial(name)) as text, MAX_NAME_LEN) + if(newname && trim(newname)) + name = newname + else + alert(occupant, "nope.avi") + return + if(href_list["toggle_id_upload"]) + if(usr != occupant) return + add_req_access = !add_req_access + send_byjax(occupant,"exosuit.browser","t_id_upload","[add_req_access?"L":"Unl"]ock ID upload panel") + return + if(href_list["toggle_maint_access"]) + if(usr != occupant) return + if(state) + occupant_message("Maintenance protocols in effect") + return + maint_access = !maint_access + send_byjax(occupant,"exosuit.browser","t_maint_access","[maint_access?"Forbid":"Permit"] maintenance protocols") + return + if(href_list["req_access"] && add_req_access) + if(!in_range(src, usr)) return + output_access_dialog(filter.getObj("id_card"),filter.getMob("user")) + return + if(href_list["maint_access"] && maint_access) + if(!in_range(src, usr)) return + var/mob/user = filter.getMob("user") + if(user) + if(state==0) + state = 1 + to_chat(user, "The securing bolts are now exposed.") + else if(state==1) + state = 0 + to_chat(user, "The securing bolts are now hidden.") + output_maintenance_dialog(filter.getObj("id_card"),user) + return + if(href_list["set_internal_tank_valve"] && state >=1) + if(!in_range(src, usr)) return + var/mob/user = filter.getMob("user") + if(user) + var/new_pressure = input(user,"Input new output pressure","Pressure setting",internal_tank_valve) as num + if(new_pressure) + internal_tank_valve = new_pressure + to_chat(user, "The internal pressure valve has been set to [internal_tank_valve]kPa.") + if(href_list["add_req_access"] && add_req_access && filter.getObj("id_card")) + if(!in_range(src, usr)) return + operation_req_access += filter.getNum("add_req_access") + output_access_dialog(filter.getObj("id_card"),filter.getMob("user")) + return + if(href_list["del_req_access"] && add_req_access && filter.getObj("id_card")) + if(!in_range(src, usr)) return + operation_req_access -= filter.getNum("del_req_access") + output_access_dialog(filter.getObj("id_card"),filter.getMob("user")) + return + if(href_list["finish_req_access"]) + if(!in_range(src, usr)) return + add_req_access = 0 + var/mob/user = filter.getMob("user") + user << browse(null,"window=exosuit_add_access") + return + if(href_list["dna_lock"]) + if(usr != occupant) + return + if(occupant && !iscarbon(occupant)) + to_chat(occupant, "You do not have any DNA!") + return + dna = occupant.dna.unique_enzymes + occupant_message("You feel a prick as the needle takes your DNA sample.") + return + if(href_list["reset_dna"]) + if(usr != occupant) return + dna = null + if(href_list["repair_int_control_lost"]) + if(usr != occupant) return + occupant_message("Recalibrating coordination system.") + log_message("Recalibration of coordination system started.") + var/T = loc + spawn(100) + if(T == loc) + clearInternalDamage(MECHA_INT_CONTROL_LOST) + occupant_message("Recalibration successful.") + log_message("Recalibration of coordination system finished with 0 errors.") + else + occupant_message("Recalibration failed.") + log_message("Recalibration of coordination system failed with 1 error.",1) + + //debug + /* + if(href_list["debug"]) + if(href_list["set_i_dam"]) + setInternalDamage(filter.getNum("set_i_dam")) + if(href_list["clear_i_dam"]) + clearInternalDamage(filter.getNum("clear_i_dam")) + return + */ + + return diff --git a/code/game/mecha/medical/medical.dm b/code/game/mecha/medical/medical.dm index a63a8d3d6dd..ce28687a9e6 100644 --- a/code/game/mecha/medical/medical.dm +++ b/code/game/mecha/medical/medical.dm @@ -1,22 +1,7 @@ +/obj/mecha/medical + turnsound = 'sound/mecha/mechmove01.ogg' + stepsound = 'sound/mecha/mechstep.ogg' + /obj/mecha/medical/New() ..() new /obj/item/mecha_parts/mecha_tracking(src) - return - - -/obj/mecha/medical/mechturn(direction) - dir = direction - playsound(src,'sound/mecha/mechmove01.ogg',40,1) - return 1 - -/obj/mecha/medical/mechstep(direction) - var/result = step(src,direction) - if(result) - playsound(src,'sound/mecha/mechstep.ogg',25,1) - return result - -/obj/mecha/medical/mechsteprand() - var/result = step_rand(src) - if(result) - playsound(src,'sound/mecha/mechstep.ogg',25,1) - return result \ No newline at end of file diff --git a/code/game/mecha/medical/odysseus.dm b/code/game/mecha/medical/odysseus.dm index deb3df8b4fc..b7a320adc77 100644 --- a/code/game/mecha/medical/odysseus.dm +++ b/code/game/mecha/medical/odysseus.dm @@ -12,44 +12,35 @@ step_energy_drain = 6 var/builtin_hud_user = 0 - moved_inside(var/mob/living/carbon/human/H as mob) - if(..()) - if(H.glasses && istype(H.glasses, /obj/item/clothing/glasses/hud)) - occupant_message("Your [H.glasses] prevent you from using the built-in medical hud.") - else - var/datum/atom_hud/data/human/medical/advanced/A = huds[DATA_HUD_MEDICAL_ADVANCED] - A.add_hud_to(H) - builtin_hud_user = 1 - return 1 +/obj/mecha/medical/odysseus/moved_inside(var/mob/living/carbon/human/H) + . = ..() + if(. && ishuman(H)) + if(istype(H.glasses, /obj/item/clothing/glasses/hud)) + occupant_message("[H.glasses] prevent you from using the built-in medical hud.") else - return 0 - - mmi_moved_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob) - if(..()) - if(occupant.client) - var/datum/atom_hud/A = huds[DATA_HUD_MEDICAL_ADVANCED] - A.add_hud_to(occupant) - builtin_hud_user = 1 - return 1 - else - return 0 - - go_out() - if(istype(occupant,/mob/living/carbon/human) && builtin_hud_user) - var/mob/living/carbon/human/H = occupant var/datum/atom_hud/data/human/medical/advanced/A = huds[DATA_HUD_MEDICAL_ADVANCED] - A.remove_hud_from(H) - builtin_hud_user = 0 - else if((istype(occupant, /mob/living/carbon/brain) || pilot_is_mmi()) && builtin_hud_user ) - var/mob/living/carbon/brain/H = occupant + A.add_hud_to(H) + builtin_hud_user = 1 + +/obj/mecha/medical/odysseus/mmi_moved_inside(var/obj/item/device/mmi/mmi_as_oc, mob/user) + . = ..() + if(.) + if(occupant.client) var/datum/atom_hud/A = huds[DATA_HUD_MEDICAL_ADVANCED] - A.remove_hud_from(H) - builtin_hud_user = 0 + A.add_hud_to(occupant) + builtin_hud_user = 1 - ..() - return +/obj/mecha/medical/odysseus/go_out() + if(ishuman(occupant) && builtin_hud_user) + var/mob/living/carbon/human/H = occupant + var/datum/atom_hud/data/human/medical/advanced/A = huds[DATA_HUD_MEDICAL_ADVANCED] + A.remove_hud_from(H) + builtin_hud_user = 0 + else if((isbrain(occupant) || pilot_is_mmi()) && builtin_hud_user) + var/mob/living/carbon/brain/H = occupant + var/datum/atom_hud/A = huds[DATA_HUD_MEDICAL_ADVANCED] + A.remove_hud_from(H) + builtin_hud_user = 0 + + . = ..() -//TODO - Check documentation for client.eye and client.perspective... -/obj/item/clothing/glasses/hud/health/mech - name = "Integrated Medical Hud" - HUDType = DATA_HUD_MEDICAL_ADVANCED diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm index 2a4f6adf189..c2ddd11d787 100644 --- a/code/game/mecha/working/ripley.dm +++ b/code/game/mecha/working/ripley.dm @@ -14,52 +14,46 @@ var/list/cargo = new var/cargo_capacity = 15 -/* -/obj/mecha/working/ripley/New() - ..() - return -*/ - /obj/mecha/working/ripley/Move() . = ..() update_pressure() /obj/mecha/working/ripley/Destroy() - while(src.damage_absorption.["brute"] < 0.6) - new /obj/item/asteroid/goliath_hide(src.loc) - src.damage_absorption.["brute"] = src.damage_absorption.["brute"] + 0.1 //If a goliath-plated ripley gets killed, all the plates drop - for(var/atom/movable/A in src.cargo) - A.loc = loc + while(damage_absorption.["brute"] < 0.6) + new /obj/item/asteroid/goliath_hide(loc) + damage_absorption.["brute"] = damage_absorption.["brute"] + 0.1 //If a goliath-plated ripley gets killed, all the plates drop + for(var/atom/movable/A in cargo) + A.forceMove(loc) step_rand(A) cargo.Cut() return ..() /obj/mecha/working/ripley/go_out() ..() - if(src.damage_absorption.["brute"] < 0.6 && src.damage_absorption.["brute"] > 0.3) - src.overlays = null - src.overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-open") - else if(src.damage_absorption.["brute"] == 0.3) - src.overlays = null - src.overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full-open") + if(damage_absorption.["brute"] < 0.6 && damage_absorption.["brute"] > 0.3) + overlays = null + overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-open") + else if(damage_absorption.["brute"] == 0.3) + overlays = null + overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full-open") /obj/mecha/working/ripley/moved_inside(var/mob/living/carbon/human/H as mob) ..() - if(src.damage_absorption.["brute"] < 0.6 && src.damage_absorption.["brute"] > 0.3) - src.overlays = null - src.overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g") - else if(src.damage_absorption.["brute"] == 0.3) - src.overlays = null - src.overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full") + if(damage_absorption.["brute"] < 0.6 && damage_absorption.["brute"] > 0.3) + overlays = null + overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g") + else if(damage_absorption.["brute"] == 0.3) + overlays = null + overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full") /obj/mecha/working/ripley/mmi_moved_inside(var/obj/item/device/mmi/mmi_as_oc as obj,mob/user as mob) ..() - if(src.damage_absorption.["brute"] < 0.6 && src.damage_absorption.["brute"] > 0.3) - src.overlays = null - src.overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g") - else if(src.damage_absorption.["brute"] == 0.3) - src.overlays = null - src.overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full") + if(damage_absorption.["brute"] < 0.6 && damage_absorption.["brute"] > 0.3) + overlays = null + overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g") + else if(damage_absorption.["brute"] == 0.3) + overlays = null + overlays += image("icon" = "mecha.dmi", "icon_state" = "ripley-g-full") /obj/mecha/working/ripley/firefighter desc = "Standart APLU chassis was refitted with additional thermal protection and cistern." @@ -90,7 +84,7 @@ /obj/mecha/working/ripley/deathripley/New() ..() - var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/tool/safety_clamp + var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/kill ME.attach(src) return @@ -102,10 +96,10 @@ ..() //Attach drill if(prob(25)) //Possible diamond drill... Feeling lucky? - var/obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill/D = new /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill + var/obj/item/mecha_parts/mecha_equipment/drill/diamonddrill/D = new /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill D.attach(src) else - var/obj/item/mecha_parts/mecha_equipment/tool/drill/D = new /obj/item/mecha_parts/mecha_equipment/tool/drill + var/obj/item/mecha_parts/mecha_equipment/drill/D = new /obj/item/mecha_parts/mecha_equipment/drill D.attach(src) //Add possible plasma cutter @@ -117,12 +111,12 @@ cargo.Add(new /obj/structure/ore_box(src)) //Attach hydrolic clamp - var/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/HC = new /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp + var/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/HC = new /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp HC.attach(src) - for(var/obj/item/mecha_parts/mecha_tracking/B in src.contents)//Deletes the beacon so it can't be found easily + for(var/obj/item/mecha_parts/mecha_tracking/B in contents)//Deletes the beacon so it can't be found easily qdel(B) - var/obj/item/mecha_parts/mecha_equipment/tool/mining_scanner/scanner = new /obj/item/mecha_parts/mecha_equipment/tool/mining_scanner + var/obj/item/mecha_parts/mecha_equipment/mining_scanner/scanner = new /obj/item/mecha_parts/mecha_equipment/mining_scanner scanner.attach(src) /obj/mecha/working/ripley/Exit(atom/movable/O) @@ -134,14 +128,14 @@ ..() if(href_list["drop_from_cargo"]) var/obj/O = locate(href_list["drop_from_cargo"]) - if(O && O in src.cargo) - src.occupant_message("\blue You unload [O].") + if(O && O in cargo) + occupant_message("\blue You unload [O].") O.loc = get_turf(src) - src.cargo -= O + cargo -= O var/turf/T = get_turf(O) if(T) T.Entered(O) - src.log_message("Unloaded [O]. Cargo compartment capacity: [cargo_capacity - src.cargo.len]") + log_message("Unloaded [O]. Cargo compartment capacity: [cargo_capacity - cargo.len]") return @@ -149,8 +143,8 @@ /obj/mecha/working/ripley/get_stats_part() var/output = ..() output += "Cargo Compartment Contents:
" - if(src.cargo.len) - for(var/obj/O in src.cargo) + if(cargo.len) + for(var/obj/O in cargo) output += "Unload : [O]
" else output += "Nothing" @@ -159,12 +153,12 @@ /obj/mecha/working/ripley/Destroy() for(var/mob/M in src) - if(M==src.occupant) + if(M == occupant) continue M.loc = get_turf(src) M.loc.Entered(M) step_rand(M) - for(var/atom/movable/A in src.cargo) + for(var/atom/movable/A in cargo) A.loc = get_turf(src) var/turf/T = get_turf(A) if(T) @@ -179,9 +173,9 @@ if(pressure < 20) step_in = 3 - for(var/obj/item/mecha_parts/mecha_equipment/tool/drill/drill in equipment) + for(var/obj/item/mecha_parts/mecha_equipment/drill/drill in equipment) drill.equip_cooldown = initial(drill.equip_cooldown)/2 else step_in = 5 - for(var/obj/item/mecha_parts/mecha_equipment/tool/drill/drill in equipment) + for(var/obj/item/mecha_parts/mecha_equipment/drill/drill in equipment) drill.equip_cooldown = initial(drill.equip_cooldown) \ No newline at end of file diff --git a/code/game/mecha/working/working.dm b/code/game/mecha/working/working.dm index 7a59b6190ed..ccbfe2ef21b 100644 --- a/code/game/mecha/working/working.dm +++ b/code/game/mecha/working/working.dm @@ -4,29 +4,3 @@ /obj/mecha/working/New() ..() new /obj/item/mecha_parts/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/get_stats_part() - var/output = ..() - output += "[src.name] Tools:
" - 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 -*/ \ No newline at end of file diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index cead6e33ffd..4c61393d9f7 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -29,6 +29,11 @@ . = ..() unbuckle_mob() +/atom/movable/proc/has_buckled_mobs() + if(buckled_mob) + return TRUE + return FALSE + //procs that handle the actual buckling and unbuckling /atom/movable/proc/buckle_mob(mob/living/M) if(!can_buckle || !istype(M) || (M.loc != loc) || M.buckled || M.buckled_mob || buckled_mob || (buckle_requires_restraints && !M.restrained()) || M == src) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 5946ef77f0a..3a04a11f9e6 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -200,6 +200,9 @@ levelupdate() CalculateAdjacentTurfs() + if(air_master && !ignore_air) + air_master.add_to_active(src) + if(!keep_cabling && !can_have_cabling()) for(var/obj/structure/cable/C in contents) qdel(C) diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index a76dfa9a699..0c24daf977c 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -436,10 +436,9 @@ var/global/list/rockTurfEdgeCache = list( else if(istype(AM,/obj/mecha)) var/obj/mecha/M = AM - if(istype(M.selected,/obj/item/mecha_parts/mecha_equipment/tool/drill)) + if(istype(M.selected,/obj/item/mecha_parts/mecha_equipment/drill)) M.selected.action(src) - else - return + /**********************Asteroid**************************/ diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 93b94e74f9e..1d2b40c6a70 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -90,21 +90,23 @@ // blind_message (optional) is what blind people will hear e.g. "You hear something!" /mob/visible_message(var/message, var/self_message, var/blind_message) - for(var/mob/M in viewers(src)) + for(var/mob/M in get_mobs_in_view(7, src)) if(M.see_invisible < invisibility) continue //can't view the invisible var/msg = message - if(self_message && M==src) + if(self_message && M == src) msg = self_message - M.show_message( msg, 1, blind_message, 2) + M.show_message(msg, 1, blind_message, 2) // Show a message to all mobs in sight of this atom // Use for objects performing visible actions // message is output to anyone who can see, e.g. "The [src] does something!" // blind_message (optional) is what blind people will hear e.g. "You hear something!" /atom/proc/visible_message(var/message, var/blind_message) - for(var/mob/M in viewers(src)) - M.show_message( message, 1, blind_message, 2) + for(var/mob/M in get_mobs_in_view(7, src)) + if(!M.client) + continue + M.show_message(message, 1, blind_message, 2) // Show a message to all mobs in earshot of this one // This would be for audible actions by the src mob @@ -118,7 +120,7 @@ range = hearing_distance var/msg = message for(var/mob/M in get_mobs_in_view(range, src)) - if(self_message && M==src) + if(self_message && M == src) msg = self_message M.show_message(msg, 2, deaf_message, 1) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 69e29fa9aa8..4c210f6f8f8 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -408,44 +408,42 @@ ///Called by /client/Move() ///For moving in space ///Return 1 for movement 0 for none -/mob/Process_Spacemove(var/movement_dir = 0) - +/mob/Process_Spacemove(movement_dir = 0) if(..()) return 1 + var/atom/movable/backup = get_spacemove_backup() + if(backup) + if(istype(backup) && movement_dir && !backup.anchored) + if(backup.newtonian_move(turn(movement_dir, 180))) //You're pushing off something movable, so it moves + src << "You push off of [backup] to propel yourself." + return 1 + return 0 +/mob/get_spacemove_backup() var/atom/movable/dense_object_backup - for(var/atom/A in orange(1, get_turf(src))) + for(var/A in orange(1, get_turf(src))) if(isarea(A)) continue - else if(isturf(A)) var/turf/turf = A - if(istype(turf,/turf/space)) + if(istype(turf, /turf/space)) continue - if(!turf.density && !mob_negates_gravity()) continue - - return 1 - + return A else var/atom/movable/AM = A if(AM == buckled) //Kind of unnecessary but let's just be sure continue - if(AM.density) + if(!AM.CanPass(src) || AM.density) if(AM.anchored) - return 1 + return AM if(pulling == AM) continue dense_object_backup = AM + break + . = dense_object_backup - if(movement_dir && dense_object_backup) - if(dense_object_backup.newtonian_move(turn(movement_dir, 180))) //You're pushing off something movable, so it moves - to_chat(src, "You push off of [dense_object_backup] to propel yourself.") - - - return 1 - return 0 /mob/proc/mob_has_gravity(turf/T) return has_gravity(src, T) diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index f292209ac3e..1a26599b93a 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -601,7 +601,7 @@ name = "Exosuit Engineering Equipment (Cable Layer)" id = "mech_cable_layer" build_type = MECHFAB - build_path = /obj/item/mecha_parts/mecha_equipment/tool/cable_layer + build_path = /obj/item/mecha_parts/mecha_equipment/cable_layer materials = list(MAT_METAL=10000) construction_time = 100 category = list("Exosuit Equipment") @@ -610,7 +610,7 @@ name = "Exosuit Engineering Equipment (Drill)" id = "mech_drill" build_type = MECHFAB - build_path = /obj/item/mecha_parts/mecha_equipment/tool/drill + build_path = /obj/item/mecha_parts/mecha_equipment/drill materials = list(MAT_METAL=10000) construction_time = 100 category = list("Exosuit Equipment") @@ -619,7 +619,7 @@ name = "Exosuit Engineering Equipment (Extinguisher)" id = "mech_extinguisher" build_type = MECHFAB - build_path = /obj/item/mecha_parts/mecha_equipment/tool/extinguisher + build_path = /obj/item/mecha_parts/mecha_equipment/extinguisher materials = list(MAT_METAL=10000) construction_time = 100 category = list("Exosuit Equipment") @@ -628,7 +628,7 @@ name = "Exosuit Engineering Equipment (Hydraulic Clamp)" id = "mech_hydraulic_clamp" build_type = MECHFAB - build_path = /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp + build_path = /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp materials = list(MAT_METAL=10000) construction_time = 100 category = list("Exosuit Equipment") @@ -638,7 +638,7 @@ id = "mech_sleeper" build_type = MECHFAB req_tech = list("biotech" = 2) - build_path = /obj/item/mecha_parts/mecha_equipment/tool/sleeper + build_path = /obj/item/mecha_parts/mecha_equipment/medical/sleeper materials = list(MAT_METAL=5000,MAT_GLASS=10000) construction_time = 100 category = list("Exosuit Equipment") @@ -648,7 +648,7 @@ id = "mech_syringe_gun" build_type = MECHFAB req_tech = list("magnets" = 3,"biotech" = 3) - build_path = /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun + build_path = /obj/item/mecha_parts/mecha_equipment/medical/syringe_gun materials = list(MAT_METAL=3000,MAT_GLASS=2000) construction_time = 200 category = list("Exosuit Equipment") @@ -723,7 +723,7 @@ desc = "An exosuit-mounted Mime Rapid Construction Device." id = "mech_mrcd" build_type = MECHFAB - build_path = /obj/item/mecha_parts/mecha_equipment/tool/mimercd + build_path = /obj/item/mecha_parts/mecha_equipment/mimercd materials = list(MAT_METAL=30000,MAT_TRANQUILLITE=10000) construction_time = 700 category = list("Exosuit Equipment") @@ -735,7 +735,7 @@ id = "mech_diamond_drill" build_type = MECHFAB req_tech = list("materials" = 4, "engineering" = 3) - build_path = /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill + build_path = /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill materials = list(MAT_METAL=10000,MAT_DIAMOND=6500) construction_time = 100 category = list("Exosuit Equipment") @@ -744,7 +744,7 @@ name = "Exosuit Engineering Equipement (Mining Scanner)" id = "mech_mscanner" build_type = MECHFAB - build_path = /obj/item/mecha_parts/mecha_equipment/tool/mining_scanner + build_path = /obj/item/mecha_parts/mecha_equipment/mining_scanner materials = list(MAT_METAL=5000,MAT_GLASS=2500) construction_time = 50 category = list("Exosuit Equipment") @@ -788,7 +788,7 @@ id = "mech_rcd" build_type = MECHFAB req_tech = list("materials" = 4, "bluespace" = 3, "magnets" = 4, "powerstorage"=4, "engineering" = 4) - build_path = /obj/item/mecha_parts/mecha_equipment/tool/rcd + build_path = /obj/item/mecha_parts/mecha_equipment/rcd materials = list(MAT_METAL=30000,MAT_GOLD=20000,MAT_PLASMA=25000,MAT_SILVER=20000) construction_time = 1200 category = list("Exosuit Equipment") diff --git a/code/modules/research/xenoarchaeology/artifact/artifact.dm b/code/modules/research/xenoarchaeology/artifact/artifact.dm index 82caa2b9be5..57759308aee 100644 --- a/code/modules/research/xenoarchaeology/artifact/artifact.dm +++ b/code/modules/research/xenoarchaeology/artifact/artifact.dm @@ -59,7 +59,7 @@ else if(istype(AM,/obj/mecha)) var/obj/mecha/M = AM - if(istype(M.selected,/obj/item/mecha_parts/mecha_equipment/tool/drill)) + if(istype(M.selected,/obj/item/mecha_parts/mecha_equipment/drill)) M.selected.action(src) /obj/structure/boulder/attackby(obj/item/weapon/W as obj, mob/user as mob, params) diff --git a/code/modules/research/xenoarchaeology/artifact/artifact_hoverpod.dm b/code/modules/research/xenoarchaeology/artifact/artifact_hoverpod.dm index 4b16c25aeea..6544deb1d68 100644 --- a/code/modules/research/xenoarchaeology/artifact/artifact_hoverpod.dm +++ b/code/modules/research/xenoarchaeology/artifact/artifact_hoverpod.dm @@ -3,40 +3,11 @@ icon_state = "engineering_pod" desc = "Stubby and round, it has a human sized access hatch on the top." wreckage = /obj/effect/decal/mecha_wreckage/hoverpod + stepsound = 'sound/machines/hiss.ogg' /obj/mecha/working/hoverpod/Process_Spacemove(var/movement_dir = 0) return 1 // puts the hover in hoverpod -//these three procs overriden to play different sounds -/obj/mecha/working/hoverpod/mechturn(direction) - dir = direction - //playsound(src,'sound/machines/hiss.ogg',40,1) - return 1 - -/obj/mecha/working/hoverpod/mechstep(direction) - var/result = step(src,direction) - if(result) - playsound(src,'sound/machines/hiss.ogg',40,1) - return result - - -/obj/mecha/working/hoverpod/mechsteprand() - var/result = step_rand(src) - if(result) - playsound(src,'sound/machines/hiss.ogg',40,1) - return result - /obj/effect/decal/mecha_wreckage/hoverpod name = "Hover pod wreckage" icon_state = "engineering_pod-broken" - - /*New() - ..() - var/list/parts = list( - - for(var/i=0;i<2;i++) - if(!isemptylist(parts) && prob(40)) - var/part = pick(parts) - welder_salvage += part - parts -= part - return*/ diff --git a/code/modules/surgery/generic.dm b/code/modules/surgery/generic.dm index d02787eb3b5..fa7c8c63451 100644 --- a/code/modules/surgery/generic.dm +++ b/code/modules/surgery/generic.dm @@ -214,7 +214,7 @@ //drill bone /datum/surgery_step/generic/drill name = "drill bone" - allowed_tools = list(/obj/item/weapon/surgicaldrill = 100, /obj/item/weapon/pickaxe/drill = 60, /obj/item/mecha_parts/mecha_equipment/tool/drill = 60, /obj/item/weapon/screwdriver = 20) + allowed_tools = list(/obj/item/weapon/surgicaldrill = 100, /obj/item/weapon/pickaxe/drill = 60, /obj/item/mecha_parts/mecha_equipment/drill = 60, /obj/item/weapon/screwdriver = 20) time = 30 /datum/surgery_step/generic/drill/begin_step(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) diff --git a/paradise.dme b/paradise.dme index c75e5fc0c2c..c4dcba43636 100644 --- a/paradise.dme +++ b/paradise.dme @@ -639,6 +639,7 @@ #include "code\game\mecha\mecha_construction_paths.dm" #include "code\game\mecha\mecha_control_console.dm" #include "code\game\mecha\mecha_parts.dm" +#include "code\game\mecha\mecha_topic.dm" #include "code\game\mecha\mecha_wreckage.dm" #include "code\game\mecha\paintkits.dm" #include "code\game\mecha\combat\combat.dm" @@ -650,7 +651,9 @@ #include "code\game\mecha\combat\recitence.dm" #include "code\game\mecha\equipment\mecha_equipment.dm" #include "code\game\mecha\equipment\tools\medical_tools.dm" -#include "code\game\mecha\equipment\tools\tools.dm" +#include "code\game\mecha\equipment\tools\mining_tools.dm" +#include "code\game\mecha\equipment\tools\other_tools.dm" +#include "code\game\mecha\equipment\tools\work_tools.dm" #include "code\game\mecha\equipment\weapons\weapons.dm" #include "code\game\mecha\medical\medical.dm" #include "code\game\mecha\medical\odysseus.dm"