diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index 413759cc377..18fe42bbe4a 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -1,81 +1,81 @@ -//TODO: rewrite and standardise all controller datums to the datum/controller type -//TODO: allow all controllers to be deleted for clean restarts (see WIP master controller stuff) - MC done - lighting done - -/client/proc/restart_controller(controller in list("Master","Failsafe","Lighting","Supply Shuttle")) - set category = "Debug" - set name = "Restart Controller" - set desc = "Restart one of the various periodic loop controllers for the game (be careful!)" - - if(!holder) return - usr = null - src = null - switch(controller) - if("Master") - new /datum/controller/game_controller() - master_controller.process() - feedback_add_details("admin_verb","RMC") - if("Failsafe") - new /datum/controller/failsafe() - feedback_add_details("admin_verb","RFailsafe") - if("Lighting") - new /datum/controller/lighting() - lighting_controller.process() - feedback_add_details("admin_verb","RLighting") - if("Supply Shuttle") - supply_shuttle.process() - feedback_add_details("admin_verb","RSupply") - message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.") - return - - -/client/proc/debug_controller(controller in list("Master","Failsafe","Ticker","Lighting","Air","Jobs","Sun","Radio","Supply Shuttle","Emergency Shuttle","Configuration","pAI", "Cameras", "Events")) - set category = "Debug" - set name = "Debug Controller" - set desc = "Debug the various periodic loop controllers for the game (be careful!)" - - if(!holder) return - switch(controller) - if("Master") - debug_variables(master_controller) - feedback_add_details("admin_verb","DMC") - if("Failsafe") - debug_variables(Failsafe) - feedback_add_details("admin_verb","DFailsafe") - if("Ticker") - debug_variables(ticker) - feedback_add_details("admin_verb","DTicker") - if("Lighting") - debug_variables(lighting_controller) - feedback_add_details("admin_verb","DLighting") - if("Air") - debug_variables(air_master) - feedback_add_details("admin_verb","DAir") - if("Jobs") - debug_variables(job_master) - feedback_add_details("admin_verb","DJobs") - if("Sun") - debug_variables(sun) - feedback_add_details("admin_verb","DSun") - if("Radio") - debug_variables(radio_controller) - feedback_add_details("admin_verb","DRadio") - if("Supply Shuttle") - debug_variables(supply_shuttle) - feedback_add_details("admin_verb","DSupply") - if("Emergency Shuttle") - debug_variables(emergency_shuttle) - feedback_add_details("admin_verb","DEmergency") - if("Configuration") - debug_variables(config) - feedback_add_details("admin_verb","DConf") - if("pAI") - debug_variables(paiController) - feedback_add_details("admin_verb","DpAI") - if("Cameras") - debug_variables(cameranet) - feedback_add_details("admin_verb","DCameras") - if("Events") - debug_variables(events) - feedback_add_details("admin_verb","DEvents") - message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.") - return +//TODO: rewrite and standardise all controller datums to the datum/controller type +//TODO: allow all controllers to be deleted for clean restarts (see WIP master controller stuff) - MC done - lighting done + +/client/proc/restart_controller(controller in list("Master","Failsafe","Lighting","Supply Shuttle")) + set category = "Debug" + set name = "Restart Controller" + set desc = "Restart one of the various periodic loop controllers for the game (be careful!)" + + if(!holder) return + usr = null + src = null + switch(controller) + if("Master") + new /datum/controller/game_controller() + master_controller.process() + feedback_add_details("admin_verb","RMC") + if("Failsafe") + new /datum/controller/failsafe() + feedback_add_details("admin_verb","RFailsafe") + if("Lighting") + new /datum/controller/lighting() + lighting_controller.process() + feedback_add_details("admin_verb","RLighting") + if("Supply Shuttle") + supply_shuttle.process() + feedback_add_details("admin_verb","RSupply") + message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.") + return + + +/client/proc/debug_controller(controller in list("Master","Failsafe","Ticker","Lighting","Air","Jobs","Sun","Radio","Supply Shuttle","Emergency Shuttle","Configuration","pAI", "Cameras", "Events")) + set category = "Debug" + set name = "Debug Controller" + set desc = "Debug the various periodic loop controllers for the game (be careful!)" + + if(!holder) return + switch(controller) + if("Master") + debug_variables(master_controller) + feedback_add_details("admin_verb","DMC") + if("Failsafe") + debug_variables(Failsafe) + feedback_add_details("admin_verb","DFailsafe") + if("Ticker") + debug_variables(ticker) + feedback_add_details("admin_verb","DTicker") + if("Lighting") + debug_variables(lighting_controller) + feedback_add_details("admin_verb","DLighting") + if("Air") + debug_variables(air_master) + feedback_add_details("admin_verb","DAir") + if("Jobs") + debug_variables(job_master) + feedback_add_details("admin_verb","DJobs") + if("Sun") + debug_variables(sun) + feedback_add_details("admin_verb","DSun") + if("Radio") + debug_variables(radio_controller) + feedback_add_details("admin_verb","DRadio") + if("Supply Shuttle") + debug_variables(supply_shuttle) + feedback_add_details("admin_verb","DSupply") + if("Emergency Shuttle") + debug_variables(emergency_shuttle) + feedback_add_details("admin_verb","DEmergency") + if("Configuration") + debug_variables(config) + feedback_add_details("admin_verb","DConf") + if("pAI") + debug_variables(paiController) + feedback_add_details("admin_verb","DpAI") + if("Cameras") + debug_variables(cameranet) + feedback_add_details("admin_verb","DCameras") + if("Events") + debug_variables(events) + feedback_add_details("admin_verb","DEvents") + message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.") + return diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 63548240980..ffc5bbc0bb3 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1,864 +1,864 @@ -/mob/Del()//This makes sure that mobs with clients/keys are not just deleted from the game. - mob_list -= src - dead_mob_list -= src - living_mob_list -= src - ghostize() - ..() - -var/next_mob_id = 0 -/mob/New() - tag = "mob_[next_mob_id++]" - mob_list += src - if(stat == DEAD) - dead_mob_list += src - else - living_mob_list += src - ..() - -/mob/proc/Cell() - set category = "Admin" - set hidden = 1 - - if(!loc) return 0 - - var/datum/gas_mixture/environment = loc.return_air() - - var/t = "\blue Coordinates: [x],[y] \n" - t+= "\red Temperature: [environment.temperature] \n" - t+= "\blue Nitrogen: [environment.nitrogen] \n" - t+= "\blue Oxygen: [environment.oxygen] \n" - t+= "\blue Plasma : [environment.toxins] \n" - t+= "\blue Carbon Dioxide: [environment.carbon_dioxide] \n" - for(var/datum/gas/trace_gas in environment.trace_gases) - usr << "\blue [trace_gas.type]: [trace_gas.moles] \n" - - usr.show_message(t, 1) - -/mob/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2) - - if(!client) return - - msg = copytext(msg, 1, MAX_MESSAGE_LEN) - - if (type) - if(type & 1 && (sdisabilities & BLIND || blinded || paralysis) )//Vision related - if (!( alt )) - return - else - msg = alt - type = alt_type - if (type & 2 && (sdisabilities & DEAF || ear_deaf))//Hearing related - if (!( alt )) - return - else - msg = alt - type = alt_type - if ((type & 1 && sdisabilities & BLIND)) - return - // Added voice muffling for Issue 41. - if(stat == UNCONSCIOUS || sleeping > 0) - src << "... You can almost hear someone talking ..." - else - src << msg - return - -// Show a message to all mobs in sight of this one -// This would be for visible actions by the src mob -// message is the message output to anyone who can see e.g. "[src] does something!" -// self_message (optional) is what the src mob sees e.g. "You do something!" -// 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)) - var/msg = message - if(self_message && M==src) - msg = self_message - 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) - - -/mob/proc/movement_delay() - return 0 - -/mob/proc/Life() - return - -/mob/proc/get_item_by_slot(slot_id) - switch(slot_id) - if(slot_l_hand) - return l_hand - if(slot_r_hand) - return r_hand - return null - -/mob/proc/ret_grab(obj/effect/list_container/mobl/L as obj, flag) - if ((!( istype(l_hand, /obj/item/weapon/grab) ) && !( istype(r_hand, /obj/item/weapon/grab) ))) - if (!( L )) - return null - else - return L.container - else - if (!( L )) - L = new /obj/effect/list_container/mobl( null ) - L.container += src - L.master = src - if (istype(l_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = l_hand - if (!( L.container.Find(G.affecting) )) - L.container += G.affecting - if (G.affecting) - G.affecting.ret_grab(L, 1) - if (istype(r_hand, /obj/item/weapon/grab)) - var/obj/item/weapon/grab/G = r_hand - if (!( L.container.Find(G.affecting) )) - L.container += G.affecting - if (G.affecting) - G.affecting.ret_grab(L, 1) - if (!( flag )) - if (L.master == src) - var/list/temp = list( ) - temp += L.container - //L = null - del(L) - return temp - else - return L.container - return - -/mob/proc/restrained() - return - -//This proc is called whenever someone clicks an inventory ui slot. -/mob/proc/attack_ui(slot) - var/obj/item/W = get_active_hand() - - if(istype(W)) - if(equip_to_slot_if_possible(W, slot,0,0,0)) - return 1 - - if(!W) - // Activate the item - var/obj/item/I = get_item_by_slot(slot) - if(istype(I)) - I.attack_hand(src) - - return 0 - -/mob/proc/put_in_any_hand_if_possible(obj/item/W as obj, del_on_fail = 0, disable_warning = 1, redraw_mob = 1) - if(equip_to_slot_if_possible(W, slot_l_hand, del_on_fail, disable_warning, redraw_mob)) - return 1 - else if(equip_to_slot_if_possible(W, slot_r_hand, del_on_fail, disable_warning, redraw_mob)) - return 1 - return 0 - -//This is a SAFE proc. Use this instead of equip_to_splot()! -//set del_on_fail to have it delete W if it fails to equip -//set disable_warning to disable the 'you are unable to equip that' warning. -//unset redraw_mob to prevent the mob from being redrawn at the end. -/mob/proc/equip_to_slot_if_possible(obj/item/W as obj, slot, del_on_fail = 0, disable_warning = 0, redraw_mob = 1) - if(!istype(W)) return 0 - if(!W.mob_can_equip(src, slot, disable_warning)) - if(del_on_fail) - del(W) - else - if(!disable_warning) - src << "\red You are unable to equip that." //Only print if del_on_fail is false - return 0 - equip_to_slot(W, slot, redraw_mob) //This proc should not ever fail. - return 1 - -//This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on whether you can or can't eqip need to be done before! Use mob_can_equip() for that task. -//In most cases you will want to use equip_to_slot_if_possible() -/mob/proc/equip_to_slot(obj/item/W as obj, slot) - return - -//This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to equip people when the rounds tarts and when events happen and such. -/mob/proc/equip_to_slot_or_del(obj/item/W as obj, slot) - equip_to_slot_if_possible(W, slot, 1, 1, 0) - -//The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot. -var/list/slot_equipment_priority = list( \ - slot_back,\ - slot_wear_id,\ - slot_w_uniform,\ - slot_wear_suit,\ - slot_wear_mask,\ - slot_head,\ - slot_shoes,\ - slot_gloves,\ - slot_ears,\ - slot_glasses,\ - slot_belt,\ - slot_s_store,\ - slot_l_store,\ - slot_r_store\ - ) - -//puts the item "W" into an appropriate slot in a human's inventory -//returns 0 if it cannot, 1 if successful -/mob/proc/equip_to_appropriate_slot(obj/item/W) - if(!istype(W)) return 0 - - for(var/slot in slot_equipment_priority) - if(equip_to_slot_if_possible(W, slot, 0, 1, 1)) //del_on_fail = 0; disable_warning = 0; redraw_mob = 1 - return 1 - - return 0 - -/mob/proc/reset_view(atom/A) - if (client) - if (istype(A, /atom/movable)) - client.perspective = EYE_PERSPECTIVE - client.eye = A - else - if (isturf(loc)) - client.eye = client.mob - client.perspective = MOB_PERSPECTIVE - else - client.perspective = EYE_PERSPECTIVE - client.eye = loc - return - - -/mob/proc/show_inv(mob/user) - user.set_machine(src) - var/dat = {" -
"
- for(var/t in typesof(/area))
- master += text("[]\n", t)
- //Foreach goto(26)
- src << browse(master)
- return
-*/
-
-/mob/verb/memory()
- set name = "Notes"
- set category = "IC"
- if(mind)
- mind.show_memory(src)
- else
- src << "The game appears to have misplaced your mind datum, so we can't show you your notes."
-
-/mob/verb/add_memory(msg as message)
- set name = "Add Note"
- set category = "IC"
-
- msg = copytext(msg, 1, MAX_MESSAGE_LEN)
- msg = sanitize(msg)
-
- if(mind)
- mind.store_memory(msg)
- else
- src << "The game appears to have misplaced your mind datum, so we can't show you your notes."
-
-/mob/proc/store_memory(msg as message, popup, sane = 1)
- msg = copytext(msg, 1, MAX_MESSAGE_LEN)
-
- if (sane)
- msg = sanitize(msg)
-
- if (length(memory) == 0)
- memory += msg
- else
- memory += "
[msg]"
-
- if (popup)
- memory()
-
-/*
-/mob/verb/help()
- set name = "Help"
- src << browse('html/help.html', "window=help")
- return
-*/
-
-/mob/verb/abandon_mob()
- set name = "Respawn"
- set category = "OOC"
-
- if (!( abandon_allowed ))
- return
- if ((stat != 2 || !( ticker )))
- usr << "\blue You must be dead to use this!"
- return
-
- log_game("[usr.name]/[usr.key] used abandon mob.")
-
- usr << "\blue Please roleplay correctly!"
-
- if(!client)
- log_game("[usr.key] AM failed due to disconnect.")
- return
- client.screen.Cut()
- if(!client)
- log_game("[usr.key] AM failed due to disconnect.")
- return
-
- var/mob/new_player/M = new /mob/new_player()
- if(!client)
- log_game("[usr.key] AM failed due to disconnect.")
- del(M)
- return
-
- M.key = key
-// M.Login() //wat
- return
-
-/client/verb/changes()
- set name = "Changelog"
- set category = "OOC"
- getFiles(
- 'html/postcardsmall.jpg',
- 'html/somerights20.png',
- 'html/88x31.png',
- 'html/bug-minus.png',
- 'html/cross-circle.png',
- 'html/hard-hat-exclamation.png',
- 'html/image-minus.png',
- 'html/image-plus.png',
- 'html/music-minus.png',
- 'html/music-plus.png',
- 'html/tick-circle.png',
- 'html/wrench-screwdriver.png',
- 'html/spell-check.png',
- 'html/burn-exclamation.png',
- 'html/chevron.png',
- 'html/chevron-expand.png',
- 'html/changelog.css',
- 'html/changelog.js',
- 'html/changelog.html'
- )
- src << browse('html/changelog.html', "window=changes;size=675x650")
- if(prefs.lastchangelog != changelog_hash)
- prefs.lastchangelog = changelog_hash
- prefs.save_preferences()
- winset(src, "rpane.changelog", "background-color=none;font-style=;")
-
-/mob/verb/observe()
- set name = "Observe"
- set category = "OOC"
- var/is_admin = 0
-
- if(check_rights_for(client,R_ADMIN))
- is_admin = 1
- else if(stat != DEAD || istype(src, /mob/new_player))
- usr << "\blue You must be observing to use this!"
- return
-
- if(is_admin && stat == DEAD)
- is_admin = 0
-
- var/list/names = list()
- var/list/namecounts = list()
- var/list/creatures = list()
-
- for(var/obj/O in world) //EWWWWWWWWWWWWWWWWWWWWWWWW ~needs to be optimised
- if(!O.loc)
- continue
- if(istype(O, /obj/item/weapon/disk/nuclear))
- var/name = "Nuclear Disk"
- if (names.Find(name))
- namecounts[name]++
- name = "[name] ([namecounts[name]])"
- else
- names.Add(name)
- namecounts[name] = 1
- creatures[name] = O
-
- if(istype(O, /obj/machinery/singularity))
- var/name = "Singularity"
- if (names.Find(name))
- namecounts[name]++
- name = "[name] ([namecounts[name]])"
- else
- names.Add(name)
- namecounts[name] = 1
- creatures[name] = O
-
- if(istype(O, /obj/machinery/bot))
- var/name = "BOT: [O.name]"
- if (names.Find(name))
- namecounts[name]++
- name = "[name] ([namecounts[name]])"
- else
- names.Add(name)
- namecounts[name] = 1
- creatures[name] = O
-
-
- for(var/mob/M in sortAtom(mob_list))
- var/name = M.name
- if (names.Find(name))
- namecounts[name]++
- name = "[name] ([namecounts[name]])"
- else
- names.Add(name)
- namecounts[name] = 1
-
- creatures[name] = M
-
-
- client.perspective = EYE_PERSPECTIVE
-
- var/eye_name = null
-
- var/ok = "[is_admin ? "Admin Observe" : "Observe"]"
- eye_name = input("Please, select a player!", ok, null, null) as null|anything in creatures
-
- if (!eye_name)
- return
-
- var/mob/mob_eye = creatures[eye_name]
-
- if(client && mob_eye)
- client.eye = mob_eye
- if (is_admin)
- client.adminobs = 1
- if(mob_eye == client.mob || client.eye == client.mob)
- client.adminobs = 0
-
-/mob/verb/cancel_camera()
- set name = "Cancel Camera View"
- set category = "OOC"
- reset_view(null)
- unset_machine()
- if(istype(src, /mob/living))
- if(src:cameraFollow)
- src:cameraFollow = null
-
-/mob/Topic(href, href_list)
- if(href_list["mach_close"])
- var/t1 = text("window=[href_list["mach_close"]]")
- unset_machine()
- src << browse(null, t1)
-
- if(href_list["refresh"])
- if(machine && in_range(src, usr))
- show_inv(machine)
-
- if(!usr.stat && usr.canmove && !usr.restrained() && Adjacent(usr))
- if(href_list["item"])
- var/slot = text2num(href_list["item"])
- var/obj/item/what = get_item_by_slot(slot)
-
- if(what && what.canremove)
- visible_message("[usr] tries to remove [src]'s [what.name].", \
- "[usr] tries to remove [src]'s [what.name].")
- what.add_fingerprint(usr)
- if(do_mob(usr, src, STRIP_DELAY))
- if(what && Adjacent(usr))
- u_equip(what)
- else
- what = usr.get_active_hand()
- if(what && what.mob_can_equip(src, slot, 1))
- visible_message("[usr] tries to put [what] on [src].")
- if(do_mob(usr, src, STRIP_DELAY * 0.5))
- if(what && Adjacent(usr))
- usr.u_equip(what)
- equip_to_slot_if_possible(what, slot, 0, 1)
-
- if(usr.machine == src)
- if(Adjacent(usr))
- show_inv(usr)
- else
- usr << browse(null,"window=mob\ref[src]")
-
-
-/mob/MouseDrop(mob/M)
- ..()
- if(M != usr) return
- if(usr == src) return
- if(!Adjacent(usr)) return
- if(istype(M, /mob/living/silicon/ai)) return
- show_inv(usr)
-
-
-/mob/verb/stop_pulling()
-
- set name = "Stop Pulling"
- set category = "IC"
-
- if(pulling)
- pulling.pulledby = null
- pulling = null
-
-/mob/proc/start_pulling(var/atom/movable/AM)
- if ( !AM || !usr || src==AM || !isturf(src.loc) ) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort!
- return
- if (!( AM.anchored ))
- AM.add_fingerprint(src)
-
- // If we're pulling something then drop what we're currently pulling and pull this instead.
- if(pulling)
- // Are we trying to pull something we are already pulling? Then just stop here, no need to continue.
- if(AM == pulling)
- return
- stop_pulling()
-
- src.pulling = AM
- AM.pulledby = src
- if(ismob(AM))
- var/mob/M = AM
- if(!iscarbon(src))
- M.LAssailant = null
- else
- M.LAssailant = usr
-
-
-/mob/proc/can_use_hands()
- return
-
-/mob/proc/is_active()
- return (0 >= usr.stat)
-
-/mob/proc/see(message)
- if(!is_active())
- return 0
- src << message
- return 1
-
-/mob/proc/show_viewers(message)
- for(var/mob/M in viewers())
- M.see(message)
-
-/*
-adds a dizziness amount to a mob
-use this rather than directly changing var/dizziness
-since this ensures that the dizzy_process proc is started
-currently only humans get dizzy
-
-value of dizziness ranges from 0 to 1000
-below 100 is not dizzy
-*/
-/mob/proc/make_dizzy(var/amount)
- if(!istype(src, /mob/living/carbon/human)) // for the moment, only humans get dizzy
- return
-
- dizziness = min(1000, dizziness + amount) // store what will be new value
- // clamped to max 1000
- if(dizziness > 100 && !is_dizzy)
- spawn(0)
- dizzy_process()
-
-
-/*
-dizzy process - wiggles the client's pixel offset over time
-spawned from make_dizzy(), will terminate automatically when dizziness gets <100
-note dizziness decrements automatically in the mob's Life() proc.
-*/
-/mob/proc/dizzy_process()
- is_dizzy = 1
- while(dizziness > 100)
- if(client)
- var/amplitude = dizziness*(sin(dizziness * 0.044 * world.time) + 1) / 70
- client.pixel_x = amplitude * sin(0.008 * dizziness * world.time)
- client.pixel_y = amplitude * cos(0.008 * dizziness * world.time)
-
- sleep(1)
- //endwhile - reset the pixel offsets to zero
- is_dizzy = 0
- if(client)
- client.pixel_x = 0
- client.pixel_y = 0
-
-// jitteriness - copy+paste of dizziness
-
-/mob/proc/make_jittery(var/amount)
- if(!istype(src, /mob/living/carbon/human)) // for the moment, only humans get dizzy
- return
-
- jitteriness = min(1000, jitteriness + amount) // store what will be new value
- // clamped to max 1000
- if(jitteriness > 100 && !is_jittery)
- spawn(0)
- jittery_process()
-
-
-// Typo from the oriignal coder here, below lies the jitteriness process. So make of his code what you will, the previous comment here was just a copypaste of the above.
-/mob/proc/jittery_process()
- var/old_x = pixel_x
- var/old_y = pixel_y
- is_jittery = 1
- while(jitteriness > 100)
-// var/amplitude = jitteriness*(sin(jitteriness * 0.044 * world.time) + 1) / 70
-// pixel_x = amplitude * sin(0.008 * jitteriness * world.time)
-// pixel_y = amplitude * cos(0.008 * jitteriness * world.time)
-
- var/amplitude = min(4, jitteriness / 100)
- pixel_x = rand(-amplitude, amplitude)
- pixel_y = rand(-amplitude/3, amplitude/3)
-
- sleep(1)
- //endwhile - reset the pixel offsets to zero
- is_jittery = 0
- pixel_x = old_x
- pixel_y = old_y
-
-/mob/Stat()
- ..()
-
- if(client && client.holder)
-
- if(statpanel("Status")) //not looking at that panel
- stat(null,"Location:\t([x], [y], [z])")
- stat(null,"CPU:\t[world.cpu]")
- stat(null,"Instances:\t[world.contents.len]")
-
- if(master_controller)
- stat(null,"MasterController-[last_tick_duration] ([master_controller.processing?"On":"Off"]-[controller_iteration])")
- stat(null,"Air-[master_controller.air_cost]\t#[global_activeturfs]")
- stat(null,"Sun-[master_controller.sun_cost]")
- stat(null,"Mob-[master_controller.mobs_cost]\t#[mob_list.len]")
- stat(null,"Dis-[master_controller.diseases_cost]\t#[active_diseases.len]")
- stat(null,"Mch-[master_controller.machines_cost]\t#[machines.len]")
- stat(null,"Obj-[master_controller.objects_cost]\t#[processing_objects.len]")
- stat(null,"Net-[master_controller.networks_cost]\tPnet-[master_controller.powernets_cost]")
- stat(null,"NanoUI-[master_controller.nano_cost]\t#[nanomanager.processing_uis.len]")
- stat(null,"Tick-[master_controller.ticker_cost]\tALL-[master_controller.total_cost]")
- else
- stat(null,"MasterController-ERROR")
-
- if(listed_turf && client)
- if(!TurfAdjacent(listed_turf))
- listed_turf = null
- else
- statpanel(listed_turf.name, null, listed_turf)
- for(var/atom/A in listed_turf)
- if(A.invisibility > see_invisible)
- continue
- statpanel(listed_turf.name, null, A)
-
- if(spell_list.len)
- for(var/obj/effect/proc_holder/spell/S in spell_list)
- switch(S.charge_type)
- if("recharge")
- statpanel("[S.panel]","[S.charge_counter/10.0]/[S.charge_max/10]",S)
- if("charges")
- statpanel("[S.panel]","[S.charge_counter]/[S.charge_max]",S)
- if("holdervar")
- statpanel("[S.panel]","[S.holder_var_type] [S.holder_var_amount]",S)
-
-
-
-// facing verbs
-/mob/proc/canface()
- if(!canmove) return 0
- if(client.moving) return 0
- if(world.time < client.move_delay) return 0
- if(stat==2) return 0
- if(anchored) return 0
- if(notransform) return 0
- if(restrained()) return 0
- return 1
-
-//Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it.
-//Robots and brains have their own version so don't worry about them
-/mob/proc/update_canmove()
- var/ko = weakened || paralysis || stat || (status_flags & FAKEDEATH)
- if(ko || resting || buckled)
- canmove = 0
- drop_r_hand() //makes mobs drop items in hands when incapacitated
- drop_l_hand()
- if(!lying)
- if(resting) //Presuming that you're resting on a bed, which would look goofy lying the wrong way
- lying = 90
- else
- lying = pick(90, 270) //180 looks like shit since BYOND inverts rather than turns in that case
- else if(stunned)
- canmove = 0
- else
- lying = 0
- canmove = 1
-
- if(buckled)
- anchored = 1
- canmove = 0
- if(istype(buckled, /obj/structure/stool/bed/chair))
- lying = 0
- else
- lying = 90 //Everything else faces right. TODO: Allow left-facing beds
-
- if(lying)
- density = 0
- else
- density = 1
-
- //Temporarily moved here from the various life() procs
- //I'm fixing stuff incrementally so this will likely find a better home.
- //It just makes sense for now. ~Carn
- if(lying != lying_prev)
- if(lying && !lying_prev)
- fall(ko)
- update_transform()
-
- if(update_icon) //forces a full overlay update
- update_icon = 0
- regenerate_icons()
-
- return canmove
-
-/mob/proc/fall(var/forced)
- drop_l_hand()
- drop_r_hand()
-
-/mob/verb/eastface()
- set hidden = 1
- if(!canface()) return 0
- dir = EAST
- client.move_delay += movement_delay()
- return 1
-
-
-/mob/verb/westface()
- set hidden = 1
- if(!canface()) return 0
- dir = WEST
- client.move_delay += movement_delay()
- return 1
-
-
-/mob/verb/northface()
- set hidden = 1
- if(!canface()) return 0
- dir = NORTH
- client.move_delay += movement_delay()
- return 1
-
-
-/mob/verb/southface()
- set hidden = 1
- if(!canface()) return 0
- dir = SOUTH
- client.move_delay += movement_delay()
- return 1
-
-
-/mob/proc/IsAdvancedToolUser()//This might need a rename but it should replace the can this mob use things check
- return 0
-
-
-/mob/proc/Stun(amount)
- if(status_flags & CANSTUN)
- stunned = max(max(stunned,amount),0) //can't go below 0, getting a low amount of stun doesn't lower your current stun
- update_canmove()
- return
-
-/mob/proc/SetStunned(amount) //if you REALLY need to set stun to a set amount without the whole "can't go below current stunned"
- if(status_flags & CANSTUN)
- stunned = max(amount,0)
- update_canmove()
- return
-
-/mob/proc/AdjustStunned(amount)
- if(status_flags & CANSTUN)
- stunned = max(stunned + amount,0)
- update_canmove()
- return
-
-/mob/proc/Weaken(amount)
- if(status_flags & CANWEAKEN)
- weakened = max(max(weakened,amount),0)
- update_canmove() //updates lying, canmove and icons
- return
-
-/mob/proc/SetWeakened(amount)
- if(status_flags & CANWEAKEN)
- weakened = max(amount,0)
- update_canmove() //updates lying, canmove and icons
- return
-
-/mob/proc/AdjustWeakened(amount)
- if(status_flags & CANWEAKEN)
- weakened = max(weakened + amount,0)
- update_canmove() //updates lying, canmove and icons
- return
-
-/mob/proc/Paralyse(amount)
- if(status_flags & CANPARALYSE)
- paralysis = max(max(paralysis,amount),0)
- update_canmove()
- return
-
-/mob/proc/SetParalysis(amount)
- if(status_flags & CANPARALYSE)
- paralysis = max(amount,0)
- update_canmove()
- return
-
-/mob/proc/AdjustParalysis(amount)
- if(status_flags & CANPARALYSE)
- paralysis = max(paralysis + amount,0)
- update_canmove()
- return
-
-/mob/proc/Sleeping(amount)
- sleeping = max(max(sleeping,amount),0)
- update_canmove()
- return
-
-/mob/proc/SetSleeping(amount)
- sleeping = max(amount,0)
- update_canmove()
- return
-
-/mob/proc/AdjustSleeping(amount)
- sleeping = max(sleeping + amount,0)
- update_canmove()
- return
-
-/mob/proc/Resting(amount)
- resting = max(max(resting,amount),0)
- update_canmove()
- return
-
-/mob/proc/SetResting(amount)
- resting = max(amount,0)
- update_canmove()
- return
-
-/mob/proc/AdjustResting(amount)
- resting = max(resting + amount,0)
- update_canmove()
+/mob/Del()//This makes sure that mobs with clients/keys are not just deleted from the game.
+ mob_list -= src
+ dead_mob_list -= src
+ living_mob_list -= src
+ ghostize()
+ ..()
+
+var/next_mob_id = 0
+/mob/New()
+ tag = "mob_[next_mob_id++]"
+ mob_list += src
+ if(stat == DEAD)
+ dead_mob_list += src
+ else
+ living_mob_list += src
+ ..()
+
+/mob/proc/Cell()
+ set category = "Admin"
+ set hidden = 1
+
+ if(!loc) return 0
+
+ var/datum/gas_mixture/environment = loc.return_air()
+
+ var/t = "\blue Coordinates: [x],[y] \n"
+ t+= "\red Temperature: [environment.temperature] \n"
+ t+= "\blue Nitrogen: [environment.nitrogen] \n"
+ t+= "\blue Oxygen: [environment.oxygen] \n"
+ t+= "\blue Plasma : [environment.toxins] \n"
+ t+= "\blue Carbon Dioxide: [environment.carbon_dioxide] \n"
+ for(var/datum/gas/trace_gas in environment.trace_gases)
+ usr << "\blue [trace_gas.type]: [trace_gas.moles] \n"
+
+ usr.show_message(t, 1)
+
+/mob/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2)
+
+ if(!client) return
+
+ msg = copytext(msg, 1, MAX_MESSAGE_LEN)
+
+ if (type)
+ if(type & 1 && (sdisabilities & BLIND || blinded || paralysis) )//Vision related
+ if (!( alt ))
+ return
+ else
+ msg = alt
+ type = alt_type
+ if (type & 2 && (sdisabilities & DEAF || ear_deaf))//Hearing related
+ if (!( alt ))
+ return
+ else
+ msg = alt
+ type = alt_type
+ if ((type & 1 && sdisabilities & BLIND))
+ return
+ // Added voice muffling for Issue 41.
+ if(stat == UNCONSCIOUS || sleeping > 0)
+ src << "... You can almost hear someone talking ..."
+ else
+ src << msg
+ return
+
+// Show a message to all mobs in sight of this one
+// This would be for visible actions by the src mob
+// message is the message output to anyone who can see e.g. "[src] does something!"
+// self_message (optional) is what the src mob sees e.g. "You do something!"
+// 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))
+ var/msg = message
+ if(self_message && M==src)
+ msg = self_message
+ 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)
+
+
+/mob/proc/movement_delay()
+ return 0
+
+/mob/proc/Life()
+ return
+
+/mob/proc/get_item_by_slot(slot_id)
+ switch(slot_id)
+ if(slot_l_hand)
+ return l_hand
+ if(slot_r_hand)
+ return r_hand
+ return null
+
+/mob/proc/ret_grab(obj/effect/list_container/mobl/L as obj, flag)
+ if ((!( istype(l_hand, /obj/item/weapon/grab) ) && !( istype(r_hand, /obj/item/weapon/grab) )))
+ if (!( L ))
+ return null
+ else
+ return L.container
+ else
+ if (!( L ))
+ L = new /obj/effect/list_container/mobl( null )
+ L.container += src
+ L.master = src
+ if (istype(l_hand, /obj/item/weapon/grab))
+ var/obj/item/weapon/grab/G = l_hand
+ if (!( L.container.Find(G.affecting) ))
+ L.container += G.affecting
+ if (G.affecting)
+ G.affecting.ret_grab(L, 1)
+ if (istype(r_hand, /obj/item/weapon/grab))
+ var/obj/item/weapon/grab/G = r_hand
+ if (!( L.container.Find(G.affecting) ))
+ L.container += G.affecting
+ if (G.affecting)
+ G.affecting.ret_grab(L, 1)
+ if (!( flag ))
+ if (L.master == src)
+ var/list/temp = list( )
+ temp += L.container
+ //L = null
+ del(L)
+ return temp
+ else
+ return L.container
+ return
+
+/mob/proc/restrained()
+ return
+
+//This proc is called whenever someone clicks an inventory ui slot.
+/mob/proc/attack_ui(slot)
+ var/obj/item/W = get_active_hand()
+
+ if(istype(W))
+ if(equip_to_slot_if_possible(W, slot,0,0,0))
+ return 1
+
+ if(!W)
+ // Activate the item
+ var/obj/item/I = get_item_by_slot(slot)
+ if(istype(I))
+ I.attack_hand(src)
+
+ return 0
+
+/mob/proc/put_in_any_hand_if_possible(obj/item/W as obj, del_on_fail = 0, disable_warning = 1, redraw_mob = 1)
+ if(equip_to_slot_if_possible(W, slot_l_hand, del_on_fail, disable_warning, redraw_mob))
+ return 1
+ else if(equip_to_slot_if_possible(W, slot_r_hand, del_on_fail, disable_warning, redraw_mob))
+ return 1
+ return 0
+
+//This is a SAFE proc. Use this instead of equip_to_splot()!
+//set del_on_fail to have it delete W if it fails to equip
+//set disable_warning to disable the 'you are unable to equip that' warning.
+//unset redraw_mob to prevent the mob from being redrawn at the end.
+/mob/proc/equip_to_slot_if_possible(obj/item/W as obj, slot, del_on_fail = 0, disable_warning = 0, redraw_mob = 1)
+ if(!istype(W)) return 0
+ if(!W.mob_can_equip(src, slot, disable_warning))
+ if(del_on_fail)
+ del(W)
+ else
+ if(!disable_warning)
+ src << "\red You are unable to equip that." //Only print if del_on_fail is false
+ return 0
+ equip_to_slot(W, slot, redraw_mob) //This proc should not ever fail.
+ return 1
+
+//This is an UNSAFE proc. It merely handles the actual job of equipping. All the checks on whether you can or can't eqip need to be done before! Use mob_can_equip() for that task.
+//In most cases you will want to use equip_to_slot_if_possible()
+/mob/proc/equip_to_slot(obj/item/W as obj, slot)
+ return
+
+//This is just a commonly used configuration for the equip_to_slot_if_possible() proc, used to equip people when the rounds tarts and when events happen and such.
+/mob/proc/equip_to_slot_or_del(obj/item/W as obj, slot)
+ equip_to_slot_if_possible(W, slot, 1, 1, 0)
+
+//The list of slots by priority. equip_to_appropriate_slot() uses this list. Doesn't matter if a mob type doesn't have a slot.
+var/list/slot_equipment_priority = list( \
+ slot_back,\
+ slot_wear_id,\
+ slot_w_uniform,\
+ slot_wear_suit,\
+ slot_wear_mask,\
+ slot_head,\
+ slot_shoes,\
+ slot_gloves,\
+ slot_ears,\
+ slot_glasses,\
+ slot_belt,\
+ slot_s_store,\
+ slot_l_store,\
+ slot_r_store\
+ )
+
+//puts the item "W" into an appropriate slot in a human's inventory
+//returns 0 if it cannot, 1 if successful
+/mob/proc/equip_to_appropriate_slot(obj/item/W)
+ if(!istype(W)) return 0
+
+ for(var/slot in slot_equipment_priority)
+ if(equip_to_slot_if_possible(W, slot, 0, 1, 1)) //del_on_fail = 0; disable_warning = 0; redraw_mob = 1
+ return 1
+
+ return 0
+
+/mob/proc/reset_view(atom/A)
+ if (client)
+ if (istype(A, /atom/movable))
+ client.perspective = EYE_PERSPECTIVE
+ client.eye = A
+ else
+ if (isturf(loc))
+ client.eye = client.mob
+ client.perspective = MOB_PERSPECTIVE
+ else
+ client.perspective = EYE_PERSPECTIVE
+ client.eye = loc
+ return
+
+
+/mob/proc/show_inv(mob/user)
+ user.set_machine(src)
+ var/dat = {"
+
+ [name]
+
+
Left Hand: [(l_hand&&!(l_hand.flags&ABSTRACT)) ? l_hand : "Nothing"]
+
Right Hand: [(r_hand&&!(r_hand.flags&ABSTRACT)) ? r_hand : "Nothing"]
+
Close
+ "}
+ user << browse(dat, "window=mob\ref[src];size=325x500")
+ onclose(user, "mob\ref[src]")
+
+
+/mob/verb/mode()
+ set name = "Activate Held Object"
+ set category = "Object"
+ set src = usr
+
+ if(istype(loc,/obj/mecha)) return
+
+ if(hand)
+ var/obj/item/W = l_hand
+ if (W)
+ W.attack_self(src)
+ update_inv_l_hand(0)
+ else
+ var/obj/item/W = r_hand
+ if (W)
+ W.attack_self(src)
+ update_inv_r_hand(0)
+ if(next_move < world.time)
+ next_move = world.time + 2
+ return
+
+/*
+/mob/verb/dump_source()
+
+ var/master = ""
+ for(var/t in typesof(/area))
+ master += text("[]\n", t)
+ //Foreach goto(26)
+ src << browse(master)
+ return
+*/
+
+/mob/verb/memory()
+ set name = "Notes"
+ set category = "IC"
+ if(mind)
+ mind.show_memory(src)
+ else
+ src << "The game appears to have misplaced your mind datum, so we can't show you your notes."
+
+/mob/verb/add_memory(msg as message)
+ set name = "Add Note"
+ set category = "IC"
+
+ msg = copytext(msg, 1, MAX_MESSAGE_LEN)
+ msg = sanitize(msg)
+
+ if(mind)
+ mind.store_memory(msg)
+ else
+ src << "The game appears to have misplaced your mind datum, so we can't show you your notes."
+
+/mob/proc/store_memory(msg as message, popup, sane = 1)
+ msg = copytext(msg, 1, MAX_MESSAGE_LEN)
+
+ if (sane)
+ msg = sanitize(msg)
+
+ if (length(memory) == 0)
+ memory += msg
+ else
+ memory += "
[msg]"
+
+ if (popup)
+ memory()
+
+/*
+/mob/verb/help()
+ set name = "Help"
+ src << browse('html/help.html', "window=help")
+ return
+*/
+
+/mob/verb/abandon_mob()
+ set name = "Respawn"
+ set category = "OOC"
+
+ if (!( abandon_allowed ))
+ return
+ if ((stat != 2 || !( ticker )))
+ usr << "\blue You must be dead to use this!"
+ return
+
+ log_game("[usr.name]/[usr.key] used abandon mob.")
+
+ usr << "\blue Please roleplay correctly!"
+
+ if(!client)
+ log_game("[usr.key] AM failed due to disconnect.")
+ return
+ client.screen.Cut()
+ if(!client)
+ log_game("[usr.key] AM failed due to disconnect.")
+ return
+
+ var/mob/new_player/M = new /mob/new_player()
+ if(!client)
+ log_game("[usr.key] AM failed due to disconnect.")
+ del(M)
+ return
+
+ M.key = key
+// M.Login() //wat
+ return
+
+/client/verb/changes()
+ set name = "Changelog"
+ set category = "OOC"
+ getFiles(
+ 'html/postcardsmall.jpg',
+ 'html/somerights20.png',
+ 'html/88x31.png',
+ 'html/bug-minus.png',
+ 'html/cross-circle.png',
+ 'html/hard-hat-exclamation.png',
+ 'html/image-minus.png',
+ 'html/image-plus.png',
+ 'html/music-minus.png',
+ 'html/music-plus.png',
+ 'html/tick-circle.png',
+ 'html/wrench-screwdriver.png',
+ 'html/spell-check.png',
+ 'html/burn-exclamation.png',
+ 'html/chevron.png',
+ 'html/chevron-expand.png',
+ 'html/changelog.css',
+ 'html/changelog.js',
+ 'html/changelog.html'
+ )
+ src << browse('html/changelog.html', "window=changes;size=675x650")
+ if(prefs.lastchangelog != changelog_hash)
+ prefs.lastchangelog = changelog_hash
+ prefs.save_preferences()
+ winset(src, "rpane.changelog", "background-color=none;font-style=;")
+
+/mob/verb/observe()
+ set name = "Observe"
+ set category = "OOC"
+ var/is_admin = 0
+
+ if(check_rights_for(client,R_ADMIN))
+ is_admin = 1
+ else if(stat != DEAD || istype(src, /mob/new_player))
+ usr << "\blue You must be observing to use this!"
+ return
+
+ if(is_admin && stat == DEAD)
+ is_admin = 0
+
+ var/list/names = list()
+ var/list/namecounts = list()
+ var/list/creatures = list()
+
+ for(var/obj/O in world) //EWWWWWWWWWWWWWWWWWWWWWWWW ~needs to be optimised
+ if(!O.loc)
+ continue
+ if(istype(O, /obj/item/weapon/disk/nuclear))
+ var/name = "Nuclear Disk"
+ if (names.Find(name))
+ namecounts[name]++
+ name = "[name] ([namecounts[name]])"
+ else
+ names.Add(name)
+ namecounts[name] = 1
+ creatures[name] = O
+
+ if(istype(O, /obj/machinery/singularity))
+ var/name = "Singularity"
+ if (names.Find(name))
+ namecounts[name]++
+ name = "[name] ([namecounts[name]])"
+ else
+ names.Add(name)
+ namecounts[name] = 1
+ creatures[name] = O
+
+ if(istype(O, /obj/machinery/bot))
+ var/name = "BOT: [O.name]"
+ if (names.Find(name))
+ namecounts[name]++
+ name = "[name] ([namecounts[name]])"
+ else
+ names.Add(name)
+ namecounts[name] = 1
+ creatures[name] = O
+
+
+ for(var/mob/M in sortAtom(mob_list))
+ var/name = M.name
+ if (names.Find(name))
+ namecounts[name]++
+ name = "[name] ([namecounts[name]])"
+ else
+ names.Add(name)
+ namecounts[name] = 1
+
+ creatures[name] = M
+
+
+ client.perspective = EYE_PERSPECTIVE
+
+ var/eye_name = null
+
+ var/ok = "[is_admin ? "Admin Observe" : "Observe"]"
+ eye_name = input("Please, select a player!", ok, null, null) as null|anything in creatures
+
+ if (!eye_name)
+ return
+
+ var/mob/mob_eye = creatures[eye_name]
+
+ if(client && mob_eye)
+ client.eye = mob_eye
+ if (is_admin)
+ client.adminobs = 1
+ if(mob_eye == client.mob || client.eye == client.mob)
+ client.adminobs = 0
+
+/mob/verb/cancel_camera()
+ set name = "Cancel Camera View"
+ set category = "OOC"
+ reset_view(null)
+ unset_machine()
+ if(istype(src, /mob/living))
+ if(src:cameraFollow)
+ src:cameraFollow = null
+
+/mob/Topic(href, href_list)
+ if(href_list["mach_close"])
+ var/t1 = text("window=[href_list["mach_close"]]")
+ unset_machine()
+ src << browse(null, t1)
+
+ if(href_list["refresh"])
+ if(machine && in_range(src, usr))
+ show_inv(machine)
+
+ if(!usr.stat && usr.canmove && !usr.restrained() && Adjacent(usr))
+ if(href_list["item"])
+ var/slot = text2num(href_list["item"])
+ var/obj/item/what = get_item_by_slot(slot)
+
+ if(what && what.canremove)
+ visible_message("[usr] tries to remove [src]'s [what.name].", \
+ "[usr] tries to remove [src]'s [what.name].")
+ what.add_fingerprint(usr)
+ if(do_mob(usr, src, STRIP_DELAY))
+ if(what && Adjacent(usr))
+ u_equip(what)
+ else
+ what = usr.get_active_hand()
+ if(what && what.mob_can_equip(src, slot, 1))
+ visible_message("[usr] tries to put [what] on [src].")
+ if(do_mob(usr, src, STRIP_DELAY * 0.5))
+ if(what && Adjacent(usr))
+ usr.u_equip(what)
+ equip_to_slot_if_possible(what, slot, 0, 1)
+
+ if(usr.machine == src)
+ if(Adjacent(usr))
+ show_inv(usr)
+ else
+ usr << browse(null,"window=mob\ref[src]")
+
+
+/mob/MouseDrop(mob/M)
+ ..()
+ if(M != usr) return
+ if(usr == src) return
+ if(!Adjacent(usr)) return
+ if(istype(M, /mob/living/silicon/ai)) return
+ show_inv(usr)
+
+
+/mob/verb/stop_pulling()
+
+ set name = "Stop Pulling"
+ set category = "IC"
+
+ if(pulling)
+ pulling.pulledby = null
+ pulling = null
+
+/mob/proc/start_pulling(var/atom/movable/AM)
+ if ( !AM || !usr || src==AM || !isturf(src.loc) ) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort!
+ return
+ if (!( AM.anchored ))
+ AM.add_fingerprint(src)
+
+ // If we're pulling something then drop what we're currently pulling and pull this instead.
+ if(pulling)
+ // Are we trying to pull something we are already pulling? Then just stop here, no need to continue.
+ if(AM == pulling)
+ return
+ stop_pulling()
+
+ src.pulling = AM
+ AM.pulledby = src
+ if(ismob(AM))
+ var/mob/M = AM
+ if(!iscarbon(src))
+ M.LAssailant = null
+ else
+ M.LAssailant = usr
+
+
+/mob/proc/can_use_hands()
+ return
+
+/mob/proc/is_active()
+ return (0 >= usr.stat)
+
+/mob/proc/see(message)
+ if(!is_active())
+ return 0
+ src << message
+ return 1
+
+/mob/proc/show_viewers(message)
+ for(var/mob/M in viewers())
+ M.see(message)
+
+/*
+adds a dizziness amount to a mob
+use this rather than directly changing var/dizziness
+since this ensures that the dizzy_process proc is started
+currently only humans get dizzy
+
+value of dizziness ranges from 0 to 1000
+below 100 is not dizzy
+*/
+/mob/proc/make_dizzy(var/amount)
+ if(!istype(src, /mob/living/carbon/human)) // for the moment, only humans get dizzy
+ return
+
+ dizziness = min(1000, dizziness + amount) // store what will be new value
+ // clamped to max 1000
+ if(dizziness > 100 && !is_dizzy)
+ spawn(0)
+ dizzy_process()
+
+
+/*
+dizzy process - wiggles the client's pixel offset over time
+spawned from make_dizzy(), will terminate automatically when dizziness gets <100
+note dizziness decrements automatically in the mob's Life() proc.
+*/
+/mob/proc/dizzy_process()
+ is_dizzy = 1
+ while(dizziness > 100)
+ if(client)
+ var/amplitude = dizziness*(sin(dizziness * 0.044 * world.time) + 1) / 70
+ client.pixel_x = amplitude * sin(0.008 * dizziness * world.time)
+ client.pixel_y = amplitude * cos(0.008 * dizziness * world.time)
+
+ sleep(1)
+ //endwhile - reset the pixel offsets to zero
+ is_dizzy = 0
+ if(client)
+ client.pixel_x = 0
+ client.pixel_y = 0
+
+// jitteriness - copy+paste of dizziness
+
+/mob/proc/make_jittery(var/amount)
+ if(!istype(src, /mob/living/carbon/human)) // for the moment, only humans get dizzy
+ return
+
+ jitteriness = min(1000, jitteriness + amount) // store what will be new value
+ // clamped to max 1000
+ if(jitteriness > 100 && !is_jittery)
+ spawn(0)
+ jittery_process()
+
+
+// Typo from the oriignal coder here, below lies the jitteriness process. So make of his code what you will, the previous comment here was just a copypaste of the above.
+/mob/proc/jittery_process()
+ var/old_x = pixel_x
+ var/old_y = pixel_y
+ is_jittery = 1
+ while(jitteriness > 100)
+// var/amplitude = jitteriness*(sin(jitteriness * 0.044 * world.time) + 1) / 70
+// pixel_x = amplitude * sin(0.008 * jitteriness * world.time)
+// pixel_y = amplitude * cos(0.008 * jitteriness * world.time)
+
+ var/amplitude = min(4, jitteriness / 100)
+ pixel_x = rand(-amplitude, amplitude)
+ pixel_y = rand(-amplitude/3, amplitude/3)
+
+ sleep(1)
+ //endwhile - reset the pixel offsets to zero
+ is_jittery = 0
+ pixel_x = old_x
+ pixel_y = old_y
+
+/mob/Stat()
+ ..()
+
+ if(client && client.holder)
+
+ if(statpanel("Status")) //not looking at that panel
+ stat(null,"Location:\t([x], [y], [z])")
+ stat(null,"CPU:\t[world.cpu]")
+ stat(null,"Instances:\t[world.contents.len]")
+
+ if(master_controller)
+ stat(null,"MasterController-[last_tick_duration] ([master_controller.processing?"On":"Off"]-[controller_iteration])")
+ stat(null,"Air-[master_controller.air_cost]\t#[global_activeturfs]")
+ stat(null,"Sun-[master_controller.sun_cost]")
+ stat(null,"Mob-[master_controller.mobs_cost]\t#[mob_list.len]")
+ stat(null,"Dis-[master_controller.diseases_cost]\t#[active_diseases.len]")
+ stat(null,"Mch-[master_controller.machines_cost]\t#[machines.len]")
+ stat(null,"Obj-[master_controller.objects_cost]\t#[processing_objects.len]")
+ stat(null,"Net-[master_controller.networks_cost]\tPnet-[master_controller.powernets_cost]")
+ stat(null,"NanoUI-[master_controller.nano_cost]\t#[nanomanager.processing_uis.len]")
+ stat(null,"Tick-[master_controller.ticker_cost]\tALL-[master_controller.total_cost]")
+ else
+ stat(null,"MasterController-ERROR")
+
+ if(listed_turf && client)
+ if(!TurfAdjacent(listed_turf))
+ listed_turf = null
+ else
+ statpanel(listed_turf.name, null, listed_turf)
+ for(var/atom/A in listed_turf)
+ if(A.invisibility > see_invisible)
+ continue
+ statpanel(listed_turf.name, null, A)
+
+ if(spell_list.len)
+ for(var/obj/effect/proc_holder/spell/S in spell_list)
+ switch(S.charge_type)
+ if("recharge")
+ statpanel("[S.panel]","[S.charge_counter/10.0]/[S.charge_max/10]",S)
+ if("charges")
+ statpanel("[S.panel]","[S.charge_counter]/[S.charge_max]",S)
+ if("holdervar")
+ statpanel("[S.panel]","[S.holder_var_type] [S.holder_var_amount]",S)
+
+
+
+// facing verbs
+/mob/proc/canface()
+ if(!canmove) return 0
+ if(client.moving) return 0
+ if(world.time < client.move_delay) return 0
+ if(stat==2) return 0
+ if(anchored) return 0
+ if(notransform) return 0
+ if(restrained()) return 0
+ return 1
+
+//Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it.
+//Robots and brains have their own version so don't worry about them
+/mob/proc/update_canmove()
+ var/ko = weakened || paralysis || stat || (status_flags & FAKEDEATH)
+ if(ko || resting || buckled)
+ canmove = 0
+ drop_r_hand() //makes mobs drop items in hands when incapacitated
+ drop_l_hand()
+ if(!lying)
+ if(resting) //Presuming that you're resting on a bed, which would look goofy lying the wrong way
+ lying = 90
+ else
+ lying = pick(90, 270) //180 looks like shit since BYOND inverts rather than turns in that case
+ else if(stunned)
+ canmove = 0
+ else
+ lying = 0
+ canmove = 1
+
+ if(buckled)
+ anchored = 1
+ canmove = 0
+ if(istype(buckled, /obj/structure/stool/bed/chair))
+ lying = 0
+ else
+ lying = 90 //Everything else faces right. TODO: Allow left-facing beds
+
+ if(lying)
+ density = 0
+ else
+ density = 1
+
+ //Temporarily moved here from the various life() procs
+ //I'm fixing stuff incrementally so this will likely find a better home.
+ //It just makes sense for now. ~Carn
+ if(lying != lying_prev)
+ if(lying && !lying_prev)
+ fall(ko)
+ update_transform()
+
+ if(update_icon) //forces a full overlay update
+ update_icon = 0
+ regenerate_icons()
+
+ return canmove
+
+/mob/proc/fall(var/forced)
+ drop_l_hand()
+ drop_r_hand()
+
+/mob/verb/eastface()
+ set hidden = 1
+ if(!canface()) return 0
+ dir = EAST
+ client.move_delay += movement_delay()
+ return 1
+
+
+/mob/verb/westface()
+ set hidden = 1
+ if(!canface()) return 0
+ dir = WEST
+ client.move_delay += movement_delay()
+ return 1
+
+
+/mob/verb/northface()
+ set hidden = 1
+ if(!canface()) return 0
+ dir = NORTH
+ client.move_delay += movement_delay()
+ return 1
+
+
+/mob/verb/southface()
+ set hidden = 1
+ if(!canface()) return 0
+ dir = SOUTH
+ client.move_delay += movement_delay()
+ return 1
+
+
+/mob/proc/IsAdvancedToolUser()//This might need a rename but it should replace the can this mob use things check
+ return 0
+
+
+/mob/proc/Stun(amount)
+ if(status_flags & CANSTUN)
+ stunned = max(max(stunned,amount),0) //can't go below 0, getting a low amount of stun doesn't lower your current stun
+ update_canmove()
+ return
+
+/mob/proc/SetStunned(amount) //if you REALLY need to set stun to a set amount without the whole "can't go below current stunned"
+ if(status_flags & CANSTUN)
+ stunned = max(amount,0)
+ update_canmove()
+ return
+
+/mob/proc/AdjustStunned(amount)
+ if(status_flags & CANSTUN)
+ stunned = max(stunned + amount,0)
+ update_canmove()
+ return
+
+/mob/proc/Weaken(amount)
+ if(status_flags & CANWEAKEN)
+ weakened = max(max(weakened,amount),0)
+ update_canmove() //updates lying, canmove and icons
+ return
+
+/mob/proc/SetWeakened(amount)
+ if(status_flags & CANWEAKEN)
+ weakened = max(amount,0)
+ update_canmove() //updates lying, canmove and icons
+ return
+
+/mob/proc/AdjustWeakened(amount)
+ if(status_flags & CANWEAKEN)
+ weakened = max(weakened + amount,0)
+ update_canmove() //updates lying, canmove and icons
+ return
+
+/mob/proc/Paralyse(amount)
+ if(status_flags & CANPARALYSE)
+ paralysis = max(max(paralysis,amount),0)
+ update_canmove()
+ return
+
+/mob/proc/SetParalysis(amount)
+ if(status_flags & CANPARALYSE)
+ paralysis = max(amount,0)
+ update_canmove()
+ return
+
+/mob/proc/AdjustParalysis(amount)
+ if(status_flags & CANPARALYSE)
+ paralysis = max(paralysis + amount,0)
+ update_canmove()
+ return
+
+/mob/proc/Sleeping(amount)
+ sleeping = max(max(sleeping,amount),0)
+ update_canmove()
+ return
+
+/mob/proc/SetSleeping(amount)
+ sleeping = max(amount,0)
+ update_canmove()
+ return
+
+/mob/proc/AdjustSleeping(amount)
+ sleeping = max(sleeping + amount,0)
+ update_canmove()
+ return
+
+/mob/proc/Resting(amount)
+ resting = max(max(resting,amount),0)
+ update_canmove()
+ return
+
+/mob/proc/SetResting(amount)
+ resting = max(amount,0)
+ update_canmove()
+ return
+
+/mob/proc/AdjustResting(amount)
+ resting = max(resting + amount,0)
+ update_canmove()
return
\ No newline at end of file
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index 569aa69b757..98436558302 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -1,507 +1,507 @@
-/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG), newname = null)
- if (notransform)
- return
- //Handle items on mob
-
- //first implants
- var/list/implants = list()
- if (tr_flags & TR_KEEPIMPLANTS)
- for(var/obj/item/weapon/implant/W in src)
- implants += W
-
- if(tr_flags & TR_KEEPITEMS)
- for(var/obj/item/W in (src.contents-implants))
- drop_from_inventory(W)
-
- //Make mob invisible and spawn animation
- regenerate_icons()
- notransform = 1
- canmove = 0
- stunned = 1
- icon = null
- invisibility = 101
- var/atom/movable/overlay/animation = new /atom/movable/overlay( loc )
- animation.icon_state = "blank"
- animation.icon = 'icons/mob/mob.dmi'
- animation.master = src
- flick("h2monkey", animation)
- sleep(22)
- //animation = null
- var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey( loc )
- del(animation)
-
-
-
- // hash the original name?
- if (tr_flags & TR_HASHNAME)
- O.name = "monkey ([copytext(md5(real_name), 2, 6)])"
- O.real_name = "monkey ([copytext(md5(real_name), 2, 6)])"
- if (newname) //if there's a name as an argument, always take that one over the current name
- O.name = newname
- O.real_name = newname
-
- //handle DNA and other attributes
- O.dna = dna
- dna = null
- if (!(tr_flags & TR_KEEPSE))
- O.dna.struc_enzymes = setblock(O.dna.struc_enzymes, RACEBLOCK, construct_block(BAD_MUTATION_DIFFICULTY,BAD_MUTATION_DIFFICULTY))
- if(suiciding)
- O.suiciding = suiciding
- O.loc = loc
- O.a_intent = "harm"
-
- //keep viruses?
- if (tr_flags & TR_KEEPVIRUS)
- O.viruses = viruses
- viruses = list()
- for(var/datum/disease/D in O.viruses)
- D.affected_mob = O
-
- //keep damage?
- if (tr_flags & TR_KEEPDAMAGE)
- O.setToxLoss(getToxLoss())
- O.adjustBruteLoss(getBruteLoss())
- O.setOxyLoss(getOxyLoss())
- O.adjustFireLoss(getFireLoss())
-
- //re-add implants to new mob
- for(var/obj/item/weapon/implant/I in implants)
- I.loc = O
- I.implanted = O
-
- //transfer mind and delete old mob
- if(mind)
- mind.transfer_to(O)
- if (tr_flags & TR_DEFAULTMSG)
- O << "You are now a monkey."
- updateappearance(O)
- . = O
- if ( !(tr_flags & TR_KEEPSRC) ) //flag should be used if monkeyize() is called inside another proc of src so that one does not crash
- del(src)
- return
-
-
-
-////////////////////////// Humanize //////////////////////////////
-//Could probably be merged with monkeyize but other transformations got their own procs, too
-
-/mob/living/carbon/proc/humanize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG), newname = null)
- if (notransform)
- return
- //Handle items on mob
-
- //first implants
- var/list/implants = list()
- if (tr_flags & TR_KEEPIMPLANTS)
- for(var/obj/item/weapon/implant/W in src)
- implants += W
-
- //now the rest
- if (tr_flags & TR_KEEPITEMS)
- for(var/obj/item/W in (src.contents-implants))
- u_equip(W)
- if (client)
- client.screen -= W
- if (W)
- W.loc = loc
- W.dropped(src)
- W.layer = initial(W.layer)
-
- // for(var/obj/item/W in src)
- // drop_from_inventory(W)
-
- //Make mob invisible and spawn animation
- regenerate_icons()
- notransform = 1
- canmove = 0
- stunned = 1
- icon = null
- invisibility = 101
- var/atom/movable/overlay/animation = new( loc )
- animation.icon_state = "blank"
- animation.icon = 'icons/mob/mob.dmi'
- animation.master = src
- flick("monkey2h", animation)
- sleep(22)
- var/mob/living/carbon/human/O = new( loc )
- for(var/obj/item/C in O.loc)
- O.equip_to_appropriate_slot(C)
- del(animation)
-
-
- O.gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE
- O.dna = dna
- dna = null
- if (newname) //if there's a name as an argument, always take that one over the current name
- O.real_name = newname
- else
- if ( !(cmptext ("monkey",copytext(O.dna.real_name,1,7)) ) )
- O.real_name = O.dna.real_name
- else
- O.real_name = random_name(O.gender)
- O.name = O.real_name
-
- if (!(tr_flags & TR_KEEPSE))
- O.dna.struc_enzymes = setblock(O.dna.struc_enzymes, RACEBLOCK, construct_block(1,BAD_MUTATION_DIFFICULTY))
-
- if(suiciding)
- O.suiciding = suiciding
-
- O.loc = loc
-
- //keep viruses?
- if (tr_flags & TR_KEEPVIRUS)
- O.viruses = viruses
- viruses = list()
- for(var/datum/disease/D in O.viruses)
- D.affected_mob = O
-
- //keep damage?
- if (tr_flags & TR_KEEPDAMAGE)
- O.setToxLoss(getToxLoss())
- O.adjustBruteLoss(getBruteLoss())
- O.setOxyLoss(getOxyLoss())
- O.adjustFireLoss(getFireLoss())
-
- //re-add implants to new mob
- for(var/obj/item/weapon/implant/I in implants)
- I.loc = O
- I.implanted = O
-
- if(mind)
- mind.transfer_to(O)
- O.a_intent = "help"
- if (tr_flags & TR_DEFAULTMSG)
- O << "You are now a human."
- updateappearance(O)
- . = O
- if ( !(tr_flags & TR_KEEPSRC) ) //don't delete src yet if it's needed to finish calling proc
- del(src)
- return
-
-/mob/new_player/AIize()
- spawning = 1
- return ..()
-
-/mob/living/carbon/human/AIize()
- if (notransform)
- return
- for(var/t in organs)
- del(t)
-
- return ..()
-
-/mob/living/carbon/AIize()
- if (notransform)
- return
- for(var/obj/item/W in src)
- drop_from_inventory(W)
- regenerate_icons()
- notransform = 1
- canmove = 0
- icon = null
- invisibility = 101
- return ..()
-
-/mob/proc/AIize()
- if(client)
- src << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1) // stop the jams for AIs
- var/mob/living/silicon/ai/O = new (loc,,,1)//No MMI but safety is in effect.
- O.invisibility = 0
- O.aiRestorePowerRoutine = 0
-
- if(mind)
- mind.transfer_to(O)
- else
- O.key = key
-
- var/obj/loc_landmark
- for(var/obj/effect/landmark/start/sloc in landmarks_list)
- if (sloc.name != "AI")
- continue
- if (locate(/mob/living) in sloc.loc)
- continue
- loc_landmark = sloc
- if (!loc_landmark)
- for(var/obj/effect/landmark/tripai in landmarks_list)
- if (tripai.name == "tripai")
- if(locate(/mob/living) in tripai.loc)
- continue
- loc_landmark = tripai
- if (!loc_landmark)
- O << "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone."
- for(var/obj/effect/landmark/start/sloc in landmarks_list)
- if (sloc.name == "AI")
- loc_landmark = sloc
-
- O.loc = loc_landmark.loc
- for (var/obj/item/device/radio/intercom/comm in O.loc)
- comm.ai += O
-
- O << "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras)."
- O << "To look at other parts of the station, click on yourself to get a camera menu."
- O << "While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc."
- O << "To use something, simply click on it."
- O << {"Use say ":b to speak to your cyborgs through binary."}
- if (!(ticker && ticker.mode && (O.mind in ticker.mode.malf_ai)))
- O.show_laws()
- O << "These laws may be changed by other players, or by you being the traitor."
-
- O.verbs += /mob/living/silicon/ai/proc/ai_call_shuttle
- O.verbs += /mob/living/silicon/ai/proc/show_laws_verb
- O.verbs += /mob/living/silicon/ai/proc/ai_camera_track
- O.verbs += /mob/living/silicon/ai/proc/ai_alerts
- O.verbs += /mob/living/silicon/ai/proc/ai_camera_list
- O.verbs += /mob/living/silicon/ai/proc/ai_statuschange
- O.verbs += /mob/living/silicon/ai/proc/ai_roster
-
- O.job = "AI"
-
- O.rename_self("ai",1)
- . = O
- del(src)
- return
-
-
-//human -> robot
-/mob/living/carbon/human/proc/Robotize(var/delete_items = 0)
- if (notransform)
- return
- for(var/obj/item/W in src)
- if(delete_items)
- del(W)
- else
- drop_from_inventory(W)
- regenerate_icons()
- notransform = 1
- canmove = 0
- icon = null
- invisibility = 101
- for(var/t in organs)
- del(t)
-
- var/mob/living/silicon/robot/O = new /mob/living/silicon/robot( loc )
-
- // cyborgs produced by Robotize get an automatic power cell
- O.cell = new(O)
- O.cell.maxcharge = 7500
- O.cell.charge = 7500
-
-
- O.gender = gender
- O.invisibility = 0
-
-
- if(mind) //TODO
- mind.transfer_to(O)
- if(mind.special_role)
- O.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite")
- else
- O.key = key
-
- O.loc = loc
- O.job = "Cyborg"
-
- O.mmi = new /obj/item/device/mmi(O)
- O.mmi.transfer_identity(src)//Does not transfer key/client.
-
- . = O
- del(src)
-
-//human -> alien
-/mob/living/carbon/human/proc/Alienize()
- if (notransform)
- return
- for(var/obj/item/W in src)
- drop_from_inventory(W)
- regenerate_icons()
- notransform = 1
- canmove = 0
- icon = null
- invisibility = 101
- for(var/t in organs)
- del(t)
-
- var/alien_caste = pick("Hunter","Sentinel","Drone")
- var/mob/living/carbon/alien/humanoid/new_xeno
- switch(alien_caste)
- if("Hunter")
- new_xeno = new /mob/living/carbon/alien/humanoid/hunter(loc)
- if("Sentinel")
- new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(loc)
- if("Drone")
- new_xeno = new /mob/living/carbon/alien/humanoid/drone(loc)
-
- new_xeno.a_intent = "harm"
- new_xeno.key = key
-
- new_xeno << "You are now an alien."
- . = new_xeno
- del(src)
-
-/mob/living/carbon/human/proc/slimeize(reproduce as num)
- if (notransform)
- return
- for(var/obj/item/W in src)
- drop_from_inventory(W)
- regenerate_icons()
- notransform = 1
- canmove = 0
- icon = null
- invisibility = 101
- for(var/t in organs)
- del(t)
-
- var/mob/living/carbon/slime/new_slime
- if(reproduce)
- var/number = pick(14;2,3,4) //reproduce (has a small chance of producing 3 or 4 offspring)
- var/list/babies = list()
- for(var/i=1,i<=number,i++)
- var/mob/living/carbon/slime/M = new/mob/living/carbon/slime(loc)
- M.nutrition = round(nutrition/number)
- step_away(M,src)
- babies += M
- new_slime = pick(babies)
- else
- new_slime = new /mob/living/carbon/slime(loc)
- new_slime.a_intent = "harm"
- new_slime.key = key
-
- new_slime << "You are now a slime. Skreee!"
- . = new_slime
- del(src)
-
-/mob/living/carbon/human/proc/Blobize()
- if (notransform)
- return
- var/obj/effect/blob/core/new_blob = new /obj/effect/blob/core (loc)
- new_blob.create_overmind(src.client , 1)
- gib(src)
-
-
-
-/mob/living/carbon/human/proc/corgize()
- if (notransform)
- return
- for(var/obj/item/W in src)
- drop_from_inventory(W)
- regenerate_icons()
- notransform = 1
- canmove = 0
- icon = null
- invisibility = 101
- for(var/t in organs) //this really should not be necessary
- del(t)
-
- var/mob/living/simple_animal/corgi/new_corgi = new /mob/living/simple_animal/corgi (loc)
- new_corgi.a_intent = "harm"
- new_corgi.key = key
-
- new_corgi << "You are now a Corgi. Yap Yap!"
- . = new_corgi
- del(src)
-
-/mob/living/carbon/human/Animalize()
-
- var/list/mobtypes = typesof(/mob/living/simple_animal)
- var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") in mobtypes
-
- if(!safe_animal(mobpath))
- usr << "\red Sorry but this mob type is currently unavailable."
- return
-
- if(notransform)
- return
- for(var/obj/item/W in src)
- drop_from_inventory(W)
-
- regenerate_icons()
- notransform = 1
- canmove = 0
- icon = null
- invisibility = 101
-
- for(var/t in organs)
- del(t)
-
- var/mob/new_mob = new mobpath(src.loc)
-
- new_mob.key = key
- new_mob.a_intent = "harm"
-
-
- new_mob << "You suddenly feel more... animalistic."
- . = new_mob
- del(src)
-
-/mob/proc/Animalize()
-
- var/list/mobtypes = typesof(/mob/living/simple_animal)
- var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") in mobtypes
-
- if(!safe_animal(mobpath))
- usr << "\red Sorry but this mob type is currently unavailable."
- return
-
- var/mob/new_mob = new mobpath(src.loc)
-
- new_mob.key = key
- new_mob.a_intent = "harm"
- new_mob << "You feel more... animalistic"
-
- . = new_mob
- del(src)
-
-/* Certain mob types have problems and should not be allowed to be controlled by players.
- *
- * This proc is here to force coders to manually place their mob in this list, hopefully tested.
- * This also gives a place to explain -why- players shouldnt be turn into certain mobs and hopefully someone can fix them.
- */
-/mob/proc/safe_animal(var/MP)
-
-//Bad mobs! - Remember to add a comment explaining what's wrong with the mob
- if(!MP)
- return 0 //Sanity, this should never happen.
-
-// if(ispath(MP, /mob/living/simple_animal/space_worm)) //Goodbye Space Worms 2014
-// return 0 //Unfinished. Very buggy, they seem to just spawn additional space worms everywhere and eating your own tail results in new worms spawning.
-
- if(ispath(MP, /mob/living/simple_animal/construct/behemoth))
- return 0 //I think this may have been an unfinished WiP or something. These constructs should really have their own class simple_animal/construct/subtype
-
- if(ispath(MP, /mob/living/simple_animal/construct/armoured))
- return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype
-
- if(ispath(MP, /mob/living/simple_animal/construct/wraith))
- return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype
-
- if(ispath(MP, /mob/living/simple_animal/construct/builder))
- return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype
-
-//Good mobs!
- if(ispath(MP, /mob/living/simple_animal/cat))
- return 1
- if(ispath(MP, /mob/living/simple_animal/corgi))
- return 1
- if(ispath(MP, /mob/living/simple_animal/crab))
- return 1
- if(ispath(MP, /mob/living/simple_animal/hostile/carp))
- return 1
- if(ispath(MP, /mob/living/simple_animal/hostile/mushroom))
- return 1
- if(ispath(MP, /mob/living/simple_animal/shade))
- return 1
- if(ispath(MP, /mob/living/simple_animal/tomato))
- return 1
- if(ispath(MP, /mob/living/simple_animal/mouse))
- return 1 //It is impossible to pull up the player panel for mice (Fixed! - Nodrak)
- if(ispath(MP, /mob/living/simple_animal/hostile/bear))
- return 1 //Bears will auto-attack mobs, even if they're player controlled (Fixed! - Nodrak)
- if(ispath(MP, /mob/living/simple_animal/parrot))
- return 1 //Parrots are no longer unfinished! -Nodrak
-
- //Not in here? Must be untested!
- return 0
-
-
-
+/mob/living/carbon/proc/monkeyize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG), newname = null)
+ if (notransform)
+ return
+ //Handle items on mob
+
+ //first implants
+ var/list/implants = list()
+ if (tr_flags & TR_KEEPIMPLANTS)
+ for(var/obj/item/weapon/implant/W in src)
+ implants += W
+
+ if(tr_flags & TR_KEEPITEMS)
+ for(var/obj/item/W in (src.contents-implants))
+ drop_from_inventory(W)
+
+ //Make mob invisible and spawn animation
+ regenerate_icons()
+ notransform = 1
+ canmove = 0
+ stunned = 1
+ icon = null
+ invisibility = 101
+ var/atom/movable/overlay/animation = new /atom/movable/overlay( loc )
+ animation.icon_state = "blank"
+ animation.icon = 'icons/mob/mob.dmi'
+ animation.master = src
+ flick("h2monkey", animation)
+ sleep(22)
+ //animation = null
+ var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey( loc )
+ del(animation)
+
+
+
+ // hash the original name?
+ if (tr_flags & TR_HASHNAME)
+ O.name = "monkey ([copytext(md5(real_name), 2, 6)])"
+ O.real_name = "monkey ([copytext(md5(real_name), 2, 6)])"
+ if (newname) //if there's a name as an argument, always take that one over the current name
+ O.name = newname
+ O.real_name = newname
+
+ //handle DNA and other attributes
+ O.dna = dna
+ dna = null
+ if (!(tr_flags & TR_KEEPSE))
+ O.dna.struc_enzymes = setblock(O.dna.struc_enzymes, RACEBLOCK, construct_block(BAD_MUTATION_DIFFICULTY,BAD_MUTATION_DIFFICULTY))
+ if(suiciding)
+ O.suiciding = suiciding
+ O.loc = loc
+ O.a_intent = "harm"
+
+ //keep viruses?
+ if (tr_flags & TR_KEEPVIRUS)
+ O.viruses = viruses
+ viruses = list()
+ for(var/datum/disease/D in O.viruses)
+ D.affected_mob = O
+
+ //keep damage?
+ if (tr_flags & TR_KEEPDAMAGE)
+ O.setToxLoss(getToxLoss())
+ O.adjustBruteLoss(getBruteLoss())
+ O.setOxyLoss(getOxyLoss())
+ O.adjustFireLoss(getFireLoss())
+
+ //re-add implants to new mob
+ for(var/obj/item/weapon/implant/I in implants)
+ I.loc = O
+ I.implanted = O
+
+ //transfer mind and delete old mob
+ if(mind)
+ mind.transfer_to(O)
+ if (tr_flags & TR_DEFAULTMSG)
+ O << "You are now a monkey."
+ updateappearance(O)
+ . = O
+ if ( !(tr_flags & TR_KEEPSRC) ) //flag should be used if monkeyize() is called inside another proc of src so that one does not crash
+ del(src)
+ return
+
+
+
+////////////////////////// Humanize //////////////////////////////
+//Could probably be merged with monkeyize but other transformations got their own procs, too
+
+/mob/living/carbon/proc/humanize(tr_flags = (TR_KEEPITEMS | TR_KEEPVIRUS | TR_DEFAULTMSG), newname = null)
+ if (notransform)
+ return
+ //Handle items on mob
+
+ //first implants
+ var/list/implants = list()
+ if (tr_flags & TR_KEEPIMPLANTS)
+ for(var/obj/item/weapon/implant/W in src)
+ implants += W
+
+ //now the rest
+ if (tr_flags & TR_KEEPITEMS)
+ for(var/obj/item/W in (src.contents-implants))
+ u_equip(W)
+ if (client)
+ client.screen -= W
+ if (W)
+ W.loc = loc
+ W.dropped(src)
+ W.layer = initial(W.layer)
+
+ // for(var/obj/item/W in src)
+ // drop_from_inventory(W)
+
+ //Make mob invisible and spawn animation
+ regenerate_icons()
+ notransform = 1
+ canmove = 0
+ stunned = 1
+ icon = null
+ invisibility = 101
+ var/atom/movable/overlay/animation = new( loc )
+ animation.icon_state = "blank"
+ animation.icon = 'icons/mob/mob.dmi'
+ animation.master = src
+ flick("monkey2h", animation)
+ sleep(22)
+ var/mob/living/carbon/human/O = new( loc )
+ for(var/obj/item/C in O.loc)
+ O.equip_to_appropriate_slot(C)
+ del(animation)
+
+
+ O.gender = (deconstruct_block(getblock(dna.uni_identity, DNA_GENDER_BLOCK), 2)-1) ? FEMALE : MALE
+ O.dna = dna
+ dna = null
+ if (newname) //if there's a name as an argument, always take that one over the current name
+ O.real_name = newname
+ else
+ if ( !(cmptext ("monkey",copytext(O.dna.real_name,1,7)) ) )
+ O.real_name = O.dna.real_name
+ else
+ O.real_name = random_name(O.gender)
+ O.name = O.real_name
+
+ if (!(tr_flags & TR_KEEPSE))
+ O.dna.struc_enzymes = setblock(O.dna.struc_enzymes, RACEBLOCK, construct_block(1,BAD_MUTATION_DIFFICULTY))
+
+ if(suiciding)
+ O.suiciding = suiciding
+
+ O.loc = loc
+
+ //keep viruses?
+ if (tr_flags & TR_KEEPVIRUS)
+ O.viruses = viruses
+ viruses = list()
+ for(var/datum/disease/D in O.viruses)
+ D.affected_mob = O
+
+ //keep damage?
+ if (tr_flags & TR_KEEPDAMAGE)
+ O.setToxLoss(getToxLoss())
+ O.adjustBruteLoss(getBruteLoss())
+ O.setOxyLoss(getOxyLoss())
+ O.adjustFireLoss(getFireLoss())
+
+ //re-add implants to new mob
+ for(var/obj/item/weapon/implant/I in implants)
+ I.loc = O
+ I.implanted = O
+
+ if(mind)
+ mind.transfer_to(O)
+ O.a_intent = "help"
+ if (tr_flags & TR_DEFAULTMSG)
+ O << "You are now a human."
+ updateappearance(O)
+ . = O
+ if ( !(tr_flags & TR_KEEPSRC) ) //don't delete src yet if it's needed to finish calling proc
+ del(src)
+ return
+
+/mob/new_player/AIize()
+ spawning = 1
+ return ..()
+
+/mob/living/carbon/human/AIize()
+ if (notransform)
+ return
+ for(var/t in organs)
+ del(t)
+
+ return ..()
+
+/mob/living/carbon/AIize()
+ if (notransform)
+ return
+ for(var/obj/item/W in src)
+ drop_from_inventory(W)
+ regenerate_icons()
+ notransform = 1
+ canmove = 0
+ icon = null
+ invisibility = 101
+ return ..()
+
+/mob/proc/AIize()
+ if(client)
+ src << sound(null, repeat = 0, wait = 0, volume = 85, channel = 1) // stop the jams for AIs
+ var/mob/living/silicon/ai/O = new (loc,,,1)//No MMI but safety is in effect.
+ O.invisibility = 0
+ O.aiRestorePowerRoutine = 0
+
+ if(mind)
+ mind.transfer_to(O)
+ else
+ O.key = key
+
+ var/obj/loc_landmark
+ for(var/obj/effect/landmark/start/sloc in landmarks_list)
+ if (sloc.name != "AI")
+ continue
+ if (locate(/mob/living) in sloc.loc)
+ continue
+ loc_landmark = sloc
+ if (!loc_landmark)
+ for(var/obj/effect/landmark/tripai in landmarks_list)
+ if (tripai.name == "tripai")
+ if(locate(/mob/living) in tripai.loc)
+ continue
+ loc_landmark = tripai
+ if (!loc_landmark)
+ O << "Oh god sorry we can't find an unoccupied AI spawn location, so we're spawning you on top of someone."
+ for(var/obj/effect/landmark/start/sloc in landmarks_list)
+ if (sloc.name == "AI")
+ loc_landmark = sloc
+
+ O.loc = loc_landmark.loc
+ for (var/obj/item/device/radio/intercom/comm in O.loc)
+ comm.ai += O
+
+ O << "You are playing the station's AI. The AI cannot move, but can interact with many objects while viewing them (through cameras)."
+ O << "To look at other parts of the station, click on yourself to get a camera menu."
+ O << "While observing through a camera, you can use most (networked) devices which you can see, such as computers, APCs, intercoms, doors, etc."
+ O << "To use something, simply click on it."
+ O << {"Use say ":b to speak to your cyborgs through binary."}
+ if (!(ticker && ticker.mode && (O.mind in ticker.mode.malf_ai)))
+ O.show_laws()
+ O << "These laws may be changed by other players, or by you being the traitor."
+
+ O.verbs += /mob/living/silicon/ai/proc/ai_call_shuttle
+ O.verbs += /mob/living/silicon/ai/proc/show_laws_verb
+ O.verbs += /mob/living/silicon/ai/proc/ai_camera_track
+ O.verbs += /mob/living/silicon/ai/proc/ai_alerts
+ O.verbs += /mob/living/silicon/ai/proc/ai_camera_list
+ O.verbs += /mob/living/silicon/ai/proc/ai_statuschange
+ O.verbs += /mob/living/silicon/ai/proc/ai_roster
+
+ O.job = "AI"
+
+ O.rename_self("ai",1)
+ . = O
+ del(src)
+ return
+
+
+//human -> robot
+/mob/living/carbon/human/proc/Robotize(var/delete_items = 0)
+ if (notransform)
+ return
+ for(var/obj/item/W in src)
+ if(delete_items)
+ del(W)
+ else
+ drop_from_inventory(W)
+ regenerate_icons()
+ notransform = 1
+ canmove = 0
+ icon = null
+ invisibility = 101
+ for(var/t in organs)
+ del(t)
+
+ var/mob/living/silicon/robot/O = new /mob/living/silicon/robot( loc )
+
+ // cyborgs produced by Robotize get an automatic power cell
+ O.cell = new(O)
+ O.cell.maxcharge = 7500
+ O.cell.charge = 7500
+
+
+ O.gender = gender
+ O.invisibility = 0
+
+
+ if(mind) //TODO
+ mind.transfer_to(O)
+ if(mind.special_role)
+ O.mind.store_memory("In case you look at this after being borged, the objectives are only here until I find a way to make them not show up for you, as I can't simply delete them without screwing up round-end reporting. --NeoFite")
+ else
+ O.key = key
+
+ O.loc = loc
+ O.job = "Cyborg"
+
+ O.mmi = new /obj/item/device/mmi(O)
+ O.mmi.transfer_identity(src)//Does not transfer key/client.
+
+ . = O
+ del(src)
+
+//human -> alien
+/mob/living/carbon/human/proc/Alienize()
+ if (notransform)
+ return
+ for(var/obj/item/W in src)
+ drop_from_inventory(W)
+ regenerate_icons()
+ notransform = 1
+ canmove = 0
+ icon = null
+ invisibility = 101
+ for(var/t in organs)
+ del(t)
+
+ var/alien_caste = pick("Hunter","Sentinel","Drone")
+ var/mob/living/carbon/alien/humanoid/new_xeno
+ switch(alien_caste)
+ if("Hunter")
+ new_xeno = new /mob/living/carbon/alien/humanoid/hunter(loc)
+ if("Sentinel")
+ new_xeno = new /mob/living/carbon/alien/humanoid/sentinel(loc)
+ if("Drone")
+ new_xeno = new /mob/living/carbon/alien/humanoid/drone(loc)
+
+ new_xeno.a_intent = "harm"
+ new_xeno.key = key
+
+ new_xeno << "You are now an alien."
+ . = new_xeno
+ del(src)
+
+/mob/living/carbon/human/proc/slimeize(reproduce as num)
+ if (notransform)
+ return
+ for(var/obj/item/W in src)
+ drop_from_inventory(W)
+ regenerate_icons()
+ notransform = 1
+ canmove = 0
+ icon = null
+ invisibility = 101
+ for(var/t in organs)
+ del(t)
+
+ var/mob/living/carbon/slime/new_slime
+ if(reproduce)
+ var/number = pick(14;2,3,4) //reproduce (has a small chance of producing 3 or 4 offspring)
+ var/list/babies = list()
+ for(var/i=1,i<=number,i++)
+ var/mob/living/carbon/slime/M = new/mob/living/carbon/slime(loc)
+ M.nutrition = round(nutrition/number)
+ step_away(M,src)
+ babies += M
+ new_slime = pick(babies)
+ else
+ new_slime = new /mob/living/carbon/slime(loc)
+ new_slime.a_intent = "harm"
+ new_slime.key = key
+
+ new_slime << "You are now a slime. Skreee!"
+ . = new_slime
+ del(src)
+
+/mob/living/carbon/human/proc/Blobize()
+ if (notransform)
+ return
+ var/obj/effect/blob/core/new_blob = new /obj/effect/blob/core (loc)
+ new_blob.create_overmind(src.client , 1)
+ gib(src)
+
+
+
+/mob/living/carbon/human/proc/corgize()
+ if (notransform)
+ return
+ for(var/obj/item/W in src)
+ drop_from_inventory(W)
+ regenerate_icons()
+ notransform = 1
+ canmove = 0
+ icon = null
+ invisibility = 101
+ for(var/t in organs) //this really should not be necessary
+ del(t)
+
+ var/mob/living/simple_animal/corgi/new_corgi = new /mob/living/simple_animal/corgi (loc)
+ new_corgi.a_intent = "harm"
+ new_corgi.key = key
+
+ new_corgi << "You are now a Corgi. Yap Yap!"
+ . = new_corgi
+ del(src)
+
+/mob/living/carbon/human/Animalize()
+
+ var/list/mobtypes = typesof(/mob/living/simple_animal)
+ var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") in mobtypes
+
+ if(!safe_animal(mobpath))
+ usr << "\red Sorry but this mob type is currently unavailable."
+ return
+
+ if(notransform)
+ return
+ for(var/obj/item/W in src)
+ drop_from_inventory(W)
+
+ regenerate_icons()
+ notransform = 1
+ canmove = 0
+ icon = null
+ invisibility = 101
+
+ for(var/t in organs)
+ del(t)
+
+ var/mob/new_mob = new mobpath(src.loc)
+
+ new_mob.key = key
+ new_mob.a_intent = "harm"
+
+
+ new_mob << "You suddenly feel more... animalistic."
+ . = new_mob
+ del(src)
+
+/mob/proc/Animalize()
+
+ var/list/mobtypes = typesof(/mob/living/simple_animal)
+ var/mobpath = input("Which type of mob should [src] turn into?", "Choose a type") in mobtypes
+
+ if(!safe_animal(mobpath))
+ usr << "\red Sorry but this mob type is currently unavailable."
+ return
+
+ var/mob/new_mob = new mobpath(src.loc)
+
+ new_mob.key = key
+ new_mob.a_intent = "harm"
+ new_mob << "You feel more... animalistic"
+
+ . = new_mob
+ del(src)
+
+/* Certain mob types have problems and should not be allowed to be controlled by players.
+ *
+ * This proc is here to force coders to manually place their mob in this list, hopefully tested.
+ * This also gives a place to explain -why- players shouldnt be turn into certain mobs and hopefully someone can fix them.
+ */
+/mob/proc/safe_animal(var/MP)
+
+//Bad mobs! - Remember to add a comment explaining what's wrong with the mob
+ if(!MP)
+ return 0 //Sanity, this should never happen.
+
+// if(ispath(MP, /mob/living/simple_animal/space_worm)) //Goodbye Space Worms 2014
+// return 0 //Unfinished. Very buggy, they seem to just spawn additional space worms everywhere and eating your own tail results in new worms spawning.
+
+ if(ispath(MP, /mob/living/simple_animal/construct/behemoth))
+ return 0 //I think this may have been an unfinished WiP or something. These constructs should really have their own class simple_animal/construct/subtype
+
+ if(ispath(MP, /mob/living/simple_animal/construct/armoured))
+ return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype
+
+ if(ispath(MP, /mob/living/simple_animal/construct/wraith))
+ return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype
+
+ if(ispath(MP, /mob/living/simple_animal/construct/builder))
+ return 0 //Verbs do not appear for players. These constructs should really have their own class simple_animal/construct/subtype
+
+//Good mobs!
+ if(ispath(MP, /mob/living/simple_animal/cat))
+ return 1
+ if(ispath(MP, /mob/living/simple_animal/corgi))
+ return 1
+ if(ispath(MP, /mob/living/simple_animal/crab))
+ return 1
+ if(ispath(MP, /mob/living/simple_animal/hostile/carp))
+ return 1
+ if(ispath(MP, /mob/living/simple_animal/hostile/mushroom))
+ return 1
+ if(ispath(MP, /mob/living/simple_animal/shade))
+ return 1
+ if(ispath(MP, /mob/living/simple_animal/tomato))
+ return 1
+ if(ispath(MP, /mob/living/simple_animal/mouse))
+ return 1 //It is impossible to pull up the player panel for mice (Fixed! - Nodrak)
+ if(ispath(MP, /mob/living/simple_animal/hostile/bear))
+ return 1 //Bears will auto-attack mobs, even if they're player controlled (Fixed! - Nodrak)
+ if(ispath(MP, /mob/living/simple_animal/parrot))
+ return 1 //Parrots are no longer unfinished! -Nodrak
+
+ //Not in here? Must be untested!
+ return 0
+
+
+
diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm
index c3a309529c0..fabce6b4abd 100644
--- a/code/modules/paperwork/photography.dm
+++ b/code/modules/paperwork/photography.dm
@@ -1,358 +1,358 @@
-/* Photography!
- * Contains:
- * Camera
- * Camera Film
- * Photos
- * Photo Albums
- */
-
-/*
- * Film
- */
-/obj/item/device/camera_film
- name = "film cartridge"
- icon = 'icons/obj/items.dmi'
- desc = "A camera film cartridge. Insert it into a camera to reload it."
- icon_state = "film"
- item_state = "electropack"
- w_class = 1.0
-
-
-/*
- * Photo
- */
-/obj/item/weapon/photo
- name = "photo"
- icon = 'icons/obj/items.dmi'
- icon_state = "photo"
- item_state = "paper"
- w_class = 1.0
- var/icon/img //Big photo image
- var/scribble //Scribble on the back.
- var/blueprints = 0 //Does it include the blueprints?
-
-
-/obj/item/weapon/photo/attack_self(mob/user)
- examine()
-
-
-/obj/item/weapon/photo/attackby(obj/item/weapon/P, mob/user)
- if(istype(P, /obj/item/weapon/pen) || istype(P, /obj/item/toy/crayon))
- var/txt = sanitize(input(user, "What would you like to write on the back?", "Photo Writing", null) as text)
- txt = copytext(txt, 1, 128)
- if(loc == user && user.stat == 0)
- scribble = txt
- ..()
-
-
-/obj/item/weapon/photo/examine()
- set src in oview(1)
- if(is_blind(usr)) return
-
- if(in_range(usr, src))
- show(usr)
- usr << desc
- else
- usr << "It is too far away."
-
-
-/obj/item/weapon/photo/proc/show(mob/user)
- user << browse_rsc(img, "tmp_photo.png")
- user << browse("[name] " \
- + "" \
- + "
Written on the back:
[scribble]" : ]"\
- + "", "window=book;size=200x[scribble ? 400 : 200]")
- onclose(user, "[name]")
-
-
-/obj/item/weapon/photo/verb/rename()
- set name = "Rename photo"
- set category = "Object"
- set src in usr
-
- var/n_name = copytext(sanitize(input(usr, "What would you like to label the photo?", "Photo Labelling", null) as text), 1, MAX_NAME_LEN)
- //loc.loc check is for making possible renaming photos in clipboards
- if((loc == usr || loc.loc && loc.loc == usr) && usr.stat == 0)
- name = "photo[(n_name ? text("- '[n_name]'") : null)]"
- add_fingerprint(usr)
-
-
-/*
- * Photo album
- */
-/obj/item/weapon/storage/photo_album
- name = "photo album"
- icon = 'icons/obj/items.dmi'
- icon_state = "album"
- item_state = "briefcase"
- can_hold = list("/obj/item/weapon/photo",)
-
-
-/*
- * Camera
- */
-/obj/item/device/camera
- name = "camera"
- icon = 'icons/obj/items.dmi'
- desc = "A polaroid camera. 10 photos left."
- icon_state = "camera"
- item_state = "electropack"
- w_class = 2.0
- flags = CONDUCT
- slot_flags = SLOT_BELT
- m_amt = 2000
- var/pictures_max = 10
- var/pictures_left = 10
- var/on = 1
- var/blueprints = 0 //are blueprints visible in the current photo being created?
- var/list/aipictures = list() //Allows for storage of pictures taken by AI, in a similar manner the datacore stores info
-
-
-/obj/item/device/camera/ai_camera //camera AI can take pictures with
- name = "AI photo camera"
- var/in_camera_mode = 0
-
- verb/picture()
- set category ="AI Commands"
- set name = "Take Image"
- set src in usr
-
- toggle_camera_mode()
-
- verb/viewpicture()
- set category ="AI Commands"
- set name = "View Images"
- set src in usr
-
- viewpictures()
-
-
-/obj/item/device/camera/attack(mob/living/carbon/human/M, mob/user)
- return
-
-
-/obj/item/device/camera/attackby(obj/item/I, mob/user)
- if(istype(I, /obj/item/device/camera_film))
- if(pictures_left)
- user << "[src] still has some film in it!"
- return
- user << "You insert [I] into [src]."
- user.drop_item()
- del(I)
- pictures_left = pictures_max
- return
- ..()
-
-
-/obj/item/device/camera/proc/camera_get_icon(turf/the_turf)
- //Bigger icon base to capture those icons that were shifted to the next tile
- //i.e. pretty much all wall-mounted machinery
- var/icon/res = icon('icons/effects/96x96.dmi', "")
-
- var/icon/turficon = build_composite_icon(the_turf)
- res.Blend(turficon, ICON_OVERLAY, 33, 33)
-
- var/atoms[] = list()
- for(var/atom/A in the_turf)
- if(A.invisibility) continue
- atoms.Add(A)
-
- //Sorting icons based on levels
- var/gap = atoms.len
- var/swapped = 1
- while (gap > 1 || swapped)
- swapped = 0
- if(gap > 1)
- gap = round(gap / 1.247330950103979)
- if(gap < 1)
- gap = 1
- for(var/i = 1; gap + i <= atoms.len; i++)
- var/atom/l = atoms[i] //Fucking hate
- var/atom/r = atoms[gap+i] //how lists work here
- if(l.layer > r.layer) //no "atoms[i].layer" for me
- atoms.Swap(i, gap + i)
- swapped = 1
-
- for(var/i; i <= atoms.len; i++)
- var/atom/A = atoms[i]
- if(A)
- var/icon/img = getFlatIcon(A, A.dir)//build_composite_icon(A)
- if(istype(img, /icon))
- res.Blend(new/icon(img, "", A.dir), ICON_OVERLAY, 33 + A.pixel_x, 33 + A.pixel_y)
-
- if(istype(A, /obj/item/blueprints))
- blueprints = 1
-
- return res
-
-
-/obj/item/device/camera/proc/camera_get_mobs(turf/the_turf)
- var/mob_detail
- for(var/mob/living/carbon/A in the_turf)
- if(A.invisibility) continue
- var/holding = null
- if(A.l_hand || A.r_hand)
- if(A.l_hand) holding = "They are holding \a [A.l_hand]"
- if(A.r_hand)
- if(holding)
- holding += " and \a [A.r_hand]"
- else
- holding = "They are holding \a [A.r_hand]"
-
- if(!mob_detail)
- mob_detail = "You can see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]. "
- else
- mob_detail += "You can also see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]."
- return mob_detail
-
-
-/obj/item/device/camera/proc/captureimage(atom/target, mob/user, flag) //Proc for both regular and AI-based camera to take the image
- var/x_c = target.x - 1
- var/y_c = target.y + 1
- var/z_c = target.z
-
- var/icon/temp = icon('icons/effects/96x96.dmi',"")
- temp.Blend("#000", ICON_OVERLAY)
- var/mobs = ""
- var/viewer = user
- var/list/seen
- if(!istype(user,/mob/living/silicon/ai)) //crappy check, but without it AI photos would be subject to line of sight from the AI Eye object. Made the best of it by moving the sec camera check inside
- if(user.client) //To make shooting through security cameras possible
- viewer = user.client.eye
- seen = hear(world.view, viewer)
- else
- seen = hear(world.view, target)
- for(var/i = 1; i <= 3; i++)
- for(var/j = 1; j <= 3; j++)
- var/turf/T = locate(x_c, y_c, z_c)
- if(T in seen)
- if(istype(user,/mob/living/silicon/ai))
- if(0 == cameranet.checkTurfVis(T)) //Checks to see if this turf is visible to the AI's cameras
- x_c++ //because continue would skip the x_c++ further down, and it is rather important to this proc to work right
- continue
- temp.Blend(camera_get_icon(T), ICON_OVERLAY, 32 * (j-1-1), 32 - 32 * (i-1))
- mobs += camera_get_mobs(T)
- x_c++
- y_c--
- x_c -= 3
- if(!istype(usr,/mob/living/silicon/ai))
- printpicture(user, temp, mobs, flag)
- else
- aipicture(user, temp, mobs, blueprints)
-
-
-
-/obj/item/device/camera/proc/printpicture(mob/user, icon/temp, mobs, flag) //Normal camera proc for creating photos
- var/obj/item/weapon/photo/P = new/obj/item/weapon/photo()
- user.put_in_hands(P)
- var/icon/small_img = icon(temp)
- var/icon/ic = icon('icons/obj/items.dmi',"photo")
- small_img.Scale(8, 8)
- ic.Blend(small_img,ICON_OVERLAY, 10, 13)
- P.icon = ic
- P.img = temp
- P.desc = mobs
- P.pixel_x = rand(-10, 10)
- P.pixel_y = rand(-10, 10)
-
- if(blueprints)
- P.blueprints = 1
- blueprints = 0
-
-
-/obj/item/device/camera/proc/aipicture(mob/user, icon/temp, mobs) //instead of printing a picture like a regular camera would, we do this instead for the AI
-
- var/icon/small_img = icon(temp)
- var/icon/ic = icon('icons/obj/items.dmi',"photo")
- small_img.Scale(8, 8)
- ic.Blend(small_img,ICON_OVERLAY, 10, 13)
- var/icon = ic
- var/img = temp
- var/desc = mobs
- var/pixel_x = rand(-10, 10)
- var/pixel_y = rand(-10, 10)
-
- var/injectblueprints = 1
- if(blueprints)
- injectblueprints = 1
- blueprints = 0
-
- injectaialbum(icon, img, desc, pixel_x, pixel_y, injectblueprints)
-
-
-/datum/picture
- var/name = "image"
- var/list/fields = list()
-
-
-/obj/item/device/camera/proc/injectaialbum(var/icon, var/img, var/desc, var/pixel_x, var/pixel_y, var/blueprintsinject) //stores image information to a list similar to that of the datacore
- var/numberer = 1
- for(var/datum/picture in src.aipictures)
- numberer++
- var/datum/picture/P = new()
- P.fields["name"] = "Image [numberer]"
- P.fields["icon"] = icon
- P.fields["img"] = img
- P.fields["desc"] = desc
- P.fields["pixel_x"] = pixel_x
- P.fields["pixel_y"] = pixel_y
- P.fields["blueprints"] = blueprintsinject
-
- aipictures += P
- usr << "Image recorded" //feedback to the AI player that the picture was taken
-
-
-/obj/item/device/camera/ai_camera/proc/viewpictures() //AI proc for viewing pictures they have taken
- var/list/nametemp = list()
- var/find
- var/datum/picture/selection
- if(src.aipictures.len == 0)
- usr << "No images saved"
- return
- for(var/datum/picture/t in src.aipictures)
- nametemp += t.fields["name"]
- find = input("Select image (numbered in order taken)") in nametemp
- var/obj/item/weapon/photo/P = new/obj/item/weapon/photo()
- for(var/datum/picture/q in src.aipictures)
- if(q.fields["name"] == find)
- selection = q
- break // just in case some AI decides to take 10 thousand pictures in a round
- P.icon = selection.fields["icon"]
- P.img = selection.fields["img"]
- P.desc = selection.fields["desc"]
- P.pixel_x = selection.fields["pixel_x"]
- P.pixel_y = selection.fields["pixel_y"]
-
- P.show(usr)
- usr << P.desc
- del P //so 10 thousdand pictures items are not left in memory should an AI take them and then view them all.
-
-/obj/item/device/camera/afterattack(atom/target, mob/user, flag)
- if(!on || !pictures_left || ismob(target.loc)) return
- captureimage(target, user, flag)
-
- playsound(loc, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 75, 1, -3)
-
- pictures_left--
- desc = "A polaroid camera. It has [pictures_left] photos left."
- user << "[pictures_left] photos left."
- icon_state = "camera_off"
- on = 0
- spawn(64)
- icon_state = "camera"
- on = 1
-
-/obj/item/device/camera/ai_camera/proc/toggle_camera_mode()
- if(in_camera_mode)
- camera_mode_off()
- else
- camera_mode_on()
-
-/obj/item/device/camera/ai_camera/proc/camera_mode_off()
- src.in_camera_mode = 0
- usr << "Camera Mode deactivated"
-
-/obj/item/device/camera/ai_camera/proc/camera_mode_on()
- src.in_camera_mode = 1
+/* Photography!
+ * Contains:
+ * Camera
+ * Camera Film
+ * Photos
+ * Photo Albums
+ */
+
+/*
+ * Film
+ */
+/obj/item/device/camera_film
+ name = "film cartridge"
+ icon = 'icons/obj/items.dmi'
+ desc = "A camera film cartridge. Insert it into a camera to reload it."
+ icon_state = "film"
+ item_state = "electropack"
+ w_class = 1.0
+
+
+/*
+ * Photo
+ */
+/obj/item/weapon/photo
+ name = "photo"
+ icon = 'icons/obj/items.dmi'
+ icon_state = "photo"
+ item_state = "paper"
+ w_class = 1.0
+ var/icon/img //Big photo image
+ var/scribble //Scribble on the back.
+ var/blueprints = 0 //Does it include the blueprints?
+
+
+/obj/item/weapon/photo/attack_self(mob/user)
+ examine()
+
+
+/obj/item/weapon/photo/attackby(obj/item/weapon/P, mob/user)
+ if(istype(P, /obj/item/weapon/pen) || istype(P, /obj/item/toy/crayon))
+ var/txt = sanitize(input(user, "What would you like to write on the back?", "Photo Writing", null) as text)
+ txt = copytext(txt, 1, 128)
+ if(loc == user && user.stat == 0)
+ scribble = txt
+ ..()
+
+
+/obj/item/weapon/photo/examine()
+ set src in oview(1)
+ if(is_blind(usr)) return
+
+ if(in_range(usr, src))
+ show(usr)
+ usr << desc
+ else
+ usr << "It is too far away."
+
+
+/obj/item/weapon/photo/proc/show(mob/user)
+ user << browse_rsc(img, "tmp_photo.png")
+ user << browse("[name] " \
+ + "" \
+ + "
Written on the back:
[scribble]" : ]"\
+ + "", "window=book;size=200x[scribble ? 400 : 200]")
+ onclose(user, "[name]")
+
+
+/obj/item/weapon/photo/verb/rename()
+ set name = "Rename photo"
+ set category = "Object"
+ set src in usr
+
+ var/n_name = copytext(sanitize(input(usr, "What would you like to label the photo?", "Photo Labelling", null) as text), 1, MAX_NAME_LEN)
+ //loc.loc check is for making possible renaming photos in clipboards
+ if((loc == usr || loc.loc && loc.loc == usr) && usr.stat == 0)
+ name = "photo[(n_name ? text("- '[n_name]'") : null)]"
+ add_fingerprint(usr)
+
+
+/*
+ * Photo album
+ */
+/obj/item/weapon/storage/photo_album
+ name = "photo album"
+ icon = 'icons/obj/items.dmi'
+ icon_state = "album"
+ item_state = "briefcase"
+ can_hold = list("/obj/item/weapon/photo",)
+
+
+/*
+ * Camera
+ */
+/obj/item/device/camera
+ name = "camera"
+ icon = 'icons/obj/items.dmi'
+ desc = "A polaroid camera. 10 photos left."
+ icon_state = "camera"
+ item_state = "electropack"
+ w_class = 2.0
+ flags = CONDUCT
+ slot_flags = SLOT_BELT
+ m_amt = 2000
+ var/pictures_max = 10
+ var/pictures_left = 10
+ var/on = 1
+ var/blueprints = 0 //are blueprints visible in the current photo being created?
+ var/list/aipictures = list() //Allows for storage of pictures taken by AI, in a similar manner the datacore stores info
+
+
+/obj/item/device/camera/ai_camera //camera AI can take pictures with
+ name = "AI photo camera"
+ var/in_camera_mode = 0
+
+ verb/picture()
+ set category ="AI Commands"
+ set name = "Take Image"
+ set src in usr
+
+ toggle_camera_mode()
+
+ verb/viewpicture()
+ set category ="AI Commands"
+ set name = "View Images"
+ set src in usr
+
+ viewpictures()
+
+
+/obj/item/device/camera/attack(mob/living/carbon/human/M, mob/user)
+ return
+
+
+/obj/item/device/camera/attackby(obj/item/I, mob/user)
+ if(istype(I, /obj/item/device/camera_film))
+ if(pictures_left)
+ user << "[src] still has some film in it!"
+ return
+ user << "You insert [I] into [src]."
+ user.drop_item()
+ del(I)
+ pictures_left = pictures_max
+ return
+ ..()
+
+
+/obj/item/device/camera/proc/camera_get_icon(turf/the_turf)
+ //Bigger icon base to capture those icons that were shifted to the next tile
+ //i.e. pretty much all wall-mounted machinery
+ var/icon/res = icon('icons/effects/96x96.dmi', "")
+
+ var/icon/turficon = build_composite_icon(the_turf)
+ res.Blend(turficon, ICON_OVERLAY, 33, 33)
+
+ var/atoms[] = list()
+ for(var/atom/A in the_turf)
+ if(A.invisibility) continue
+ atoms.Add(A)
+
+ //Sorting icons based on levels
+ var/gap = atoms.len
+ var/swapped = 1
+ while (gap > 1 || swapped)
+ swapped = 0
+ if(gap > 1)
+ gap = round(gap / 1.247330950103979)
+ if(gap < 1)
+ gap = 1
+ for(var/i = 1; gap + i <= atoms.len; i++)
+ var/atom/l = atoms[i] //Fucking hate
+ var/atom/r = atoms[gap+i] //how lists work here
+ if(l.layer > r.layer) //no "atoms[i].layer" for me
+ atoms.Swap(i, gap + i)
+ swapped = 1
+
+ for(var/i; i <= atoms.len; i++)
+ var/atom/A = atoms[i]
+ if(A)
+ var/icon/img = getFlatIcon(A, A.dir)//build_composite_icon(A)
+ if(istype(img, /icon))
+ res.Blend(new/icon(img, "", A.dir), ICON_OVERLAY, 33 + A.pixel_x, 33 + A.pixel_y)
+
+ if(istype(A, /obj/item/blueprints))
+ blueprints = 1
+
+ return res
+
+
+/obj/item/device/camera/proc/camera_get_mobs(turf/the_turf)
+ var/mob_detail
+ for(var/mob/living/carbon/A in the_turf)
+ if(A.invisibility) continue
+ var/holding = null
+ if(A.l_hand || A.r_hand)
+ if(A.l_hand) holding = "They are holding \a [A.l_hand]"
+ if(A.r_hand)
+ if(holding)
+ holding += " and \a [A.r_hand]"
+ else
+ holding = "They are holding \a [A.r_hand]"
+
+ if(!mob_detail)
+ mob_detail = "You can see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]. "
+ else
+ mob_detail += "You can also see [A] on the photo[A:health < 75 ? " - [A] looks hurt":""].[holding ? " [holding]":"."]."
+ return mob_detail
+
+
+/obj/item/device/camera/proc/captureimage(atom/target, mob/user, flag) //Proc for both regular and AI-based camera to take the image
+ var/x_c = target.x - 1
+ var/y_c = target.y + 1
+ var/z_c = target.z
+
+ var/icon/temp = icon('icons/effects/96x96.dmi',"")
+ temp.Blend("#000", ICON_OVERLAY)
+ var/mobs = ""
+ var/viewer = user
+ var/list/seen
+ if(!istype(user,/mob/living/silicon/ai)) //crappy check, but without it AI photos would be subject to line of sight from the AI Eye object. Made the best of it by moving the sec camera check inside
+ if(user.client) //To make shooting through security cameras possible
+ viewer = user.client.eye
+ seen = hear(world.view, viewer)
+ else
+ seen = hear(world.view, target)
+ for(var/i = 1; i <= 3; i++)
+ for(var/j = 1; j <= 3; j++)
+ var/turf/T = locate(x_c, y_c, z_c)
+ if(T in seen)
+ if(istype(user,/mob/living/silicon/ai))
+ if(0 == cameranet.checkTurfVis(T)) //Checks to see if this turf is visible to the AI's cameras
+ x_c++ //because continue would skip the x_c++ further down, and it is rather important to this proc to work right
+ continue
+ temp.Blend(camera_get_icon(T), ICON_OVERLAY, 32 * (j-1-1), 32 - 32 * (i-1))
+ mobs += camera_get_mobs(T)
+ x_c++
+ y_c--
+ x_c -= 3
+ if(!istype(usr,/mob/living/silicon/ai))
+ printpicture(user, temp, mobs, flag)
+ else
+ aipicture(user, temp, mobs, blueprints)
+
+
+
+/obj/item/device/camera/proc/printpicture(mob/user, icon/temp, mobs, flag) //Normal camera proc for creating photos
+ var/obj/item/weapon/photo/P = new/obj/item/weapon/photo()
+ user.put_in_hands(P)
+ var/icon/small_img = icon(temp)
+ var/icon/ic = icon('icons/obj/items.dmi',"photo")
+ small_img.Scale(8, 8)
+ ic.Blend(small_img,ICON_OVERLAY, 10, 13)
+ P.icon = ic
+ P.img = temp
+ P.desc = mobs
+ P.pixel_x = rand(-10, 10)
+ P.pixel_y = rand(-10, 10)
+
+ if(blueprints)
+ P.blueprints = 1
+ blueprints = 0
+
+
+/obj/item/device/camera/proc/aipicture(mob/user, icon/temp, mobs) //instead of printing a picture like a regular camera would, we do this instead for the AI
+
+ var/icon/small_img = icon(temp)
+ var/icon/ic = icon('icons/obj/items.dmi',"photo")
+ small_img.Scale(8, 8)
+ ic.Blend(small_img,ICON_OVERLAY, 10, 13)
+ var/icon = ic
+ var/img = temp
+ var/desc = mobs
+ var/pixel_x = rand(-10, 10)
+ var/pixel_y = rand(-10, 10)
+
+ var/injectblueprints = 1
+ if(blueprints)
+ injectblueprints = 1
+ blueprints = 0
+
+ injectaialbum(icon, img, desc, pixel_x, pixel_y, injectblueprints)
+
+
+/datum/picture
+ var/name = "image"
+ var/list/fields = list()
+
+
+/obj/item/device/camera/proc/injectaialbum(var/icon, var/img, var/desc, var/pixel_x, var/pixel_y, var/blueprintsinject) //stores image information to a list similar to that of the datacore
+ var/numberer = 1
+ for(var/datum/picture in src.aipictures)
+ numberer++
+ var/datum/picture/P = new()
+ P.fields["name"] = "Image [numberer]"
+ P.fields["icon"] = icon
+ P.fields["img"] = img
+ P.fields["desc"] = desc
+ P.fields["pixel_x"] = pixel_x
+ P.fields["pixel_y"] = pixel_y
+ P.fields["blueprints"] = blueprintsinject
+
+ aipictures += P
+ usr << "Image recorded" //feedback to the AI player that the picture was taken
+
+
+/obj/item/device/camera/ai_camera/proc/viewpictures() //AI proc for viewing pictures they have taken
+ var/list/nametemp = list()
+ var/find
+ var/datum/picture/selection
+ if(src.aipictures.len == 0)
+ usr << "No images saved"
+ return
+ for(var/datum/picture/t in src.aipictures)
+ nametemp += t.fields["name"]
+ find = input("Select image (numbered in order taken)") in nametemp
+ var/obj/item/weapon/photo/P = new/obj/item/weapon/photo()
+ for(var/datum/picture/q in src.aipictures)
+ if(q.fields["name"] == find)
+ selection = q
+ break // just in case some AI decides to take 10 thousand pictures in a round
+ P.icon = selection.fields["icon"]
+ P.img = selection.fields["img"]
+ P.desc = selection.fields["desc"]
+ P.pixel_x = selection.fields["pixel_x"]
+ P.pixel_y = selection.fields["pixel_y"]
+
+ P.show(usr)
+ usr << P.desc
+ del P //so 10 thousdand pictures items are not left in memory should an AI take them and then view them all.
+
+/obj/item/device/camera/afterattack(atom/target, mob/user, flag)
+ if(!on || !pictures_left || ismob(target.loc)) return
+ captureimage(target, user, flag)
+
+ playsound(loc, pick('sound/items/polaroid1.ogg', 'sound/items/polaroid2.ogg'), 75, 1, -3)
+
+ pictures_left--
+ desc = "A polaroid camera. It has [pictures_left] photos left."
+ user << "[pictures_left] photos left."
+ icon_state = "camera_off"
+ on = 0
+ spawn(64)
+ icon_state = "camera"
+ on = 1
+
+/obj/item/device/camera/ai_camera/proc/toggle_camera_mode()
+ if(in_camera_mode)
+ camera_mode_off()
+ else
+ camera_mode_on()
+
+/obj/item/device/camera/ai_camera/proc/camera_mode_off()
+ src.in_camera_mode = 0
+ usr << "Camera Mode deactivated"
+
+/obj/item/device/camera/ai_camera/proc/camera_mode_on()
+ src.in_camera_mode = 1
usr << "Camera Mode activated"
\ No newline at end of file
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 95ea12256a3..f3aa222665f 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -1,1121 +1,1121 @@
-#define APC_WIRE_IDSCAN 1
-#define APC_WIRE_MAIN_POWER1 2
-#define APC_WIRE_MAIN_POWER2 3
-#define APC_WIRE_AI_CONTROL 4
-
-#define APC_UPDATE_ICON_COOLDOWN 200 // 20 seconds
-
-// the Area Power Controller (APC), formerly Power Distribution Unit (PDU)
-// one per area, needs wire conection to power network
-
-// controls power to devices in that area
-// may be opened to change power cell
-// three different channels (lighting/equipment/environ) - may each be set to on, off, or auto
-
-
-//NOTE: STUFF STOLEN FROM AIRLOCK.DM thx
-
-
-/obj/machinery/power/apc
- name = "area power controller"
- desc = "A control terminal for the area electrical systems."
-
- icon_state = "apc0"
- anchored = 1
- use_power = 0
- req_access = list(access_engine_equip)
- var/area/area
- var/areastring = null
- var/obj/item/weapon/cell/cell
- var/start_charge = 90 // initial cell charge %
- var/cell_type = 2500 // 0=no cell, 1=regular, 2=high-cap (x5) <- old, now it's just 0=no cell, otherwise dictate cellcapacity by changing this value. 1 used to be 1000, 2 was 2500
- var/opened = 0 //0=closed, 1=opened, 2=cover removed
- var/shorted = 0
- var/lighting = 3
- var/equipment = 3
- var/environ = 3
- var/operating = 1
- var/charging = 0
- var/chargemode = 1
- var/chargecount = 0
- var/locked = 1
- var/coverlocked = 1
- var/aidisabled = 0
- var/tdir = null
- var/obj/machinery/power/terminal/terminal = null
- var/lastused_light = 0
- var/lastused_equip = 0
- var/lastused_environ = 0
- var/lastused_total = 0
- var/main_status = 0
- var/wiresexposed = 0
- powernet = 0 // set so that APCs aren't found as powernet nodes //Hackish, Horrible, was like this before I changed it :(
- var/malfhack = 0 //New var for my changes to AI malf. --NeoFite
- var/mob/living/silicon/ai/malfai = null //See above --NeoFite
-// luminosity = 1
- var/has_electronics = 0 // 0 - none, 1 - plugged in, 2 - secured by screwdriver
- var/overload = 1 //used for the Blackout malf module
- var/beenhit = 0 // used for counting how many times it has been hit, used for Aliens at the moment
- var/mob/living/silicon/ai/occupant = null
- var/longtermpower = 10
- var/updating_icon = 0
- var/datum/wires/apc/wires = null
- //var/debug = 0
- var/auto_name = 0
-
-/obj/machinery/power/apc/updateDialog()
- if (stat & (BROKEN|MAINT))
- return
- ..()
-
-/obj/machinery/power/apc/connect_to_network()
- //Override because the APC does not directly connect to the network; it goes through a terminal.
- //The terminal is what the power computer looks for anyway.
- if(!terminal)
- make_terminal()
- if(terminal)
- terminal.connect_to_network()
-
-/obj/machinery/power/apc/New(turf/loc, var/ndir, var/building=0)
- ..()
- wires = new(src)
- // offset 24 pixels in direction of dir
- // this allows the APC to be embedded in a wall, yet still inside an area
- if (building)
- dir = ndir
- src.tdir = dir // to fix Vars bug
- dir = SOUTH
-
- if(auto_name)
- name = "[get_area(src)] APC"
-
- pixel_x = (src.tdir & 3)? 0 : (src.tdir == 4 ? 24 : -24)
- pixel_y = (src.tdir & 3)? (src.tdir ==1 ? 24 : -24) : 0
- if (building==0)
- init()
- else
- area = src.loc.loc:master
- opened = 1
- operating = 0
- name = "[area.name] APC"
- stat |= MAINT
- src.update_icon()
- spawn(5)
- src.update()
-
-
-
-/obj/machinery/power/apc/proc/make_terminal()
- // create a terminal object at the same position as original turf loc
- // wires will attach to this
- terminal = new/obj/machinery/power/terminal(src.loc)
- terminal.dir = tdir
- terminal.master = src
-
-/obj/machinery/power/apc/proc/init()
- has_electronics = 2 //installed and secured
- // is starting with a power cell installed, create it and set its charge level
- if(cell_type)
- src.cell = new/obj/item/weapon/cell(src)
- cell.maxcharge = cell_type // cell_type is maximum charge (old default was 1000 or 2500 (values one and two respectively)
- cell.charge = start_charge * cell.maxcharge / 100.0 // (convert percentage to actual value)
-
- var/area/A = src.loc.loc
-
- //if area isn't specified use current
- if(isarea(A) && src.areastring == null)
- src.area = A
- else
- src.area = get_area_name(areastring)
- update_icon()
-
- make_terminal()
-
- spawn(5)
- src.update()
-
-/obj/machinery/power/apc/examine()
- set src in oview(1)
-
- if(usr /*&& !usr.stat*/)
- ..()
- if(stat & BROKEN)
- usr << "Looks broken."
- return
- if(opened)
- if(has_electronics && terminal)
- usr << "The cover is [opened==2?"removed":"open"] and the power cell is [ cell ? "installed" : "missing"]."
- else if (!has_electronics && terminal)
- usr << "There are some wires but no any electronics."
- else if (has_electronics && !terminal)
- usr << "Electronics installed but not wired."
- else /* if (!has_electronics && !terminal) */
- usr << "There is no electronics nor connected wires."
-
- else
- if (stat & MAINT)
- usr << "The cover is closed. Something wrong with it: it doesn't work."
- else if (malfhack)
- usr << "The cover is broken. It may be hard to force it open."
- else
- usr << "The cover is closed."
-
-
-// update the APC icon to show the three base states
-// also add overlays for indicator lights
-/obj/machinery/power/apc/update_icon()
-
- overlays.Cut()
- if(opened)
- var/basestate = "apc[ cell ? "2" : "1" ]" // if opened, show cell if it's inserted
- if (opened==1)
- if (stat & (MAINT|BROKEN))
- icon_state = "apcmaint" //disassembled APC cannot hold cell
- else
- icon_state = basestate
- else if (opened == 2)
- if ((stat & BROKEN) || malfhack )
- icon_state = "[basestate]-b-nocover"
- else /* if (emagged)*/
- icon_state = "[basestate]-nocover"
- else if (stat & BROKEN)
- icon_state = "apc-b"
- else if(emagged || malfai)
- icon_state = "apcemag"
- else if(wiresexposed)
- icon_state = "apcewires"
- else
- icon_state = "apc0"
- // if closed, update overlays for channel status
- if(!(stat & (BROKEN|MAINT)))
- overlays.Add("apcox-[locked]","apco3-[charging]") // 0=blue 1=red // 0=red, 1=yellow/black 2=green
- if(operating)
- overlays.Add("apco0-[equipment]","apco1-[lighting]","apco2-[environ]") // 0=red, 1=green, 2=blue
-
-// Used in process so it doesn't update the icon too much
-/obj/machinery/power/apc/proc/queue_icon_update()
-
- if(!updating_icon)
- updating_icon = 1
- // Start the update
- spawn(APC_UPDATE_ICON_COOLDOWN)
- update_icon()
- updating_icon = 0
-
-//attack with an item - open/close cover, insert cell, or (un)lock interface
-
-/obj/machinery/power/apc/attackby(obj/item/W, mob/user)
-
- if (istype(user, /mob/living/silicon) && get_dist(src,user)>1)
- return src.attack_hand(user)
- if (istype(W, /obj/item/weapon/crowbar) && opened)
- if (has_electronics==1)
- if (terminal)
- user << "\red Disconnect wires first."
- return
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
- user << "You are trying to remove the power control board..." //lpeters - fixed grammar issues
- if(do_after(user, 50))
- has_electronics = 0
- if ((stat & BROKEN) || malfhack)
- user.visible_message(\
- "\red [user.name] has broken the power control board inside [src.name]!",\
- "You broke the charred power control board and remove the remains.",
- "You hear a crack!")
- //ticker.mode:apcs-- //XSI said no and I agreed. -rastaf0
- else
- user.visible_message(\
- "\red [user.name] has removed the power control board from [src.name]!",\
- "You remove the power control board.")
- new /obj/item/weapon/module/power_control(loc)
- else if (opened!=2) //cover isn't removed
- opened = 0
- update_icon()
- else if (istype(W, /obj/item/weapon/crowbar) && !((stat & BROKEN) || malfhack) )
- if(coverlocked && !(stat & MAINT))
- user << "\red The cover is locked and cannot be opened."
- return
- else
- opened = 1
- update_icon()
- else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside
- if(cell)
- user << "There is a power cell already installed."
- return
- else
- if (stat & MAINT)
- user << "\red There is no connector for your power cell."
- return
- user.drop_item()
- W.loc = src
- cell = W
- user.visible_message(\
- "\red [user.name] has inserted the power cell to [src.name]!",\
- "You insert the power cell.")
- chargecount = 0
- update_icon()
- else if (istype(W, /obj/item/weapon/screwdriver)) // haxing
- if(opened)
- if (cell)
- user << "\red Close the APC first." //Less hints more mystery!
- return
- else
- if (has_electronics==1 && terminal)
- has_electronics = 2
- stat &= ~MAINT
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
- user << "You screw the circuit electronics into place."
- else if (has_electronics==2)
- has_electronics = 1
- stat |= MAINT
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
- user << "You unfasten the electronics."
- else /* has_electronics==0 */
- user << "\red There is nothing to secure."
- return
- update_icon()
- else if(emagged)
- user << "The interface is broken."
- else
- wiresexposed = !wiresexposed
- user << "The wires have been [wiresexposed ? "exposed" : "unexposed"]"
- update_icon()
-
- else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card
- if(emagged)
- user << "The interface is broken."
- else if(opened)
- user << "You must close the cover to swipe an ID card."
- else if(wiresexposed)
- user << "You must close the panel"
- else if(stat & (BROKEN|MAINT))
- user << "Nothing happens."
- else
- if(src.allowed(usr) && !isWireCut(APC_WIRE_IDSCAN))
- locked = !locked
- user << "You [ locked ? "lock" : "unlock"] the APC interface."
- update_icon()
- else
- user << "\red Access denied."
- else if (istype(W, /obj/item/weapon/card/emag) && !(emagged || malfhack)) // trying to unlock with an emag card
- if(opened)
- user << "You must close the cover to swipe an ID card."
- else if(wiresexposed)
- user << "You must close the panel first"
- else if(stat & (BROKEN|MAINT))
- user << "Nothing happens."
- else
- flick("apc-spark", src)
- if (do_after(user,6))
- if(prob(50))
- emagged = 1
- locked = 0
- user << "You emag the APC interface."
- update_icon()
- else
- user << "You fail to [ locked ? "unlock" : "lock"] the APC interface."
- else if (istype(W, /obj/item/stack/cable_coil) && !terminal && opened && has_electronics!=2)
- if (src.loc:intact)
- user << "\red You must remove the floor plating in front of the APC first."
- return
- var/obj/item/stack/cable_coil/C = W
- if(C.amount < 10)
- user << "\red You need more wires."
- return
- user << "You start adding cables to the APC frame..."
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
- if(do_after(user, 20) && C.amount >= 10)
- var/turf/T = get_turf(src)
- var/obj/structure/cable/N = T.get_cable_node()
- if (prob(50) && electrocute_mob(usr, N, N))
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start()
- return
- C.use(10)
- user.visible_message(\
- "\red [user.name] has added cables to the APC frame!",\
- "You add cables to the APC frame.")
- make_terminal()
- terminal.connect_to_network()
- else if (istype(W, /obj/item/weapon/wirecutters) && terminal && opened && has_electronics!=2)
- if (src.loc:intact)
- user << "\red You must remove the floor plating in front of the APC first."
- return
- user << "You begin to cut the cables..."
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
- if(do_after(user, 50))
- if (prob(50) && electrocute_mob(usr, terminal.powernet, terminal))
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start()
- return
- new /obj/item/stack/cable_coil(loc,10)
- user.visible_message(\
- "\red [user.name] cut the cables and dismantled the power terminal.",\
- "You cut the cables and dismantle the power terminal.")
- del(terminal)
- else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && !((stat & BROKEN) || malfhack))
- user << "You trying to insert the power control board into the frame..."
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
- if(do_after(user, 10))
- has_electronics = 1
- user << "You place the power control board inside the frame."
- del(W)
- else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && ((stat & BROKEN) || malfhack))
- user << "\red You cannot put the board inside, the frame is damaged."
- return
- else if (istype(W, /obj/item/weapon/weldingtool) && opened && has_electronics==0 && !terminal)
- var/obj/item/weapon/weldingtool/WT = W
- if (WT.get_fuel() < 3)
- user << "\blue You need more welding fuel to complete this task."
- return
- user << "You start welding the APC frame..."
- playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
- if(do_after(user, 50))
- if(!src || !WT.remove_fuel(3, user)) return
- if (emagged || malfhack || (stat & BROKEN) || opened==2)
- new /obj/item/stack/sheet/metal(loc)
- user.visible_message(\
- "\red [src] has been cut apart by [user.name] with the weldingtool.",\
- "You disassembled the broken APC frame.",\
- "\red You hear welding.")
- else
- new /obj/item/apc_frame(loc)
- user.visible_message(\
- "\red [src] has been cut from the wall by [user.name] with the weldingtool.",\
- "You cut the APC frame from the wall.",\
- "\red You hear welding.")
- del(src)
- return
- else if (istype(W, /obj/item/apc_frame) && opened && emagged)
- emagged = 0
- if (opened==2)
- opened = 1
- user.visible_message(\
- "\red [user.name] has replaced the damaged APC frontal panel with a new one.",\
- "You replace the damaged APC frontal panel with a new one.")
- del(W)
- update_icon()
- else if (istype(W, /obj/item/apc_frame) && opened && ((stat & BROKEN) || malfhack))
- if (has_electronics)
- user << "You cannot repair this APC until you remove the electronics still inside."
- return
- user << "You begin to replace the damaged APC frame..."
- if(do_after(user, 50))
- user.visible_message(\
- "\red [user.name] has replaced the damaged APC frame with new one.",\
- "You replace the damaged APC frame with new one.")
- del(W)
- stat &= ~BROKEN
- malfai = null
- malfhack = 0
- if (opened==2)
- opened = 1
- update_icon()
- else
- if ( ((stat & BROKEN) || malfhack) \
- && !opened \
- && W.force >= 5 \
- && W.w_class >= 3.0 \
- && prob(20) )
- opened = 2
- user.visible_message("\red The APC cover was knocked down with the [W.name] by [user.name]!", \
- "\red You knock down the APC cover with your [W.name]!", \
- "You hear bang")
- update_icon()
- else
- if (istype(user, /mob/living/silicon))
- return src.attack_hand(user)
- if (!opened && wiresexposed && \
- (istype(W, /obj/item/device/multitool) || \
- istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/assembly/signaler)))
- return src.attack_hand(user)
- user.visible_message("\red The [src.name] has been hit with the [W.name] by [user.name]!", \
- "\red You hit the [src.name] with your [W.name]!", \
- "You hear bang")
-
-// attack with hand - remove cell (if cover open) or interact with the APC
-
-/obj/machinery/power/apc/attack_hand(mob/user)
-// if (!can_use(user)) This already gets called in interact() and in topic()
-// return
- if(!user)
- return
- src.add_fingerprint(user)
- if(usr == user && opened && (!issilicon(user)))
- if(cell)
- user.put_in_hands(cell)
- cell.add_fingerprint(user)
- cell.updateicon()
-
- src.cell = null
- user.visible_message("\red [user.name] removes the power cell from [src.name]!", "You remove the power cell.")
- //user << "You remove the power cell."
- charging = 0
- src.update_icon()
- return
- if(stat & (BROKEN|MAINT))
- return
- // do APC interaction
- src.interact(user)
-
-/obj/machinery/power/apc/attack_alien(mob/living/carbon/alien/humanoid/user)
- if(!user)
- return
- user.visible_message("\red [user.name] slashes at the [src.name]!", "\blue You slash at the [src.name]!")
- playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
-
- var/allcut = wires.IsAllCut()
-
- if(beenhit >= pick(3, 4) && wiresexposed != 1)
- wiresexposed = 1
- src.update_icon()
- src.visible_message("\red The [src.name]'s cover flies open, exposing the wires!")
-
- else if(wiresexposed == 1 && allcut == 0)
- wires.CutAll()
- src.update_icon()
- src.visible_message("\red The [src.name]'s wires are shredded!")
- else
- beenhit += 1
- return
-
-
-/obj/machinery/power/apc/interact(mob/user)
- if(!user)
- return
-
- if(wiresexposed /*&& (!istype(user, /mob/living/silicon))*/) //Commented out the typecheck to allow engiborgs to repair damaged apcs.
- wires.Interact(user)
-
- return ui_interact(user)
-
-
-/obj/machinery/power/apc/proc/get_malf_status(mob/user)
- if (ticker && ticker.mode && (user.mind in ticker.mode.malf_ai) && istype(user, /mob/living/silicon/ai))
- if (src.malfai == (user:parent ? user:parent : user))
- if (src.occupant == user)
- return 3 // 3 = User is shunted in this APC
- else if (istype(user.loc, /obj/machinery/power/apc))
- return 4 // 4 = User is shunted in another APC
- else
- return 2 // 2 = APC hacked by user, and user is in its core.
- else
- return 1 // 1 = APC not hacked.
- else
- return 0 // 0 = User is not a Malf AI
-
-
-/obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
- if(!user)
- return
-
- var/list/data = list(
- "locked" = locked,
- "isOperating" = operating,
- "externalPower" = main_status,
- "powerCellStatus" = cell ? cell.percent() : null,
- "chargeMode" = chargemode,
- "chargingStatus" = charging,
- "totalLoad" = lastused_equip + lastused_light + lastused_environ,
- "coverLocked" = coverlocked,
- "siliconUser" = istype(user, /mob/living/silicon),
- "malfStatus" = get_malf_status(user),
-
- "powerChannels" = list(
- list(
- "title" = "Equipment",
- "powerLoad" = lastused_equip,
- "status" = equipment,
- "topicParams" = list(
- "auto" = list("eqp" = 3),
- "on" = list("eqp" = 2),
- "off" = list("eqp" = 1)
- )
- ),
- list(
- "title" = "Lighting",
- "powerLoad" = lastused_light,
- "status" = lighting,
- "topicParams" = list(
- "auto" = list("lgt" = 3),
- "on" = list("lgt" = 2),
- "off" = list("lgt" = 1)
- )
- ),
- list(
- "title" = "Environment",
- "powerLoad" = lastused_environ,
- "status" = environ,
- "topicParams" = list(
- "auto" = list("env" = 3),
- "on" = list("env" = 2),
- "off" = list("env" = 1)
- )
- )
- )
- )
-
- // update the ui if it exists, returns null if no ui is passed/found
- ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
- if (!ui)
- // the ui does not exist, so we'll create a new() one
- // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
- ui = new(user, src, ui_key, "apc.tmpl", "[area.name] - APC", 520, data["siliconUser"] ? 465 : 420)
- // when the ui is first opened this is the data it will use
- ui.set_initial_data(data)
- // open the new ui window
- ui.open()
- // auto update every Master Controller tick
- ui.set_auto_update(1)
-
-/obj/machinery/power/apc/proc/report()
- return "[area.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])"
-
-/obj/machinery/power/apc/proc/update()
- if(operating && !shorted)
- area.power_light = (lighting > 1)
- area.power_equip = (equipment > 1)
- area.power_environ = (environ > 1)
-// if (area.name == "AI Chamber")
-// spawn(10)
-// world << " [area.name] [area.power_equip]"
- else
- area.power_light = 0
- area.power_equip = 0
- area.power_environ = 0
-// if (area.name == "AI Chamber")
-// world << "[area.power_equip]"
- area.power_change()
-
-/obj/machinery/power/apc/proc/isWireCut(var/wireIndex)
- return wires.IsIndexCut(wireIndex)
-
-
-/obj/machinery/power/apc/proc/can_use(mob/user as mob, var/loud = 0) //used by attack_hand() and Topic()
- if (user.stat)
- user << "\red You must be conscious to use this [src]!"
- return 0
- if(!user.client)
- return 0
- if ( ! (istype(user, /mob/living/carbon/human) || \
- istype(user, /mob/living/silicon) || \
- istype(user, /mob/living/carbon/monkey) /*&& ticker && ticker.mode.name == "monkey"*/) )
- user << "\red You don't have the dexterity to use this [src]!"
- return 0
- if(user.restrained())
- user << "\red You must have free hands to use this [src]"
- return 0
- if(user.lying)
- user << "\red You must stand to use this [src]!"
- return 0
- if (istype(user, /mob/living/silicon))
- var/mob/living/silicon/ai/AI = user
- var/mob/living/silicon/robot/robot = user
- if ( \
- src.aidisabled || \
- malfhack && istype(malfai) && \
- ( \
- (istype(AI) && (malfai!=AI && malfai != AI.parent)) || \
- (istype(robot) && (robot in malfai.connected_robots)) \
- ) \
- )
- if(!loud)
- user << "\red \The [src] have AI control disabled!"
- return 0
- else
- if ((!in_range(src, user) || !istype(src.loc, /turf)))
- return 0
-
- var/mob/living/carbon/human/H = user
- if (istype(H))
- if(H.getBrainLoss() >= 60)
- for(var/mob/M in viewers(src, null))
- M << "\red [H] stares cluelessly at [src] and drools."
- return 0
- else if(prob(H.getBrainLoss()))
- user << "\red You momentarily forget how to use [src]."
- return 0
- return 1
-
-/obj/machinery/power/apc/Topic(href, href_list)
- if(..())
- return 0
-
- if(!can_use(usr, 1))
- return 0
-
- if (href_list["lock"])
- coverlocked = !coverlocked
-
- else if (href_list["breaker"])
- toggle_breaker()
-
- else if (href_list["cmode"])
- chargemode = !chargemode
- if(!chargemode)
- charging = 0
- update_icon()
-
- else if (href_list["eqp"])
- var/val = text2num(href_list["eqp"])
- equipment = setsubsystem(val)
- update_icon()
- update()
-
- else if (href_list["lgt"])
- var/val = text2num(href_list["lgt"])
- lighting = setsubsystem(val)
- update_icon()
- update()
-
- else if (href_list["env"])
- var/val = text2num(href_list["env"])
- environ = setsubsystem(val)
- update_icon()
- update()
-
- else if (href_list["overload"])
- if(istype(usr, /mob/living/silicon))
- src.overload_lighting()
-
- else if (href_list["malfhack"])
- var/mob/living/silicon/ai/malfai = usr
- if(get_malf_status(malfai)==1)
- if (malfai.malfhacking)
- malfai << "You are already hacking an APC."
- return 1
- malfai << "Beginning override of APC systems. This takes some time, and you cannot perform other actions during the process."
- malfai.malfhack = src
- malfai.malfhacking = 1
- sleep(600)
- if(src)
- if (!src.aidisabled)
- malfai.malfhack = null
- malfai.malfhacking = 0
- locked = 1
- if (ticker.mode.config_tag == "malfunction")
- if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
- ticker.mode:apcs++
- if(usr:parent)
- src.malfai = usr:parent
- else
- src.malfai = usr
- malfai << "Hack complete. The APC is now under your exclusive control."
- update_icon()
-
- else if (href_list["occupyapc"])
- if(get_malf_status(usr))
- malfoccupy(usr)
-
- else if (href_list["deoccupyapc"])
- if(get_malf_status(usr))
- malfvacate()
-
- else if (href_list["toggleaccess"])
- if(istype(usr, /mob/living/silicon))
- if(emagged || (stat & (BROKEN|MAINT)))
- usr << "The APC does not respond to the command."
- else
- locked = !locked
- update_icon()
-
- return 1
-
-/obj/machinery/power/apc/proc/toggle_breaker()
- operating = !operating
-
- if(malfai)
- if (ticker.mode.config_tag == "malfunction")
- if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
- operating ? ticker.mode:apcs++ : ticker.mode:apcs--
-
- src.update()
- update_icon()
-
-/obj/machinery/power/apc/proc/malfoccupy(var/mob/living/silicon/ai/malf)
- if(!istype(malf))
- return
- if(istype(malf.loc, /obj/machinery/power/apc)) // Already in an APC
- malf << "You must evacuate your current apc first."
- return
- if(!malf.can_shunt)
- malf << "You cannot shunt."
- return
- if(src.z != 1)
- return
- src.occupant = new /mob/living/silicon/ai(src,malf.laws,null,1)
- src.occupant.adjustOxyLoss(malf.getOxyLoss())
- if(!findtext(src.occupant.name,"APC Copy"))
- src.occupant.name = "[malf.name] APC Copy"
- if(malf.parent)
- src.occupant.parent = malf.parent
- else
- src.occupant.parent = malf
- malf.mind.transfer_to(src.occupant)
- src.occupant.eyeobj.name = "[src.occupant.name] (AI Eye)"
- if(malf.parent)
- del(malf)
- src.occupant.verbs += /mob/living/silicon/ai/proc/corereturn
- src.occupant.verbs += /datum/game_mode/malfunction/proc/takeover
- src.occupant.cancel_camera()
- if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA)
- for(var/obj/item/weapon/pinpointer/point in world)
- point.the_disk = src //the pinpointer will detect the shunted AI
-
-
-/obj/machinery/power/apc/proc/malfvacate(var/forced)
- if(!src.occupant)
- return
- if(src.occupant.parent && src.occupant.parent.stat != 2)
- src.occupant.mind.transfer_to(src.occupant.parent)
- src.occupant.parent.adjustOxyLoss(src.occupant.getOxyLoss())
- src.occupant.parent.cancel_camera()
- del(src.occupant)
- if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA)
- for(var/obj/item/weapon/pinpointer/point in world)
- for(var/datum/mind/AI_mind in ticker.mode.malf_ai)
- var/mob/living/silicon/ai/A = AI_mind.current // the current mob the mind owns
- if(A.stat != DEAD)
- point.the_disk = A //The pinpointer tracks the AI back into its core.
-
- else
- src.occupant << "\red Primary core damaged, unable to return core processes."
- if(forced)
- src.occupant.loc = src.loc
- src.occupant.death()
- src.occupant.gib()
- for(var/obj/item/weapon/pinpointer/point in world)
- point.the_disk = null //the pinpointer will go back to pointing at the nuke disc.
-
-
-/obj/machinery/power/apc/proc/ion_act()
- //intended to be exactly the same as an AI malf attack
- if(!src.malfhack && src.z == 1)
- if(prob(3))
- src.locked = 1
- if (src.cell.charge > 0)
-// world << "\red blew APC in [src.loc.loc]"
- src.cell.charge = 0
- cell.corrupt()
- src.malfhack = 1
- update_icon()
- var/datum/effect/effect/system/harmless_smoke_spread/smoke = new /datum/effect/effect/system/harmless_smoke_spread()
- smoke.set_up(3, 0, src.loc)
- smoke.attach(src)
- smoke.start()
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(3, 1, src)
- s.start()
- for(var/mob/M in viewers(src))
- M.show_message("\red The [src.name] suddenly lets out a blast of smoke and some sparks!", 3, "\red You hear sizzling electronics.", 2)
-
-
-/obj/machinery/power/apc/surplus()
- if(terminal)
- return terminal.surplus()
- else
- return 0
-
-/obj/machinery/power/apc/add_load(var/amount)
- if(terminal && terminal.powernet)
- terminal.powernet.newload += amount
-
-/obj/machinery/power/apc/avail()
- if(terminal)
- return terminal.avail()
- else
- return 0
-
-/obj/machinery/power/apc/process()
-
- if(stat & (BROKEN|MAINT))
- return
- if(!area.requires_power)
- return
-
-
- /*
- if (equipment > 1) // off=0, off auto=1, on=2, on auto=3
- use_power(src.equip_consumption, EQUIP)
- if (lighting > 1) // off=0, off auto=1, on=2, on auto=3
- use_power(src.light_consumption, LIGHT)
- if (environ > 1) // off=0, off auto=1, on=2, on auto=3
- use_power(src.environ_consumption, ENVIRON)
-
- area.calc_lighting() */
-
- lastused_light = area.usage(LIGHT)
- lastused_equip = area.usage(EQUIP)
- lastused_environ = area.usage(ENVIRON)
- area.clear_usage()
-
- lastused_total = lastused_light + lastused_equip + lastused_environ
-
- //store states to update icon if any change
- var/last_lt = lighting
- var/last_eq = equipment
- var/last_en = environ
- var/last_ch = charging
-
- var/excess = surplus()
-
- if(!src.avail())
- main_status = 0
- else if(excess < 0)
- main_status = 1
- else
- main_status = 2
-
- var/perapc = 0
- if(terminal && terminal.powernet)
- perapc = terminal.powernet.perapc
-
- //if(debug)
- // world.log << "Status: [main_status] - Excess: [excess] - Last Equip: [lastused_equip] - Last Light: [lastused_light] - Longterm: [longtermpower]"
-
- if(cell && !shorted)
-
-
- // draw power from cell as before
- var/cellused = min(cell.charge, CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell
- cell.use(cellused)
-
- if(excess > 0 || perapc > lastused_total) // if power excess, or enough anyway, recharge the cell
- // by the same amount just used
- cell.give(cellused)
- add_load(cellused/CELLRATE) // add the load used to recharge the cell
-
-
- else // no excess, and not enough per-apc
-
- if( (cell.charge/CELLRATE+perapc) >= lastused_total) // can we draw enough from cell+grid to cover last usage?
-
- cell.charge = min(cell.maxcharge, cell.charge + CELLRATE * perapc) //recharge with what we can
- add_load(perapc) // so draw what we can from the grid
- charging = 0
-
- else // not enough power available to run the last tick!
- charging = 0
- chargecount = 0
- // This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room.
- equipment = autoset(equipment, 0)
- lighting = autoset(lighting, 0)
- environ = autoset(environ, 0)
-
-
- // set channels depending on how much charge we have left
-
- // Allow the APC to operate as normal if the cell can charge
- if(charging && longtermpower < 10)
- longtermpower += 1
- else if(longtermpower > -10)
- longtermpower -= 2
-
- if(cell.charge <= 0) // zero charge, turn all off
- equipment = autoset(equipment, 0)
- lighting = autoset(lighting, 0)
- environ = autoset(environ, 0)
- area.poweralert(0, src)
- else if(cell.percent() < 15 && longtermpower < 0) // <15%, turn off lighting & equipment
- equipment = autoset(equipment, 2)
- lighting = autoset(lighting, 2)
- environ = autoset(environ, 1)
- area.poweralert(0, src)
- else if(cell.percent() < 30 && longtermpower < 0) // <30%, turn off equipment
- equipment = autoset(equipment, 2)
- lighting = autoset(lighting, 1)
- environ = autoset(environ, 1)
- area.poweralert(0, src)
- else // otherwise all can be on
- equipment = autoset(equipment, 1)
- lighting = autoset(lighting, 1)
- environ = autoset(environ, 1)
- area.poweralert(1, src)
- if(cell.percent() > 75)
- area.poweralert(1, src)
-
- // now trickle-charge the cell
-
- if(chargemode && charging == 1 && operating)
- if(excess > 0) // check to make sure we have enough to charge
- // Max charge is perapc share, capped to cell capacity, or % per second constant (Whichever is smallest)
-/* var/ch = min(perapc, (cell.maxcharge - cell.charge), (cell.maxcharge*CHARGELEVEL))
- add_load(ch) // Removes the power we're taking from the grid
- cell.give(ch) // actually recharge the cell
-*/
- var/ch = min(perapc*CELLRATE, (cell.maxcharge - cell.charge), (cell.maxcharge*CHARGELEVEL))
- add_load(ch/CELLRATE) // Removes the power we're taking from the grid
- cell.give(ch) // actually recharge the cell
-
- else
- charging = 0 // stop charging
- chargecount = 0
-
- // show cell as fully charged if so
-
- if(cell.charge >= cell.maxcharge)
- charging = 2
-
- if(chargemode)
- if(!charging)
- if(excess > cell.maxcharge*CHARGELEVEL)
- chargecount++
- else
- chargecount = 0
-
- if(chargecount == 10)
-
- chargecount = 0
- charging = 1
-
- else // chargemode off
- charging = 0
- chargecount = 0
-
- else // no cell, switch everything off
-
- charging = 0
- chargecount = 0
- equipment = autoset(equipment, 0)
- lighting = autoset(lighting, 0)
- environ = autoset(environ, 0)
- area.poweralert(0, src)
-
- // update icon & area power if anything changed
-
- if(last_lt != lighting || last_eq != equipment || last_en != environ)
- queue_icon_update()
- update()
- else if (last_ch != charging)
- queue_icon_update()
-
-// val 0=off, 1=off(auto) 2=on 3=on(auto)
-// on 0=off, 1=on, 2=autooff
-
-obj/machinery/power/apc/proc/autoset(var/val, var/on)
- if(on==0)
- if(val==2) // if on, return off
- return 0
- else if(val==3) // if auto-on, return auto-off
- return 1
-
- else if(on==1)
- if(val==1) // if auto-off, return auto-on
- return 3
-
- else if(on==2)
- if(val==3) // if auto-on, return auto-off
- return 1
-
- return val
-
-// damage and destruction acts
-
-/obj/machinery/power/apc/meteorhit(var/obj/O as obj)
-
- set_broken()
- return
-
-/obj/machinery/power/apc/emp_act(severity)
- if(cell)
- cell.emp_act(severity)
- if(occupant)
- occupant.emp_act(severity)
- lighting = 0
- equipment = 0
- environ = 0
- spawn(600)
- equipment = 3
- environ = 3
- ..()
-
-/obj/machinery/power/apc/ex_act(severity)
-
- switch(severity)
- if(1.0)
- //set_broken() //now Del() do what we need
- if (cell)
- cell.ex_act(1.0) // more lags woohoo
- del(src)
- return
- if(2.0)
- if (prob(50))
- set_broken()
- if (cell && prob(50))
- cell.ex_act(2.0)
- if(3.0)
- if (prob(25))
- set_broken()
- if (cell && prob(25))
- cell.ex_act(3.0)
- return
-
-/obj/machinery/power/apc/blob_act()
- if (prob(75))
- set_broken()
- if (cell && prob(5))
- cell.blob_act()
-
-/obj/machinery/power/apc/proc/set_broken()
- if(malfai && operating)
- if (ticker.mode.config_tag == "malfunction")
- if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
- ticker.mode:apcs--
- stat |= BROKEN
- operating = 0
- if(occupant)
- malfvacate(1)
- update_icon()
- update()
-
-// overload all the lights in this APC area
-
-/obj/machinery/power/apc/proc/overload_lighting()
- if(/* !get_connection() || */ !operating || shorted)
- return
- if( cell && cell.charge>=20)
- cell.use(20);
- spawn(0)
- for(var/area/A in area.related)
- for(var/obj/machinery/light/L in A)
- L.on = 1
- L.broken()
- sleep(1)
-
-/obj/machinery/power/apc/Del()
- if(malfai && operating)
- if (ticker.mode.config_tag == "malfunction")
- if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
- ticker.mode:apcs--
- area.power_light = 0
- area.power_equip = 0
- area.power_environ = 0
- area.power_change()
- if(occupant)
- malfvacate(1)
- ..()
-
-/obj/machinery/power/apc/proc/shock(mob/user, prb)
- if(!prob(prb))
- return 0
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start()
- if(isalien(user))
- return 0
- if (electrocute_mob(user, src, src))
- return 1
- else
- return 0
-
-/obj/machinery/power/apc/proc/setsubsystem(val)
- if(cell && cell.charge > 0)
- return (val==1) ? 0 : val
- else if(val == 3)
- return 1
- else
- return 0
-
+#define APC_WIRE_IDSCAN 1
+#define APC_WIRE_MAIN_POWER1 2
+#define APC_WIRE_MAIN_POWER2 3
+#define APC_WIRE_AI_CONTROL 4
+
+#define APC_UPDATE_ICON_COOLDOWN 200 // 20 seconds
+
+// the Area Power Controller (APC), formerly Power Distribution Unit (PDU)
+// one per area, needs wire conection to power network
+
+// controls power to devices in that area
+// may be opened to change power cell
+// three different channels (lighting/equipment/environ) - may each be set to on, off, or auto
+
+
+//NOTE: STUFF STOLEN FROM AIRLOCK.DM thx
+
+
+/obj/machinery/power/apc
+ name = "area power controller"
+ desc = "A control terminal for the area electrical systems."
+
+ icon_state = "apc0"
+ anchored = 1
+ use_power = 0
+ req_access = list(access_engine_equip)
+ var/area/area
+ var/areastring = null
+ var/obj/item/weapon/cell/cell
+ var/start_charge = 90 // initial cell charge %
+ var/cell_type = 2500 // 0=no cell, 1=regular, 2=high-cap (x5) <- old, now it's just 0=no cell, otherwise dictate cellcapacity by changing this value. 1 used to be 1000, 2 was 2500
+ var/opened = 0 //0=closed, 1=opened, 2=cover removed
+ var/shorted = 0
+ var/lighting = 3
+ var/equipment = 3
+ var/environ = 3
+ var/operating = 1
+ var/charging = 0
+ var/chargemode = 1
+ var/chargecount = 0
+ var/locked = 1
+ var/coverlocked = 1
+ var/aidisabled = 0
+ var/tdir = null
+ var/obj/machinery/power/terminal/terminal = null
+ var/lastused_light = 0
+ var/lastused_equip = 0
+ var/lastused_environ = 0
+ var/lastused_total = 0
+ var/main_status = 0
+ var/wiresexposed = 0
+ powernet = 0 // set so that APCs aren't found as powernet nodes //Hackish, Horrible, was like this before I changed it :(
+ var/malfhack = 0 //New var for my changes to AI malf. --NeoFite
+ var/mob/living/silicon/ai/malfai = null //See above --NeoFite
+// luminosity = 1
+ var/has_electronics = 0 // 0 - none, 1 - plugged in, 2 - secured by screwdriver
+ var/overload = 1 //used for the Blackout malf module
+ var/beenhit = 0 // used for counting how many times it has been hit, used for Aliens at the moment
+ var/mob/living/silicon/ai/occupant = null
+ var/longtermpower = 10
+ var/updating_icon = 0
+ var/datum/wires/apc/wires = null
+ //var/debug = 0
+ var/auto_name = 0
+
+/obj/machinery/power/apc/updateDialog()
+ if (stat & (BROKEN|MAINT))
+ return
+ ..()
+
+/obj/machinery/power/apc/connect_to_network()
+ //Override because the APC does not directly connect to the network; it goes through a terminal.
+ //The terminal is what the power computer looks for anyway.
+ if(!terminal)
+ make_terminal()
+ if(terminal)
+ terminal.connect_to_network()
+
+/obj/machinery/power/apc/New(turf/loc, var/ndir, var/building=0)
+ ..()
+ wires = new(src)
+ // offset 24 pixels in direction of dir
+ // this allows the APC to be embedded in a wall, yet still inside an area
+ if (building)
+ dir = ndir
+ src.tdir = dir // to fix Vars bug
+ dir = SOUTH
+
+ if(auto_name)
+ name = "[get_area(src)] APC"
+
+ pixel_x = (src.tdir & 3)? 0 : (src.tdir == 4 ? 24 : -24)
+ pixel_y = (src.tdir & 3)? (src.tdir ==1 ? 24 : -24) : 0
+ if (building==0)
+ init()
+ else
+ area = src.loc.loc:master
+ opened = 1
+ operating = 0
+ name = "[area.name] APC"
+ stat |= MAINT
+ src.update_icon()
+ spawn(5)
+ src.update()
+
+
+
+/obj/machinery/power/apc/proc/make_terminal()
+ // create a terminal object at the same position as original turf loc
+ // wires will attach to this
+ terminal = new/obj/machinery/power/terminal(src.loc)
+ terminal.dir = tdir
+ terminal.master = src
+
+/obj/machinery/power/apc/proc/init()
+ has_electronics = 2 //installed and secured
+ // is starting with a power cell installed, create it and set its charge level
+ if(cell_type)
+ src.cell = new/obj/item/weapon/cell(src)
+ cell.maxcharge = cell_type // cell_type is maximum charge (old default was 1000 or 2500 (values one and two respectively)
+ cell.charge = start_charge * cell.maxcharge / 100.0 // (convert percentage to actual value)
+
+ var/area/A = src.loc.loc
+
+ //if area isn't specified use current
+ if(isarea(A) && src.areastring == null)
+ src.area = A
+ else
+ src.area = get_area_name(areastring)
+ update_icon()
+
+ make_terminal()
+
+ spawn(5)
+ src.update()
+
+/obj/machinery/power/apc/examine()
+ set src in oview(1)
+
+ if(usr /*&& !usr.stat*/)
+ ..()
+ if(stat & BROKEN)
+ usr << "Looks broken."
+ return
+ if(opened)
+ if(has_electronics && terminal)
+ usr << "The cover is [opened==2?"removed":"open"] and the power cell is [ cell ? "installed" : "missing"]."
+ else if (!has_electronics && terminal)
+ usr << "There are some wires but no any electronics."
+ else if (has_electronics && !terminal)
+ usr << "Electronics installed but not wired."
+ else /* if (!has_electronics && !terminal) */
+ usr << "There is no electronics nor connected wires."
+
+ else
+ if (stat & MAINT)
+ usr << "The cover is closed. Something wrong with it: it doesn't work."
+ else if (malfhack)
+ usr << "The cover is broken. It may be hard to force it open."
+ else
+ usr << "The cover is closed."
+
+
+// update the APC icon to show the three base states
+// also add overlays for indicator lights
+/obj/machinery/power/apc/update_icon()
+
+ overlays.Cut()
+ if(opened)
+ var/basestate = "apc[ cell ? "2" : "1" ]" // if opened, show cell if it's inserted
+ if (opened==1)
+ if (stat & (MAINT|BROKEN))
+ icon_state = "apcmaint" //disassembled APC cannot hold cell
+ else
+ icon_state = basestate
+ else if (opened == 2)
+ if ((stat & BROKEN) || malfhack )
+ icon_state = "[basestate]-b-nocover"
+ else /* if (emagged)*/
+ icon_state = "[basestate]-nocover"
+ else if (stat & BROKEN)
+ icon_state = "apc-b"
+ else if(emagged || malfai)
+ icon_state = "apcemag"
+ else if(wiresexposed)
+ icon_state = "apcewires"
+ else
+ icon_state = "apc0"
+ // if closed, update overlays for channel status
+ if(!(stat & (BROKEN|MAINT)))
+ overlays.Add("apcox-[locked]","apco3-[charging]") // 0=blue 1=red // 0=red, 1=yellow/black 2=green
+ if(operating)
+ overlays.Add("apco0-[equipment]","apco1-[lighting]","apco2-[environ]") // 0=red, 1=green, 2=blue
+
+// Used in process so it doesn't update the icon too much
+/obj/machinery/power/apc/proc/queue_icon_update()
+
+ if(!updating_icon)
+ updating_icon = 1
+ // Start the update
+ spawn(APC_UPDATE_ICON_COOLDOWN)
+ update_icon()
+ updating_icon = 0
+
+//attack with an item - open/close cover, insert cell, or (un)lock interface
+
+/obj/machinery/power/apc/attackby(obj/item/W, mob/user)
+
+ if (istype(user, /mob/living/silicon) && get_dist(src,user)>1)
+ return src.attack_hand(user)
+ if (istype(W, /obj/item/weapon/crowbar) && opened)
+ if (has_electronics==1)
+ if (terminal)
+ user << "\red Disconnect wires first."
+ return
+ playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ user << "You are trying to remove the power control board..." //lpeters - fixed grammar issues
+ if(do_after(user, 50))
+ has_electronics = 0
+ if ((stat & BROKEN) || malfhack)
+ user.visible_message(\
+ "\red [user.name] has broken the power control board inside [src.name]!",\
+ "You broke the charred power control board and remove the remains.",
+ "You hear a crack!")
+ //ticker.mode:apcs-- //XSI said no and I agreed. -rastaf0
+ else
+ user.visible_message(\
+ "\red [user.name] has removed the power control board from [src.name]!",\
+ "You remove the power control board.")
+ new /obj/item/weapon/module/power_control(loc)
+ else if (opened!=2) //cover isn't removed
+ opened = 0
+ update_icon()
+ else if (istype(W, /obj/item/weapon/crowbar) && !((stat & BROKEN) || malfhack) )
+ if(coverlocked && !(stat & MAINT))
+ user << "\red The cover is locked and cannot be opened."
+ return
+ else
+ opened = 1
+ update_icon()
+ else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside
+ if(cell)
+ user << "There is a power cell already installed."
+ return
+ else
+ if (stat & MAINT)
+ user << "\red There is no connector for your power cell."
+ return
+ user.drop_item()
+ W.loc = src
+ cell = W
+ user.visible_message(\
+ "\red [user.name] has inserted the power cell to [src.name]!",\
+ "You insert the power cell.")
+ chargecount = 0
+ update_icon()
+ else if (istype(W, /obj/item/weapon/screwdriver)) // haxing
+ if(opened)
+ if (cell)
+ user << "\red Close the APC first." //Less hints more mystery!
+ return
+ else
+ if (has_electronics==1 && terminal)
+ has_electronics = 2
+ stat &= ~MAINT
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ user << "You screw the circuit electronics into place."
+ else if (has_electronics==2)
+ has_electronics = 1
+ stat |= MAINT
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ user << "You unfasten the electronics."
+ else /* has_electronics==0 */
+ user << "\red There is nothing to secure."
+ return
+ update_icon()
+ else if(emagged)
+ user << "The interface is broken."
+ else
+ wiresexposed = !wiresexposed
+ user << "The wires have been [wiresexposed ? "exposed" : "unexposed"]"
+ update_icon()
+
+ else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card
+ if(emagged)
+ user << "The interface is broken."
+ else if(opened)
+ user << "You must close the cover to swipe an ID card."
+ else if(wiresexposed)
+ user << "You must close the panel"
+ else if(stat & (BROKEN|MAINT))
+ user << "Nothing happens."
+ else
+ if(src.allowed(usr) && !isWireCut(APC_WIRE_IDSCAN))
+ locked = !locked
+ user << "You [ locked ? "lock" : "unlock"] the APC interface."
+ update_icon()
+ else
+ user << "\red Access denied."
+ else if (istype(W, /obj/item/weapon/card/emag) && !(emagged || malfhack)) // trying to unlock with an emag card
+ if(opened)
+ user << "You must close the cover to swipe an ID card."
+ else if(wiresexposed)
+ user << "You must close the panel first"
+ else if(stat & (BROKEN|MAINT))
+ user << "Nothing happens."
+ else
+ flick("apc-spark", src)
+ if (do_after(user,6))
+ if(prob(50))
+ emagged = 1
+ locked = 0
+ user << "You emag the APC interface."
+ update_icon()
+ else
+ user << "You fail to [ locked ? "unlock" : "lock"] the APC interface."
+ else if (istype(W, /obj/item/stack/cable_coil) && !terminal && opened && has_electronics!=2)
+ if (src.loc:intact)
+ user << "\red You must remove the floor plating in front of the APC first."
+ return
+ var/obj/item/stack/cable_coil/C = W
+ if(C.amount < 10)
+ user << "\red You need more wires."
+ return
+ user << "You start adding cables to the APC frame..."
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ if(do_after(user, 20) && C.amount >= 10)
+ var/turf/T = get_turf(src)
+ var/obj/structure/cable/N = T.get_cable_node()
+ if (prob(50) && electrocute_mob(usr, N, N))
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(5, 1, src)
+ s.start()
+ return
+ C.use(10)
+ user.visible_message(\
+ "\red [user.name] has added cables to the APC frame!",\
+ "You add cables to the APC frame.")
+ make_terminal()
+ terminal.connect_to_network()
+ else if (istype(W, /obj/item/weapon/wirecutters) && terminal && opened && has_electronics!=2)
+ if (src.loc:intact)
+ user << "\red You must remove the floor plating in front of the APC first."
+ return
+ user << "You begin to cut the cables..."
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ if(do_after(user, 50))
+ if (prob(50) && electrocute_mob(usr, terminal.powernet, terminal))
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(5, 1, src)
+ s.start()
+ return
+ new /obj/item/stack/cable_coil(loc,10)
+ user.visible_message(\
+ "\red [user.name] cut the cables and dismantled the power terminal.",\
+ "You cut the cables and dismantle the power terminal.")
+ del(terminal)
+ else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && !((stat & BROKEN) || malfhack))
+ user << "You trying to insert the power control board into the frame..."
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ if(do_after(user, 10))
+ has_electronics = 1
+ user << "You place the power control board inside the frame."
+ del(W)
+ else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && ((stat & BROKEN) || malfhack))
+ user << "\red You cannot put the board inside, the frame is damaged."
+ return
+ else if (istype(W, /obj/item/weapon/weldingtool) && opened && has_electronics==0 && !terminal)
+ var/obj/item/weapon/weldingtool/WT = W
+ if (WT.get_fuel() < 3)
+ user << "\blue You need more welding fuel to complete this task."
+ return
+ user << "You start welding the APC frame..."
+ playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
+ if(do_after(user, 50))
+ if(!src || !WT.remove_fuel(3, user)) return
+ if (emagged || malfhack || (stat & BROKEN) || opened==2)
+ new /obj/item/stack/sheet/metal(loc)
+ user.visible_message(\
+ "\red [src] has been cut apart by [user.name] with the weldingtool.",\
+ "You disassembled the broken APC frame.",\
+ "\red You hear welding.")
+ else
+ new /obj/item/apc_frame(loc)
+ user.visible_message(\
+ "\red [src] has been cut from the wall by [user.name] with the weldingtool.",\
+ "You cut the APC frame from the wall.",\
+ "\red You hear welding.")
+ del(src)
+ return
+ else if (istype(W, /obj/item/apc_frame) && opened && emagged)
+ emagged = 0
+ if (opened==2)
+ opened = 1
+ user.visible_message(\
+ "\red [user.name] has replaced the damaged APC frontal panel with a new one.",\
+ "You replace the damaged APC frontal panel with a new one.")
+ del(W)
+ update_icon()
+ else if (istype(W, /obj/item/apc_frame) && opened && ((stat & BROKEN) || malfhack))
+ if (has_electronics)
+ user << "You cannot repair this APC until you remove the electronics still inside."
+ return
+ user << "You begin to replace the damaged APC frame..."
+ if(do_after(user, 50))
+ user.visible_message(\
+ "\red [user.name] has replaced the damaged APC frame with new one.",\
+ "You replace the damaged APC frame with new one.")
+ del(W)
+ stat &= ~BROKEN
+ malfai = null
+ malfhack = 0
+ if (opened==2)
+ opened = 1
+ update_icon()
+ else
+ if ( ((stat & BROKEN) || malfhack) \
+ && !opened \
+ && W.force >= 5 \
+ && W.w_class >= 3.0 \
+ && prob(20) )
+ opened = 2
+ user.visible_message("\red The APC cover was knocked down with the [W.name] by [user.name]!", \
+ "\red You knock down the APC cover with your [W.name]!", \
+ "You hear bang")
+ update_icon()
+ else
+ if (istype(user, /mob/living/silicon))
+ return src.attack_hand(user)
+ if (!opened && wiresexposed && \
+ (istype(W, /obj/item/device/multitool) || \
+ istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/assembly/signaler)))
+ return src.attack_hand(user)
+ user.visible_message("\red The [src.name] has been hit with the [W.name] by [user.name]!", \
+ "\red You hit the [src.name] with your [W.name]!", \
+ "You hear bang")
+
+// attack with hand - remove cell (if cover open) or interact with the APC
+
+/obj/machinery/power/apc/attack_hand(mob/user)
+// if (!can_use(user)) This already gets called in interact() and in topic()
+// return
+ if(!user)
+ return
+ src.add_fingerprint(user)
+ if(usr == user && opened && (!issilicon(user)))
+ if(cell)
+ user.put_in_hands(cell)
+ cell.add_fingerprint(user)
+ cell.updateicon()
+
+ src.cell = null
+ user.visible_message("\red [user.name] removes the power cell from [src.name]!", "You remove the power cell.")
+ //user << "You remove the power cell."
+ charging = 0
+ src.update_icon()
+ return
+ if(stat & (BROKEN|MAINT))
+ return
+ // do APC interaction
+ src.interact(user)
+
+/obj/machinery/power/apc/attack_alien(mob/living/carbon/alien/humanoid/user)
+ if(!user)
+ return
+ user.visible_message("\red [user.name] slashes at the [src.name]!", "\blue You slash at the [src.name]!")
+ playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
+
+ var/allcut = wires.IsAllCut()
+
+ if(beenhit >= pick(3, 4) && wiresexposed != 1)
+ wiresexposed = 1
+ src.update_icon()
+ src.visible_message("\red The [src.name]'s cover flies open, exposing the wires!")
+
+ else if(wiresexposed == 1 && allcut == 0)
+ wires.CutAll()
+ src.update_icon()
+ src.visible_message("\red The [src.name]'s wires are shredded!")
+ else
+ beenhit += 1
+ return
+
+
+/obj/machinery/power/apc/interact(mob/user)
+ if(!user)
+ return
+
+ if(wiresexposed /*&& (!istype(user, /mob/living/silicon))*/) //Commented out the typecheck to allow engiborgs to repair damaged apcs.
+ wires.Interact(user)
+
+ return ui_interact(user)
+
+
+/obj/machinery/power/apc/proc/get_malf_status(mob/user)
+ if (ticker && ticker.mode && (user.mind in ticker.mode.malf_ai) && istype(user, /mob/living/silicon/ai))
+ if (src.malfai == (user:parent ? user:parent : user))
+ if (src.occupant == user)
+ return 3 // 3 = User is shunted in this APC
+ else if (istype(user.loc, /obj/machinery/power/apc))
+ return 4 // 4 = User is shunted in another APC
+ else
+ return 2 // 2 = APC hacked by user, and user is in its core.
+ else
+ return 1 // 1 = APC not hacked.
+ else
+ return 0 // 0 = User is not a Malf AI
+
+
+/obj/machinery/power/apc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
+ if(!user)
+ return
+
+ var/list/data = list(
+ "locked" = locked,
+ "isOperating" = operating,
+ "externalPower" = main_status,
+ "powerCellStatus" = cell ? cell.percent() : null,
+ "chargeMode" = chargemode,
+ "chargingStatus" = charging,
+ "totalLoad" = lastused_equip + lastused_light + lastused_environ,
+ "coverLocked" = coverlocked,
+ "siliconUser" = istype(user, /mob/living/silicon),
+ "malfStatus" = get_malf_status(user),
+
+ "powerChannels" = list(
+ list(
+ "title" = "Equipment",
+ "powerLoad" = lastused_equip,
+ "status" = equipment,
+ "topicParams" = list(
+ "auto" = list("eqp" = 3),
+ "on" = list("eqp" = 2),
+ "off" = list("eqp" = 1)
+ )
+ ),
+ list(
+ "title" = "Lighting",
+ "powerLoad" = lastused_light,
+ "status" = lighting,
+ "topicParams" = list(
+ "auto" = list("lgt" = 3),
+ "on" = list("lgt" = 2),
+ "off" = list("lgt" = 1)
+ )
+ ),
+ list(
+ "title" = "Environment",
+ "powerLoad" = lastused_environ,
+ "status" = environ,
+ "topicParams" = list(
+ "auto" = list("env" = 3),
+ "on" = list("env" = 2),
+ "off" = list("env" = 1)
+ )
+ )
+ )
+ )
+
+ // update the ui if it exists, returns null if no ui is passed/found
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
+ if (!ui)
+ // the ui does not exist, so we'll create a new() one
+ // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
+ ui = new(user, src, ui_key, "apc.tmpl", "[area.name] - APC", 520, data["siliconUser"] ? 465 : 420)
+ // when the ui is first opened this is the data it will use
+ ui.set_initial_data(data)
+ // open the new ui window
+ ui.open()
+ // auto update every Master Controller tick
+ ui.set_auto_update(1)
+
+/obj/machinery/power/apc/proc/report()
+ return "[area.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])"
+
+/obj/machinery/power/apc/proc/update()
+ if(operating && !shorted)
+ area.power_light = (lighting > 1)
+ area.power_equip = (equipment > 1)
+ area.power_environ = (environ > 1)
+// if (area.name == "AI Chamber")
+// spawn(10)
+// world << " [area.name] [area.power_equip]"
+ else
+ area.power_light = 0
+ area.power_equip = 0
+ area.power_environ = 0
+// if (area.name == "AI Chamber")
+// world << "[area.power_equip]"
+ area.power_change()
+
+/obj/machinery/power/apc/proc/isWireCut(var/wireIndex)
+ return wires.IsIndexCut(wireIndex)
+
+
+/obj/machinery/power/apc/proc/can_use(mob/user as mob, var/loud = 0) //used by attack_hand() and Topic()
+ if (user.stat)
+ user << "\red You must be conscious to use this [src]!"
+ return 0
+ if(!user.client)
+ return 0
+ if ( ! (istype(user, /mob/living/carbon/human) || \
+ istype(user, /mob/living/silicon) || \
+ istype(user, /mob/living/carbon/monkey) /*&& ticker && ticker.mode.name == "monkey"*/) )
+ user << "\red You don't have the dexterity to use this [src]!"
+ return 0
+ if(user.restrained())
+ user << "\red You must have free hands to use this [src]"
+ return 0
+ if(user.lying)
+ user << "\red You must stand to use this [src]!"
+ return 0
+ if (istype(user, /mob/living/silicon))
+ var/mob/living/silicon/ai/AI = user
+ var/mob/living/silicon/robot/robot = user
+ if ( \
+ src.aidisabled || \
+ malfhack && istype(malfai) && \
+ ( \
+ (istype(AI) && (malfai!=AI && malfai != AI.parent)) || \
+ (istype(robot) && (robot in malfai.connected_robots)) \
+ ) \
+ )
+ if(!loud)
+ user << "\red \The [src] have AI control disabled!"
+ return 0
+ else
+ if ((!in_range(src, user) || !istype(src.loc, /turf)))
+ return 0
+
+ var/mob/living/carbon/human/H = user
+ if (istype(H))
+ if(H.getBrainLoss() >= 60)
+ for(var/mob/M in viewers(src, null))
+ M << "\red [H] stares cluelessly at [src] and drools."
+ return 0
+ else if(prob(H.getBrainLoss()))
+ user << "\red You momentarily forget how to use [src]."
+ return 0
+ return 1
+
+/obj/machinery/power/apc/Topic(href, href_list)
+ if(..())
+ return 0
+
+ if(!can_use(usr, 1))
+ return 0
+
+ if (href_list["lock"])
+ coverlocked = !coverlocked
+
+ else if (href_list["breaker"])
+ toggle_breaker()
+
+ else if (href_list["cmode"])
+ chargemode = !chargemode
+ if(!chargemode)
+ charging = 0
+ update_icon()
+
+ else if (href_list["eqp"])
+ var/val = text2num(href_list["eqp"])
+ equipment = setsubsystem(val)
+ update_icon()
+ update()
+
+ else if (href_list["lgt"])
+ var/val = text2num(href_list["lgt"])
+ lighting = setsubsystem(val)
+ update_icon()
+ update()
+
+ else if (href_list["env"])
+ var/val = text2num(href_list["env"])
+ environ = setsubsystem(val)
+ update_icon()
+ update()
+
+ else if (href_list["overload"])
+ if(istype(usr, /mob/living/silicon))
+ src.overload_lighting()
+
+ else if (href_list["malfhack"])
+ var/mob/living/silicon/ai/malfai = usr
+ if(get_malf_status(malfai)==1)
+ if (malfai.malfhacking)
+ malfai << "You are already hacking an APC."
+ return 1
+ malfai << "Beginning override of APC systems. This takes some time, and you cannot perform other actions during the process."
+ malfai.malfhack = src
+ malfai.malfhacking = 1
+ sleep(600)
+ if(src)
+ if (!src.aidisabled)
+ malfai.malfhack = null
+ malfai.malfhacking = 0
+ locked = 1
+ if (ticker.mode.config_tag == "malfunction")
+ if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
+ ticker.mode:apcs++
+ if(usr:parent)
+ src.malfai = usr:parent
+ else
+ src.malfai = usr
+ malfai << "Hack complete. The APC is now under your exclusive control."
+ update_icon()
+
+ else if (href_list["occupyapc"])
+ if(get_malf_status(usr))
+ malfoccupy(usr)
+
+ else if (href_list["deoccupyapc"])
+ if(get_malf_status(usr))
+ malfvacate()
+
+ else if (href_list["toggleaccess"])
+ if(istype(usr, /mob/living/silicon))
+ if(emagged || (stat & (BROKEN|MAINT)))
+ usr << "The APC does not respond to the command."
+ else
+ locked = !locked
+ update_icon()
+
+ return 1
+
+/obj/machinery/power/apc/proc/toggle_breaker()
+ operating = !operating
+
+ if(malfai)
+ if (ticker.mode.config_tag == "malfunction")
+ if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
+ operating ? ticker.mode:apcs++ : ticker.mode:apcs--
+
+ src.update()
+ update_icon()
+
+/obj/machinery/power/apc/proc/malfoccupy(var/mob/living/silicon/ai/malf)
+ if(!istype(malf))
+ return
+ if(istype(malf.loc, /obj/machinery/power/apc)) // Already in an APC
+ malf << "You must evacuate your current apc first."
+ return
+ if(!malf.can_shunt)
+ malf << "You cannot shunt."
+ return
+ if(src.z != 1)
+ return
+ src.occupant = new /mob/living/silicon/ai(src,malf.laws,null,1)
+ src.occupant.adjustOxyLoss(malf.getOxyLoss())
+ if(!findtext(src.occupant.name,"APC Copy"))
+ src.occupant.name = "[malf.name] APC Copy"
+ if(malf.parent)
+ src.occupant.parent = malf.parent
+ else
+ src.occupant.parent = malf
+ malf.mind.transfer_to(src.occupant)
+ src.occupant.eyeobj.name = "[src.occupant.name] (AI Eye)"
+ if(malf.parent)
+ del(malf)
+ src.occupant.verbs += /mob/living/silicon/ai/proc/corereturn
+ src.occupant.verbs += /datum/game_mode/malfunction/proc/takeover
+ src.occupant.cancel_camera()
+ if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA)
+ for(var/obj/item/weapon/pinpointer/point in world)
+ point.the_disk = src //the pinpointer will detect the shunted AI
+
+
+/obj/machinery/power/apc/proc/malfvacate(var/forced)
+ if(!src.occupant)
+ return
+ if(src.occupant.parent && src.occupant.parent.stat != 2)
+ src.occupant.mind.transfer_to(src.occupant.parent)
+ src.occupant.parent.adjustOxyLoss(src.occupant.getOxyLoss())
+ src.occupant.parent.cancel_camera()
+ del(src.occupant)
+ if (seclevel2num(get_security_level()) == SEC_LEVEL_DELTA)
+ for(var/obj/item/weapon/pinpointer/point in world)
+ for(var/datum/mind/AI_mind in ticker.mode.malf_ai)
+ var/mob/living/silicon/ai/A = AI_mind.current // the current mob the mind owns
+ if(A.stat != DEAD)
+ point.the_disk = A //The pinpointer tracks the AI back into its core.
+
+ else
+ src.occupant << "\red Primary core damaged, unable to return core processes."
+ if(forced)
+ src.occupant.loc = src.loc
+ src.occupant.death()
+ src.occupant.gib()
+ for(var/obj/item/weapon/pinpointer/point in world)
+ point.the_disk = null //the pinpointer will go back to pointing at the nuke disc.
+
+
+/obj/machinery/power/apc/proc/ion_act()
+ //intended to be exactly the same as an AI malf attack
+ if(!src.malfhack && src.z == 1)
+ if(prob(3))
+ src.locked = 1
+ if (src.cell.charge > 0)
+// world << "\red blew APC in [src.loc.loc]"
+ src.cell.charge = 0
+ cell.corrupt()
+ src.malfhack = 1
+ update_icon()
+ var/datum/effect/effect/system/harmless_smoke_spread/smoke = new /datum/effect/effect/system/harmless_smoke_spread()
+ smoke.set_up(3, 0, src.loc)
+ smoke.attach(src)
+ smoke.start()
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(3, 1, src)
+ s.start()
+ for(var/mob/M in viewers(src))
+ M.show_message("\red The [src.name] suddenly lets out a blast of smoke and some sparks!", 3, "\red You hear sizzling electronics.", 2)
+
+
+/obj/machinery/power/apc/surplus()
+ if(terminal)
+ return terminal.surplus()
+ else
+ return 0
+
+/obj/machinery/power/apc/add_load(var/amount)
+ if(terminal && terminal.powernet)
+ terminal.powernet.newload += amount
+
+/obj/machinery/power/apc/avail()
+ if(terminal)
+ return terminal.avail()
+ else
+ return 0
+
+/obj/machinery/power/apc/process()
+
+ if(stat & (BROKEN|MAINT))
+ return
+ if(!area.requires_power)
+ return
+
+
+ /*
+ if (equipment > 1) // off=0, off auto=1, on=2, on auto=3
+ use_power(src.equip_consumption, EQUIP)
+ if (lighting > 1) // off=0, off auto=1, on=2, on auto=3
+ use_power(src.light_consumption, LIGHT)
+ if (environ > 1) // off=0, off auto=1, on=2, on auto=3
+ use_power(src.environ_consumption, ENVIRON)
+
+ area.calc_lighting() */
+
+ lastused_light = area.usage(LIGHT)
+ lastused_equip = area.usage(EQUIP)
+ lastused_environ = area.usage(ENVIRON)
+ area.clear_usage()
+
+ lastused_total = lastused_light + lastused_equip + lastused_environ
+
+ //store states to update icon if any change
+ var/last_lt = lighting
+ var/last_eq = equipment
+ var/last_en = environ
+ var/last_ch = charging
+
+ var/excess = surplus()
+
+ if(!src.avail())
+ main_status = 0
+ else if(excess < 0)
+ main_status = 1
+ else
+ main_status = 2
+
+ var/perapc = 0
+ if(terminal && terminal.powernet)
+ perapc = terminal.powernet.perapc
+
+ //if(debug)
+ // world.log << "Status: [main_status] - Excess: [excess] - Last Equip: [lastused_equip] - Last Light: [lastused_light] - Longterm: [longtermpower]"
+
+ if(cell && !shorted)
+
+
+ // draw power from cell as before
+ var/cellused = min(cell.charge, CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell
+ cell.use(cellused)
+
+ if(excess > 0 || perapc > lastused_total) // if power excess, or enough anyway, recharge the cell
+ // by the same amount just used
+ cell.give(cellused)
+ add_load(cellused/CELLRATE) // add the load used to recharge the cell
+
+
+ else // no excess, and not enough per-apc
+
+ if( (cell.charge/CELLRATE+perapc) >= lastused_total) // can we draw enough from cell+grid to cover last usage?
+
+ cell.charge = min(cell.maxcharge, cell.charge + CELLRATE * perapc) //recharge with what we can
+ add_load(perapc) // so draw what we can from the grid
+ charging = 0
+
+ else // not enough power available to run the last tick!
+ charging = 0
+ chargecount = 0
+ // This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room.
+ equipment = autoset(equipment, 0)
+ lighting = autoset(lighting, 0)
+ environ = autoset(environ, 0)
+
+
+ // set channels depending on how much charge we have left
+
+ // Allow the APC to operate as normal if the cell can charge
+ if(charging && longtermpower < 10)
+ longtermpower += 1
+ else if(longtermpower > -10)
+ longtermpower -= 2
+
+ if(cell.charge <= 0) // zero charge, turn all off
+ equipment = autoset(equipment, 0)
+ lighting = autoset(lighting, 0)
+ environ = autoset(environ, 0)
+ area.poweralert(0, src)
+ else if(cell.percent() < 15 && longtermpower < 0) // <15%, turn off lighting & equipment
+ equipment = autoset(equipment, 2)
+ lighting = autoset(lighting, 2)
+ environ = autoset(environ, 1)
+ area.poweralert(0, src)
+ else if(cell.percent() < 30 && longtermpower < 0) // <30%, turn off equipment
+ equipment = autoset(equipment, 2)
+ lighting = autoset(lighting, 1)
+ environ = autoset(environ, 1)
+ area.poweralert(0, src)
+ else // otherwise all can be on
+ equipment = autoset(equipment, 1)
+ lighting = autoset(lighting, 1)
+ environ = autoset(environ, 1)
+ area.poweralert(1, src)
+ if(cell.percent() > 75)
+ area.poweralert(1, src)
+
+ // now trickle-charge the cell
+
+ if(chargemode && charging == 1 && operating)
+ if(excess > 0) // check to make sure we have enough to charge
+ // Max charge is perapc share, capped to cell capacity, or % per second constant (Whichever is smallest)
+/* var/ch = min(perapc, (cell.maxcharge - cell.charge), (cell.maxcharge*CHARGELEVEL))
+ add_load(ch) // Removes the power we're taking from the grid
+ cell.give(ch) // actually recharge the cell
+*/
+ var/ch = min(perapc*CELLRATE, (cell.maxcharge - cell.charge), (cell.maxcharge*CHARGELEVEL))
+ add_load(ch/CELLRATE) // Removes the power we're taking from the grid
+ cell.give(ch) // actually recharge the cell
+
+ else
+ charging = 0 // stop charging
+ chargecount = 0
+
+ // show cell as fully charged if so
+
+ if(cell.charge >= cell.maxcharge)
+ charging = 2
+
+ if(chargemode)
+ if(!charging)
+ if(excess > cell.maxcharge*CHARGELEVEL)
+ chargecount++
+ else
+ chargecount = 0
+
+ if(chargecount == 10)
+
+ chargecount = 0
+ charging = 1
+
+ else // chargemode off
+ charging = 0
+ chargecount = 0
+
+ else // no cell, switch everything off
+
+ charging = 0
+ chargecount = 0
+ equipment = autoset(equipment, 0)
+ lighting = autoset(lighting, 0)
+ environ = autoset(environ, 0)
+ area.poweralert(0, src)
+
+ // update icon & area power if anything changed
+
+ if(last_lt != lighting || last_eq != equipment || last_en != environ)
+ queue_icon_update()
+ update()
+ else if (last_ch != charging)
+ queue_icon_update()
+
+// val 0=off, 1=off(auto) 2=on 3=on(auto)
+// on 0=off, 1=on, 2=autooff
+
+obj/machinery/power/apc/proc/autoset(var/val, var/on)
+ if(on==0)
+ if(val==2) // if on, return off
+ return 0
+ else if(val==3) // if auto-on, return auto-off
+ return 1
+
+ else if(on==1)
+ if(val==1) // if auto-off, return auto-on
+ return 3
+
+ else if(on==2)
+ if(val==3) // if auto-on, return auto-off
+ return 1
+
+ return val
+
+// damage and destruction acts
+
+/obj/machinery/power/apc/meteorhit(var/obj/O as obj)
+
+ set_broken()
+ return
+
+/obj/machinery/power/apc/emp_act(severity)
+ if(cell)
+ cell.emp_act(severity)
+ if(occupant)
+ occupant.emp_act(severity)
+ lighting = 0
+ equipment = 0
+ environ = 0
+ spawn(600)
+ equipment = 3
+ environ = 3
+ ..()
+
+/obj/machinery/power/apc/ex_act(severity)
+
+ switch(severity)
+ if(1.0)
+ //set_broken() //now Del() do what we need
+ if (cell)
+ cell.ex_act(1.0) // more lags woohoo
+ del(src)
+ return
+ if(2.0)
+ if (prob(50))
+ set_broken()
+ if (cell && prob(50))
+ cell.ex_act(2.0)
+ if(3.0)
+ if (prob(25))
+ set_broken()
+ if (cell && prob(25))
+ cell.ex_act(3.0)
+ return
+
+/obj/machinery/power/apc/blob_act()
+ if (prob(75))
+ set_broken()
+ if (cell && prob(5))
+ cell.blob_act()
+
+/obj/machinery/power/apc/proc/set_broken()
+ if(malfai && operating)
+ if (ticker.mode.config_tag == "malfunction")
+ if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
+ ticker.mode:apcs--
+ stat |= BROKEN
+ operating = 0
+ if(occupant)
+ malfvacate(1)
+ update_icon()
+ update()
+
+// overload all the lights in this APC area
+
+/obj/machinery/power/apc/proc/overload_lighting()
+ if(/* !get_connection() || */ !operating || shorted)
+ return
+ if( cell && cell.charge>=20)
+ cell.use(20);
+ spawn(0)
+ for(var/area/A in area.related)
+ for(var/obj/machinery/light/L in A)
+ L.on = 1
+ L.broken()
+ sleep(1)
+
+/obj/machinery/power/apc/Del()
+ if(malfai && operating)
+ if (ticker.mode.config_tag == "malfunction")
+ if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
+ ticker.mode:apcs--
+ area.power_light = 0
+ area.power_equip = 0
+ area.power_environ = 0
+ area.power_change()
+ if(occupant)
+ malfvacate(1)
+ ..()
+
+/obj/machinery/power/apc/proc/shock(mob/user, prb)
+ if(!prob(prb))
+ return 0
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(5, 1, src)
+ s.start()
+ if(isalien(user))
+ return 0
+ if (electrocute_mob(user, src, src))
+ return 1
+ else
+ return 0
+
+/obj/machinery/power/apc/proc/setsubsystem(val)
+ if(cell && cell.charge > 0)
+ return (val==1) ? 0 : val
+ else if(val == 3)
+ return 1
+ else
+ return 0
+
#undef APC_UPDATE_ICON_COOLDOWN
\ No newline at end of file
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index 8d213ebfbc4..c7c96294130 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -1,620 +1,620 @@
-// attach a wire to a power machine - leads from the turf you are standing on
-
-/obj/machinery/power/attackby(obj/item/weapon/W, mob/user)
-
- if(istype(W, /obj/item/stack/cable_coil))
-
- var/obj/item/stack/cable_coil/coil = W
-
- var/turf/T = user.loc
-
- if(T.intact || !istype(T, /turf/simulated/floor))
- return
-
- if(get_dist(src, user) > 1)
- return
-
- if(!directwired) // only for attaching to directwired machines
- return
-
- coil.turf_place(T, user)
- return
- else
- ..()
- return
-
-/obj/structure/cable
- level = 1
- anchored =1
- var/datum/powernet/powernet
- name = "power cable"
- desc = "A flexible superconducting cable for heavy-duty power transfer"
- icon = 'icons/obj/power_cond/power_cond_red.dmi'
- icon_state = "0-1"
- var/d1 = 0
- var/d2 = 1
- layer = 2.44 //Just below unary stuff, which is at 2.45 and above pipes, which are at 2.4
- var/cable_color = "red"
- var/obj/structure/powerswitch/power_switch
-
-/obj/structure/cable/yellow
- cable_color = "yellow"
- icon = 'icons/obj/power_cond/power_cond_yellow.dmi'
-
-/obj/structure/cable/green
- cable_color = "green"
- icon = 'icons/obj/power_cond/power_cond_green.dmi'
-
-/obj/structure/cable/blue
- cable_color = "blue"
- icon = 'icons/obj/power_cond/power_cond_blue.dmi'
-
-/obj/structure/cable/pink
- cable_color = "pink"
- icon = 'icons/obj/power_cond/power_cond_pink.dmi'
-
-/obj/structure/cable/orange
- cable_color = "orange"
- icon = 'icons/obj/power_cond/power_cond_orange.dmi'
-
-/obj/structure/cable/cyan
- cable_color = "cyan"
- icon = 'icons/obj/power_cond/power_cond_cyan.dmi'
-
-/obj/structure/cable/white
- cable_color = "white"
- icon = 'icons/obj/power_cond/power_cond_white.dmi'
-
-// the power cable object
-
-/obj/structure/cable/New()
- ..()
-
-
- // ensure d1 & d2 reflect the icon_state for entering and exiting cable
-
- var/dash = findtext(icon_state, "-")
-
- d1 = text2num( copytext( icon_state, 1, dash ) )
-
- d2 = text2num( copytext( icon_state, dash+1 ) )
-
- var/turf/T = src.loc // hide if turf is not intact
-
- if(level==1) hide(T.intact)
- cable_list += src
-
-
-/obj/structure/cable/Del() // called when a cable is deleted
- if(!defer_powernet_rebuild) // set if network will be rebuilt manually
- if(powernet)
- powernet.cut_cable(src) // update the powernets
- cable_list -= src
- ..() // then go ahead and delete the cable
-
-/obj/structure/cable/hide(var/i)
-
- if(level == 1 && istype(loc, /turf))
- invisibility = i ? 101 : 0
- updateicon()
-
-/obj/structure/cable/proc/updateicon()
- if(invisibility)
- icon_state = "[d1]-[d2]-f"
- else
- icon_state = "[d1]-[d2]"
-
-
-// returns the powernet this cable belongs to
-/obj/structure/cable/proc/get_powernet() //TODO: remove this as it is obsolete
- return powernet
-
-/obj/structure/cable/attack_tk(mob/user)
- return
-
-/obj/structure/cable/attackby(obj/item/W, mob/user)
-
- var/turf/T = src.loc
- if(T.intact)
- return
-
- if(istype(W, /obj/item/weapon/wirecutters))
-
-// if(power_switch)
-// user << "\red This piece of cable is tied to a power switch. Flip the switch to remove it."
-// return
-
- if (shock(user, 50))
- return
-
- if(src.d1) // 0-X cables are 1 unit, X-X cables are 2 units long
- new/obj/item/stack/cable_coil(T, 2, cable_color)
- else
- new/obj/item/stack/cable_coil(T, 1, cable_color)
-
- for(var/mob/O in viewers(src, null))
- O.show_message("\red [user] cuts the cable.", 1)
-
- investigate_log("was cut by [key_name(usr, usr.client)] in [user.loc.loc]","wires")
-
- del(src)
- return
-
-
- else if(istype(W, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/coil = W
- coil.cable_join(src, user)
-
- else if(istype(W, /obj/item/device/multitool))
-
- var/datum/powernet/PN = get_powernet() // find the powernet
-
- if(PN && (PN.avail > 0)) // is it powered?
- user << "\red [PN.avail]W in power network."
-
- else
- user << "\red The cable is not powered."
-
- shock(user, 5, 0.2)
-
- else
- if (W.flags & CONDUCT)
- shock(user, 50, 0.7)
-
- src.add_fingerprint(user)
-
-// shock the user with probability prb
-
-/obj/structure/cable/proc/shock(mob/user, prb, var/siemens_coeff = 1.0)
- if(!prob(prb))
- return 0
- if (electrocute_mob(user, powernet, src, siemens_coeff))
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start()
- return 1
- else
- return 0
-
-/obj/structure/cable/ex_act(severity)
- switch(severity)
- if(1.0)
- del(src)
- if(2.0)
- if (prob(50))
- new/obj/item/stack/cable_coil(src.loc, src.d1 ? 2 : 1, cable_color)
- del(src)
-
- if(3.0)
- if (prob(25))
- new/obj/item/stack/cable_coil(src.loc, src.d1 ? 2 : 1, cable_color)
- del(src)
- return
-
-// the cable coil object, used for laying cable
-
-#define MAXCOIL 30
-/obj/item/stack/cable_coil
- name = "cable coil"
- icon = 'icons/obj/power.dmi'
- icon_state = "coil_red"
- item_state = "coil_red"
- amount = MAXCOIL
- item_color = "red"
- desc = "A coil of power cable."
- throwforce = 10
- w_class = 2.0
- throw_speed = 2
- throw_range = 5
- m_amt = 50
- g_amt = 20
- flags = CONDUCT
- slot_flags = SLOT_BELT
- attack_verb = list("whipped", "lashed", "disciplined", "flogged")
-
- suicide_act(mob/user)
- if(locate(/obj/structure/stool) in user.loc)
- viewers(user) << "[user] is making a noose with the [src.name]! It looks like \he's trying to commit suicide."
- else
- viewers(user) << "[user] is strangling \himself with the [src.name]! It looks like \he's trying to commit suicide."
- return(OXYLOSS)
-
-/obj/item/stack/cable_coil/attack(mob/living/carbon/human/H, mob/user)
- if(!istype(H))
- return ..()
-
- var/obj/item/organ/limb/affecting = H.get_organ(check_zone(user.zone_sel.selecting))
- if(affecting.status == ORGAN_ROBOTIC)
- src.item_heal_robotic(H, user, 0, 30)
- src.use(1)
- return
- else
- return ..()
-
-/obj/item/stack/cable_coil/New(loc, length = MAXCOIL, var/param_color = null)
- ..()
- src.amount = length
- if (param_color)
- item_color = param_color
- pixel_x = rand(-2,2)
- pixel_y = rand(-2,2)
- update_icon()
-
-/obj/item/stack/cable_coil/update_icon()
- if (!item_color)
- item_color = pick("red", "yellow", "blue", "green")
- if(amount == 1)
- icon_state = "coil_[item_color]1"
- name = "cable piece"
- else if(amount == 2)
- icon_state = "coil_[item_color]2"
- name = "cable piece"
- else
- icon_state = "coil_[item_color]"
- name = "cable coil"
-
-/obj/item/stack/cable_coil/examine()
- set src in view(1)
-
- if(amount == 1)
- usr << "A short piece of power cable."
- else if(amount == 2)
- usr << "A piece of power cable."
- else
- usr << "A coil of power cable. There are [amount] lengths of cable in the coil."
-
-/obj/item/stack/cable_coil/verb/make_restraint()
- set name = "Make Cable Restraints"
- set category = "Object"
- var/mob/M = usr
-
- if(ishuman(M) && !M.restrained() && !M.stat && !M.paralysis && ! M.stunned)
- if(!istype(usr.loc,/turf)) return
- if(src.amount <= 14)
- usr << "\red You need at least 15 lengths to make restraints!"
- return
- var/obj/item/weapon/handcuffs/cable/B = new /obj/item/weapon/handcuffs/cable(usr.loc)
- B.icon_state = "cuff_[item_color]"
- usr << "\blue You wind some cable together to make some restraints."
- src.use(15)
- else
- usr << "\blue You cannot do that."
- ..()
-
-/obj/item/stack/cable_coil/attackby(obj/item/weapon/W, mob/user)
- ..()
- if( istype(W, /obj/item/weapon/wirecutters) && src.amount > 1)
- src.amount--
- new/obj/item/stack/cable_coil(user.loc, 1,item_color)
- user << "You cut a piece off the cable coil."
- src.update_icon()
- return
-
- else if( istype(W, /obj/item/stack/cable_coil) )
- var/obj/item/stack/cable_coil/C = W
- if(C.amount >= MAXCOIL)
- user << "The coil is too long, you cannot add any more cable to it."
- return
-
- if( (C.amount + src.amount <= MAXCOIL) )
- user << "You join the cable coils together."
- C.give(src.amount) // give it cable
- src.use(src.amount) // make sure this one cleans up right
- return
-
- else
- var/amt = MAXCOIL - C.amount
- user << "You transfer [amt] length\s of cable from one coil to the other."
- C.give(amt)
- src.use(amt)
- return
-
-/obj/item/stack/cable_coil/use(var/used)
- if(src.amount < used)
- return 0
- else if (src.amount == used)
- .=1 //Because del(src) stops the proc, set the default return value to 1
- if(ismob(loc)) //handle mob icon update
- var/mob/M = loc
- M.u_equip(src)
- del(src)
- else
- amount -= used
- update_icon()
- return 1
-
-/obj/item/stack/cable_coil/proc/give(var/extra)
- if(amount + extra > MAXCOIL)
- amount = MAXCOIL
- else
- amount += extra
- update_icon()
-
-// called when cable_coil is clicked on a turf/simulated/floor
-
-/obj/item/stack/cable_coil/proc/turf_place(turf/simulated/floor/F, mob/user)
-
- if(!isturf(user.loc))
- return
-
- if(get_dist(F,user) > 1)
- user << "You can't lay cable at a place that far away."
- return
-
- if(F.intact) // if floor is intact, complain
- user << "You can't lay cable there unless the floor tiles are removed."
- return
-
- else
- var/dirn
-
- if(user.loc == F)
- dirn = user.dir // if laying on the tile we're on, lay in the direction we're facing
- else
- dirn = get_dir(F, user)
-
- for(var/obj/structure/cable/LC in F)
- if((LC.d1 == dirn && LC.d2 == 0 ) || ( LC.d2 == dirn && LC.d1 == 0))
- user << "There's already a cable at that position."
- return
-
- var/obj/structure/cable/C = new(F)
-
- C.cableColor(item_color)
-
- C.d1 = 0
- C.d2 = dirn
- C.add_fingerprint(user)
- C.updateicon()
-
- C.powernet = new()
- powernets += C.powernet
- C.powernet.cables += C
-
- C.mergeConnectedNetworks(C.d2)
- C.mergeConnectedNetworksOnTurf()
-
-
- use(1)
- if (C.shock(user, 50))
- if (prob(50)) //fail
- new/obj/item/stack/cable_coil(C.loc, 1, C.cable_color)
- del(C)
- //src.laying = 1
- //last = C
-
-
-// called when cable_coil is click on an installed obj/cable
-
-/obj/item/stack/cable_coil/proc/cable_join(obj/structure/cable/C, mob/user)
-
- var/turf/U = user.loc
- if(!isturf(U))
- return
-
- var/turf/T = C.loc
-
- if(!isturf(T) || T.intact) // sanity checks, also stop use interacting with T-scanner revealed cable
- return
-
- if(get_dist(C, user) > 1) // make sure it's close enough
- user << "You can't lay cable at a place that far away."
- return
-
-
- if(U == T) // do nothing if we clicked a cable we're standing on
- return // may change later if can think of something logical to do
-
- var/dirn = get_dir(C, user)
-
- if(C.d1 == dirn || C.d2 == dirn) // one end of the clicked cable is pointing towards us
- if(U.intact) // can't place a cable if the floor is complete
- user << "You can't lay cable there unless the floor tiles are removed."
- return
- else
- // cable is pointing at us, we're standing on an open tile
- // so create a stub pointing at the clicked cable on our tile
-
- var/fdirn = turn(dirn, 180) // the opposite direction
-
- for(var/obj/structure/cable/LC in U) // check to make sure there's not a cable there already
- if(LC.d1 == fdirn || LC.d2 == fdirn)
- user << "There's already a cable at that position."
- return
-
- var/obj/structure/cable/NC = new(U)
- NC.cableColor(item_color)
-
- NC.d1 = 0
- NC.d2 = fdirn
- NC.add_fingerprint()
- NC.updateicon()
-
- if(C.powernet)
- NC.powernet = C.powernet
- NC.powernet.cables += NC
- NC.mergeConnectedNetworks(NC.d2)
- NC.mergeConnectedNetworksOnTurf()
- use(1)
- if (NC.shock(user, 50))
- if (prob(50)) //fail
- new/obj/item/stack/cable_coil(NC.loc, 1, NC.cable_color)
- del(NC)
-
- return
- else if(C.d1 == 0) // exisiting cable doesn't point at our position, so see if it's a stub
- // if so, make it a full cable pointing from it's old direction to our dirn
- var/nd1 = C.d2 // these will be the new directions
- var/nd2 = dirn
-
-
- if(nd1 > nd2) // swap directions to match icons/states
- nd1 = dirn
- nd2 = C.d2
-
-
- for(var/obj/structure/cable/LC in T) // check to make sure there's no matching cable
- if(LC == C) // skip the cable we're interacting with
- continue
- if((LC.d1 == nd1 && LC.d2 == nd2) || (LC.d1 == nd2 && LC.d2 == nd1) ) // make sure no cable matches either direction
- user << "There's already a cable at that position."
- return
-
-
- C.cableColor(item_color)
-
- C.d1 = nd1
- C.d2 = nd2
-
- C.add_fingerprint()
- C.updateicon()
-
-
- C.mergeConnectedNetworks(C.d1)
- C.mergeConnectedNetworks(C.d2)
- C.mergeConnectedNetworksOnTurf()
-
- use(1)
- if (C.shock(user, 50))
- if (prob(50)) //fail
- new/obj/item/stack/cable_coil(C.loc, 2, C.cable_color)
- del(C)
- return
-
- C.denode()// this call may have disconnected some cables that terminated on the centre of the turf, if so split the powernets.
- return
-
-/obj/structure/cable/proc/mergeConnectedNetworks(var/direction)
- var/turf/TB
- if(!(d1 == direction || d2 == direction))
- return
- TB = get_step(src, direction)
-
- for(var/obj/structure/cable/TC in TB)
-
- if(!TC)
- continue
-
- if(src == TC)
- continue
-
- var/fdir = (!direction)? 0 : turn(direction, 180)
-
- if(TC.d1 == fdir || TC.d2 == fdir)
-
- if(!TC.powernet)
- TC.powernet = new()
- powernets += TC.powernet
- TC.powernet.cables += TC
-
- if(powernet)
- merge_powernets(powernet,TC.powernet)
- else
- powernet = TC.powernet
- powernet.cables += src
-
-
-
-
-/obj/structure/cable/proc/mergeConnectedNetworksOnTurf()
- if(!powernet)
- powernet = new()
- powernets += powernet
- powernet.cables += src
-
- for(var/AM in loc)
- if(istype(AM,/obj/structure/cable))
- var/obj/structure/cable/C = AM
- if(C.d1 == 0 && d1==0) //only connected if they are both "nodes"
- if(C.powernet == powernet) continue
- if(C.powernet)
- merge_powernets(powernet, C.powernet)
- else
- C.powernet = powernet
- powernet.cables += C
-
- else if(istype(AM,/obj/machinery/power/apc))
- var/obj/machinery/power/apc/N = AM
- if(!N.terminal) continue
- if(N.terminal.powernet)
- merge_powernets(powernet, N.terminal.powernet)
- else
- N.terminal.powernet = powernet
- powernet.nodes[N.terminal] = N.terminal
-
- else if(istype(AM,/obj/machinery/power))
- var/obj/machinery/power/M = AM
- if(M.powernet == powernet) continue
- if(M.powernet)
- merge_powernets(powernet, M.powernet)
- else
- M.powernet = powernet
- powernet.nodes[M] = M
-
-
-obj/structure/cable/proc/cableColor(var/colorC)
- var/color_n = "red"
- if(colorC)
- color_n = colorC
- cable_color = color_n
- switch(colorC)
- if("red")
- icon = 'icons/obj/power_cond/power_cond_red.dmi'
- if("yellow")
- icon = 'icons/obj/power_cond/power_cond_yellow.dmi'
- if("green")
- icon = 'icons/obj/power_cond/power_cond_green.dmi'
- if("blue")
- icon = 'icons/obj/power_cond/power_cond_blue.dmi'
- if("pink")
- icon = 'icons/obj/power_cond/power_cond_pink.dmi'
- if("orange")
- icon = 'icons/obj/power_cond/power_cond_orange.dmi'
- if("cyan")
- icon = 'icons/obj/power_cond/power_cond_cyan.dmi'
- if("white")
- icon = 'icons/obj/power_cond/power_cond_white.dmi'
-
-/obj/item/stack/cable_coil/cut
- item_state = "coil_red2"
-
-/obj/item/stack/cable_coil/cut/New(loc)
- ..()
- src.amount = rand(1,2)
- pixel_x = rand(-2,2)
- pixel_y = rand(-2,2)
- update_icon()
-
-/obj/item/stack/cable_coil/yellow
- item_color = "yellow"
- icon_state = "coil_yellow"
-
-/obj/item/stack/cable_coil/blue
- item_color = "blue"
- icon_state = "coil_blue"
- item_state = "coil_blue"
-
-/obj/item/stack/cable_coil/green
- item_color = "green"
- icon_state = "coil_green"
-
-/obj/item/stack/cable_coil/pink
- item_color = "pink"
- icon_state = "coil_pink"
-
-/obj/item/stack/cable_coil/orange
- item_color = "orange"
- icon_state = "coil_orange"
-
-/obj/item/stack/cable_coil/cyan
- item_color = "cyan"
- icon_state = "coil_cyan"
-
-/obj/item/stack/cable_coil/white
- item_color = "white"
- icon_state = "coil_white"
-
-/obj/item/stack/cable_coil/random/New()
- item_color = pick("red","yellow","green","blue","pink")
- icon_state = "coil_[item_color]"
- ..()
+// attach a wire to a power machine - leads from the turf you are standing on
+
+/obj/machinery/power/attackby(obj/item/weapon/W, mob/user)
+
+ if(istype(W, /obj/item/stack/cable_coil))
+
+ var/obj/item/stack/cable_coil/coil = W
+
+ var/turf/T = user.loc
+
+ if(T.intact || !istype(T, /turf/simulated/floor))
+ return
+
+ if(get_dist(src, user) > 1)
+ return
+
+ if(!directwired) // only for attaching to directwired machines
+ return
+
+ coil.turf_place(T, user)
+ return
+ else
+ ..()
+ return
+
+/obj/structure/cable
+ level = 1
+ anchored =1
+ var/datum/powernet/powernet
+ name = "power cable"
+ desc = "A flexible superconducting cable for heavy-duty power transfer"
+ icon = 'icons/obj/power_cond/power_cond_red.dmi'
+ icon_state = "0-1"
+ var/d1 = 0
+ var/d2 = 1
+ layer = 2.44 //Just below unary stuff, which is at 2.45 and above pipes, which are at 2.4
+ var/cable_color = "red"
+ var/obj/structure/powerswitch/power_switch
+
+/obj/structure/cable/yellow
+ cable_color = "yellow"
+ icon = 'icons/obj/power_cond/power_cond_yellow.dmi'
+
+/obj/structure/cable/green
+ cable_color = "green"
+ icon = 'icons/obj/power_cond/power_cond_green.dmi'
+
+/obj/structure/cable/blue
+ cable_color = "blue"
+ icon = 'icons/obj/power_cond/power_cond_blue.dmi'
+
+/obj/structure/cable/pink
+ cable_color = "pink"
+ icon = 'icons/obj/power_cond/power_cond_pink.dmi'
+
+/obj/structure/cable/orange
+ cable_color = "orange"
+ icon = 'icons/obj/power_cond/power_cond_orange.dmi'
+
+/obj/structure/cable/cyan
+ cable_color = "cyan"
+ icon = 'icons/obj/power_cond/power_cond_cyan.dmi'
+
+/obj/structure/cable/white
+ cable_color = "white"
+ icon = 'icons/obj/power_cond/power_cond_white.dmi'
+
+// the power cable object
+
+/obj/structure/cable/New()
+ ..()
+
+
+ // ensure d1 & d2 reflect the icon_state for entering and exiting cable
+
+ var/dash = findtext(icon_state, "-")
+
+ d1 = text2num( copytext( icon_state, 1, dash ) )
+
+ d2 = text2num( copytext( icon_state, dash+1 ) )
+
+ var/turf/T = src.loc // hide if turf is not intact
+
+ if(level==1) hide(T.intact)
+ cable_list += src
+
+
+/obj/structure/cable/Del() // called when a cable is deleted
+ if(!defer_powernet_rebuild) // set if network will be rebuilt manually
+ if(powernet)
+ powernet.cut_cable(src) // update the powernets
+ cable_list -= src
+ ..() // then go ahead and delete the cable
+
+/obj/structure/cable/hide(var/i)
+
+ if(level == 1 && istype(loc, /turf))
+ invisibility = i ? 101 : 0
+ updateicon()
+
+/obj/structure/cable/proc/updateicon()
+ if(invisibility)
+ icon_state = "[d1]-[d2]-f"
+ else
+ icon_state = "[d1]-[d2]"
+
+
+// returns the powernet this cable belongs to
+/obj/structure/cable/proc/get_powernet() //TODO: remove this as it is obsolete
+ return powernet
+
+/obj/structure/cable/attack_tk(mob/user)
+ return
+
+/obj/structure/cable/attackby(obj/item/W, mob/user)
+
+ var/turf/T = src.loc
+ if(T.intact)
+ return
+
+ if(istype(W, /obj/item/weapon/wirecutters))
+
+// if(power_switch)
+// user << "\red This piece of cable is tied to a power switch. Flip the switch to remove it."
+// return
+
+ if (shock(user, 50))
+ return
+
+ if(src.d1) // 0-X cables are 1 unit, X-X cables are 2 units long
+ new/obj/item/stack/cable_coil(T, 2, cable_color)
+ else
+ new/obj/item/stack/cable_coil(T, 1, cable_color)
+
+ for(var/mob/O in viewers(src, null))
+ O.show_message("\red [user] cuts the cable.", 1)
+
+ investigate_log("was cut by [key_name(usr, usr.client)] in [user.loc.loc]","wires")
+
+ del(src)
+ return
+
+
+ else if(istype(W, /obj/item/stack/cable_coil))
+ var/obj/item/stack/cable_coil/coil = W
+ coil.cable_join(src, user)
+
+ else if(istype(W, /obj/item/device/multitool))
+
+ var/datum/powernet/PN = get_powernet() // find the powernet
+
+ if(PN && (PN.avail > 0)) // is it powered?
+ user << "\red [PN.avail]W in power network."
+
+ else
+ user << "\red The cable is not powered."
+
+ shock(user, 5, 0.2)
+
+ else
+ if (W.flags & CONDUCT)
+ shock(user, 50, 0.7)
+
+ src.add_fingerprint(user)
+
+// shock the user with probability prb
+
+/obj/structure/cable/proc/shock(mob/user, prb, var/siemens_coeff = 1.0)
+ if(!prob(prb))
+ return 0
+ if (electrocute_mob(user, powernet, src, siemens_coeff))
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(5, 1, src)
+ s.start()
+ return 1
+ else
+ return 0
+
+/obj/structure/cable/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ del(src)
+ if(2.0)
+ if (prob(50))
+ new/obj/item/stack/cable_coil(src.loc, src.d1 ? 2 : 1, cable_color)
+ del(src)
+
+ if(3.0)
+ if (prob(25))
+ new/obj/item/stack/cable_coil(src.loc, src.d1 ? 2 : 1, cable_color)
+ del(src)
+ return
+
+// the cable coil object, used for laying cable
+
+#define MAXCOIL 30
+/obj/item/stack/cable_coil
+ name = "cable coil"
+ icon = 'icons/obj/power.dmi'
+ icon_state = "coil_red"
+ item_state = "coil_red"
+ amount = MAXCOIL
+ item_color = "red"
+ desc = "A coil of power cable."
+ throwforce = 10
+ w_class = 2.0
+ throw_speed = 2
+ throw_range = 5
+ m_amt = 50
+ g_amt = 20
+ flags = CONDUCT
+ slot_flags = SLOT_BELT
+ attack_verb = list("whipped", "lashed", "disciplined", "flogged")
+
+ suicide_act(mob/user)
+ if(locate(/obj/structure/stool) in user.loc)
+ viewers(user) << "[user] is making a noose with the [src.name]! It looks like \he's trying to commit suicide."
+ else
+ viewers(user) << "[user] is strangling \himself with the [src.name]! It looks like \he's trying to commit suicide."
+ return(OXYLOSS)
+
+/obj/item/stack/cable_coil/attack(mob/living/carbon/human/H, mob/user)
+ if(!istype(H))
+ return ..()
+
+ var/obj/item/organ/limb/affecting = H.get_organ(check_zone(user.zone_sel.selecting))
+ if(affecting.status == ORGAN_ROBOTIC)
+ src.item_heal_robotic(H, user, 0, 30)
+ src.use(1)
+ return
+ else
+ return ..()
+
+/obj/item/stack/cable_coil/New(loc, length = MAXCOIL, var/param_color = null)
+ ..()
+ src.amount = length
+ if (param_color)
+ item_color = param_color
+ pixel_x = rand(-2,2)
+ pixel_y = rand(-2,2)
+ update_icon()
+
+/obj/item/stack/cable_coil/update_icon()
+ if (!item_color)
+ item_color = pick("red", "yellow", "blue", "green")
+ if(amount == 1)
+ icon_state = "coil_[item_color]1"
+ name = "cable piece"
+ else if(amount == 2)
+ icon_state = "coil_[item_color]2"
+ name = "cable piece"
+ else
+ icon_state = "coil_[item_color]"
+ name = "cable coil"
+
+/obj/item/stack/cable_coil/examine()
+ set src in view(1)
+
+ if(amount == 1)
+ usr << "A short piece of power cable."
+ else if(amount == 2)
+ usr << "A piece of power cable."
+ else
+ usr << "A coil of power cable. There are [amount] lengths of cable in the coil."
+
+/obj/item/stack/cable_coil/verb/make_restraint()
+ set name = "Make Cable Restraints"
+ set category = "Object"
+ var/mob/M = usr
+
+ if(ishuman(M) && !M.restrained() && !M.stat && !M.paralysis && ! M.stunned)
+ if(!istype(usr.loc,/turf)) return
+ if(src.amount <= 14)
+ usr << "\red You need at least 15 lengths to make restraints!"
+ return
+ var/obj/item/weapon/handcuffs/cable/B = new /obj/item/weapon/handcuffs/cable(usr.loc)
+ B.icon_state = "cuff_[item_color]"
+ usr << "\blue You wind some cable together to make some restraints."
+ src.use(15)
+ else
+ usr << "\blue You cannot do that."
+ ..()
+
+/obj/item/stack/cable_coil/attackby(obj/item/weapon/W, mob/user)
+ ..()
+ if( istype(W, /obj/item/weapon/wirecutters) && src.amount > 1)
+ src.amount--
+ new/obj/item/stack/cable_coil(user.loc, 1,item_color)
+ user << "You cut a piece off the cable coil."
+ src.update_icon()
+ return
+
+ else if( istype(W, /obj/item/stack/cable_coil) )
+ var/obj/item/stack/cable_coil/C = W
+ if(C.amount >= MAXCOIL)
+ user << "The coil is too long, you cannot add any more cable to it."
+ return
+
+ if( (C.amount + src.amount <= MAXCOIL) )
+ user << "You join the cable coils together."
+ C.give(src.amount) // give it cable
+ src.use(src.amount) // make sure this one cleans up right
+ return
+
+ else
+ var/amt = MAXCOIL - C.amount
+ user << "You transfer [amt] length\s of cable from one coil to the other."
+ C.give(amt)
+ src.use(amt)
+ return
+
+/obj/item/stack/cable_coil/use(var/used)
+ if(src.amount < used)
+ return 0
+ else if (src.amount == used)
+ .=1 //Because del(src) stops the proc, set the default return value to 1
+ if(ismob(loc)) //handle mob icon update
+ var/mob/M = loc
+ M.u_equip(src)
+ del(src)
+ else
+ amount -= used
+ update_icon()
+ return 1
+
+/obj/item/stack/cable_coil/proc/give(var/extra)
+ if(amount + extra > MAXCOIL)
+ amount = MAXCOIL
+ else
+ amount += extra
+ update_icon()
+
+// called when cable_coil is clicked on a turf/simulated/floor
+
+/obj/item/stack/cable_coil/proc/turf_place(turf/simulated/floor/F, mob/user)
+
+ if(!isturf(user.loc))
+ return
+
+ if(get_dist(F,user) > 1)
+ user << "You can't lay cable at a place that far away."
+ return
+
+ if(F.intact) // if floor is intact, complain
+ user << "You can't lay cable there unless the floor tiles are removed."
+ return
+
+ else
+ var/dirn
+
+ if(user.loc == F)
+ dirn = user.dir // if laying on the tile we're on, lay in the direction we're facing
+ else
+ dirn = get_dir(F, user)
+
+ for(var/obj/structure/cable/LC in F)
+ if((LC.d1 == dirn && LC.d2 == 0 ) || ( LC.d2 == dirn && LC.d1 == 0))
+ user << "There's already a cable at that position."
+ return
+
+ var/obj/structure/cable/C = new(F)
+
+ C.cableColor(item_color)
+
+ C.d1 = 0
+ C.d2 = dirn
+ C.add_fingerprint(user)
+ C.updateicon()
+
+ C.powernet = new()
+ powernets += C.powernet
+ C.powernet.cables += C
+
+ C.mergeConnectedNetworks(C.d2)
+ C.mergeConnectedNetworksOnTurf()
+
+
+ use(1)
+ if (C.shock(user, 50))
+ if (prob(50)) //fail
+ new/obj/item/stack/cable_coil(C.loc, 1, C.cable_color)
+ del(C)
+ //src.laying = 1
+ //last = C
+
+
+// called when cable_coil is click on an installed obj/cable
+
+/obj/item/stack/cable_coil/proc/cable_join(obj/structure/cable/C, mob/user)
+
+ var/turf/U = user.loc
+ if(!isturf(U))
+ return
+
+ var/turf/T = C.loc
+
+ if(!isturf(T) || T.intact) // sanity checks, also stop use interacting with T-scanner revealed cable
+ return
+
+ if(get_dist(C, user) > 1) // make sure it's close enough
+ user << "You can't lay cable at a place that far away."
+ return
+
+
+ if(U == T) // do nothing if we clicked a cable we're standing on
+ return // may change later if can think of something logical to do
+
+ var/dirn = get_dir(C, user)
+
+ if(C.d1 == dirn || C.d2 == dirn) // one end of the clicked cable is pointing towards us
+ if(U.intact) // can't place a cable if the floor is complete
+ user << "You can't lay cable there unless the floor tiles are removed."
+ return
+ else
+ // cable is pointing at us, we're standing on an open tile
+ // so create a stub pointing at the clicked cable on our tile
+
+ var/fdirn = turn(dirn, 180) // the opposite direction
+
+ for(var/obj/structure/cable/LC in U) // check to make sure there's not a cable there already
+ if(LC.d1 == fdirn || LC.d2 == fdirn)
+ user << "There's already a cable at that position."
+ return
+
+ var/obj/structure/cable/NC = new(U)
+ NC.cableColor(item_color)
+
+ NC.d1 = 0
+ NC.d2 = fdirn
+ NC.add_fingerprint()
+ NC.updateicon()
+
+ if(C.powernet)
+ NC.powernet = C.powernet
+ NC.powernet.cables += NC
+ NC.mergeConnectedNetworks(NC.d2)
+ NC.mergeConnectedNetworksOnTurf()
+ use(1)
+ if (NC.shock(user, 50))
+ if (prob(50)) //fail
+ new/obj/item/stack/cable_coil(NC.loc, 1, NC.cable_color)
+ del(NC)
+
+ return
+ else if(C.d1 == 0) // exisiting cable doesn't point at our position, so see if it's a stub
+ // if so, make it a full cable pointing from it's old direction to our dirn
+ var/nd1 = C.d2 // these will be the new directions
+ var/nd2 = dirn
+
+
+ if(nd1 > nd2) // swap directions to match icons/states
+ nd1 = dirn
+ nd2 = C.d2
+
+
+ for(var/obj/structure/cable/LC in T) // check to make sure there's no matching cable
+ if(LC == C) // skip the cable we're interacting with
+ continue
+ if((LC.d1 == nd1 && LC.d2 == nd2) || (LC.d1 == nd2 && LC.d2 == nd1) ) // make sure no cable matches either direction
+ user << "There's already a cable at that position."
+ return
+
+
+ C.cableColor(item_color)
+
+ C.d1 = nd1
+ C.d2 = nd2
+
+ C.add_fingerprint()
+ C.updateicon()
+
+
+ C.mergeConnectedNetworks(C.d1)
+ C.mergeConnectedNetworks(C.d2)
+ C.mergeConnectedNetworksOnTurf()
+
+ use(1)
+ if (C.shock(user, 50))
+ if (prob(50)) //fail
+ new/obj/item/stack/cable_coil(C.loc, 2, C.cable_color)
+ del(C)
+ return
+
+ C.denode()// this call may have disconnected some cables that terminated on the centre of the turf, if so split the powernets.
+ return
+
+/obj/structure/cable/proc/mergeConnectedNetworks(var/direction)
+ var/turf/TB
+ if(!(d1 == direction || d2 == direction))
+ return
+ TB = get_step(src, direction)
+
+ for(var/obj/structure/cable/TC in TB)
+
+ if(!TC)
+ continue
+
+ if(src == TC)
+ continue
+
+ var/fdir = (!direction)? 0 : turn(direction, 180)
+
+ if(TC.d1 == fdir || TC.d2 == fdir)
+
+ if(!TC.powernet)
+ TC.powernet = new()
+ powernets += TC.powernet
+ TC.powernet.cables += TC
+
+ if(powernet)
+ merge_powernets(powernet,TC.powernet)
+ else
+ powernet = TC.powernet
+ powernet.cables += src
+
+
+
+
+/obj/structure/cable/proc/mergeConnectedNetworksOnTurf()
+ if(!powernet)
+ powernet = new()
+ powernets += powernet
+ powernet.cables += src
+
+ for(var/AM in loc)
+ if(istype(AM,/obj/structure/cable))
+ var/obj/structure/cable/C = AM
+ if(C.d1 == 0 && d1==0) //only connected if they are both "nodes"
+ if(C.powernet == powernet) continue
+ if(C.powernet)
+ merge_powernets(powernet, C.powernet)
+ else
+ C.powernet = powernet
+ powernet.cables += C
+
+ else if(istype(AM,/obj/machinery/power/apc))
+ var/obj/machinery/power/apc/N = AM
+ if(!N.terminal) continue
+ if(N.terminal.powernet)
+ merge_powernets(powernet, N.terminal.powernet)
+ else
+ N.terminal.powernet = powernet
+ powernet.nodes[N.terminal] = N.terminal
+
+ else if(istype(AM,/obj/machinery/power))
+ var/obj/machinery/power/M = AM
+ if(M.powernet == powernet) continue
+ if(M.powernet)
+ merge_powernets(powernet, M.powernet)
+ else
+ M.powernet = powernet
+ powernet.nodes[M] = M
+
+
+obj/structure/cable/proc/cableColor(var/colorC)
+ var/color_n = "red"
+ if(colorC)
+ color_n = colorC
+ cable_color = color_n
+ switch(colorC)
+ if("red")
+ icon = 'icons/obj/power_cond/power_cond_red.dmi'
+ if("yellow")
+ icon = 'icons/obj/power_cond/power_cond_yellow.dmi'
+ if("green")
+ icon = 'icons/obj/power_cond/power_cond_green.dmi'
+ if("blue")
+ icon = 'icons/obj/power_cond/power_cond_blue.dmi'
+ if("pink")
+ icon = 'icons/obj/power_cond/power_cond_pink.dmi'
+ if("orange")
+ icon = 'icons/obj/power_cond/power_cond_orange.dmi'
+ if("cyan")
+ icon = 'icons/obj/power_cond/power_cond_cyan.dmi'
+ if("white")
+ icon = 'icons/obj/power_cond/power_cond_white.dmi'
+
+/obj/item/stack/cable_coil/cut
+ item_state = "coil_red2"
+
+/obj/item/stack/cable_coil/cut/New(loc)
+ ..()
+ src.amount = rand(1,2)
+ pixel_x = rand(-2,2)
+ pixel_y = rand(-2,2)
+ update_icon()
+
+/obj/item/stack/cable_coil/yellow
+ item_color = "yellow"
+ icon_state = "coil_yellow"
+
+/obj/item/stack/cable_coil/blue
+ item_color = "blue"
+ icon_state = "coil_blue"
+ item_state = "coil_blue"
+
+/obj/item/stack/cable_coil/green
+ item_color = "green"
+ icon_state = "coil_green"
+
+/obj/item/stack/cable_coil/pink
+ item_color = "pink"
+ icon_state = "coil_pink"
+
+/obj/item/stack/cable_coil/orange
+ item_color = "orange"
+ icon_state = "coil_orange"
+
+/obj/item/stack/cable_coil/cyan
+ item_color = "cyan"
+ icon_state = "coil_cyan"
+
+/obj/item/stack/cable_coil/white
+ item_color = "white"
+ icon_state = "coil_white"
+
+/obj/item/stack/cable_coil/random/New()
+ item_color = pick("red","yellow","green","blue","pink")
+ icon_state = "coil_[item_color]"
+ ..()
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index faede0b44f2..4d0fee71a46 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -1,743 +1,743 @@
-// The lighting system
-//
-// consists of light fixtures (/obj/machinery/light) and light tube/bulb items (/obj/item/weapon/light)
-
-
-// status values shared between lighting fixtures and items
-#define LIGHT_OK 0
-#define LIGHT_EMPTY 1
-#define LIGHT_BROKEN 2
-#define LIGHT_BURNED 3
-
-
-
-/obj/item/light_fixture_frame
- name = "light fixture frame"
- desc = "Used for building lights."
- icon = 'icons/obj/lighting.dmi'
- icon_state = "tube-construct-item"
- flags = CONDUCT
- var/fixture_type = "tube"
- var/obj/machinery/light/newlight = null
- var/sheets_refunded = 2
-
-/obj/item/light_fixture_frame/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if (istype(W, /obj/item/weapon/wrench))
- new /obj/item/stack/sheet/metal( get_turf(src.loc), sheets_refunded )
- del(src)
- return
- ..()
-
-/obj/item/light_fixture_frame/proc/try_build(turf/on_wall)
- if (get_dist(on_wall,usr)>1)
- return
- var/ndir = get_dir(usr,on_wall)
- if (!(ndir in cardinal))
- return
- var/turf/loc = get_turf(usr)
- if (!istype(loc, /turf/simulated/floor))
- usr << "\red [src.name] cannot be placed on this spot."
- return
- usr << "Attaching [src] to the wall."
- playsound(src.loc, 'sound/machines/click.ogg', 75, 1)
- var/constrdir = usr.dir
- var/constrloc = usr.loc
- if (!do_after(usr, 30))
- return
- switch(fixture_type)
- if("bulb")
- newlight = new /obj/machinery/light_construct/small(constrloc)
- if("tube")
- newlight = new /obj/machinery/light_construct(constrloc)
- newlight.dir = constrdir
- newlight.fingerprints = src.fingerprints
- newlight.fingerprintshidden = src.fingerprintshidden
- newlight.fingerprintslast = src.fingerprintslast
-
- usr.visible_message("[usr.name] attaches [src] to the wall.", \
- "You attach [src] to the wall.")
- del(src)
-
-/obj/item/light_fixture_frame/small
- name = "small light fixture frame"
- desc = "Used for building small lights."
- icon = 'icons/obj/lighting.dmi'
- icon_state = "bulb-construct-item"
- flags = CONDUCT
- fixture_type = "bulb"
- sheets_refunded = 1
-
-/obj/machinery/light_construct
- name = "light fixture frame"
- desc = "A light fixture under construction."
- icon = 'icons/obj/lighting.dmi'
- icon_state = "tube-construct-stage1"
- anchored = 1
- layer = 5
- var/stage = 1
- var/fixture_type = "tube"
- var/sheets_refunded = 2
- var/obj/machinery/light/newlight = null
-
-/obj/machinery/light_construct/New()
- ..()
- if (fixture_type == "bulb")
- icon_state = "bulb-construct-stage1"
-
-/obj/machinery/light_construct/examine()
- set src in view()
- ..()
- if (!(usr in view(2))) return
- switch(src.stage)
- if(1)
- usr << "It's an empty frame."
- return
- if(2)
- usr << "It's wired."
- return
- if(3)
- usr << "The casing is closed."
- return
-
-/obj/machinery/light_construct/attackby(obj/item/weapon/W as obj, mob/user as mob)
- src.add_fingerprint(user)
- if (istype(W, /obj/item/weapon/wrench))
- if (src.stage == 1)
- playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
- usr << "You begin deconstructing [src]."
- if (!do_after(usr, 30))
- return
- new /obj/item/stack/sheet/metal( get_turf(src.loc), sheets_refunded )
- user.visible_message("[user.name] deconstructs [src].", \
- "You deconstruct [src].", "You hear a noise.")
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 75, 1)
- del(src)
- if (src.stage == 2)
- usr << "You have to remove the wires first."
- return
-
- if (src.stage == 3)
- usr << "You have to unscrew the case first."
- return
-
- if(istype(W, /obj/item/weapon/wirecutters))
- if (src.stage != 2) return
- src.stage = 1
- switch(fixture_type)
- if ("tube")
- src.icon_state = "tube-construct-stage1"
- if("bulb")
- src.icon_state = "bulb-construct-stage1"
- new /obj/item/stack/cable_coil(get_turf(src.loc), 1, "red")
- user.visible_message("[user.name] removes the wiring from [src].", \
- "You remove the wiring from [src].", "You hear a noise.")
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
- return
-
- if(istype(W, /obj/item/stack/cable_coil))
- if (src.stage != 1) return
- var/obj/item/stack/cable_coil/coil = W
- coil.use(1)
- switch(fixture_type)
- if ("tube")
- src.icon_state = "tube-construct-stage2"
- if("bulb")
- src.icon_state = "bulb-construct-stage2"
- src.stage = 2
- user.visible_message("[user.name] adds wires to [src].", \
- "You add wires to [src].")
- return
-
- if(istype(W, /obj/item/weapon/screwdriver))
- if (src.stage == 2)
- switch(fixture_type)
- if ("tube")
- src.icon_state = "tube-empty"
- if("bulb")
- src.icon_state = "bulb-empty"
- src.stage = 3
- user.visible_message("[user.name] closes [src]'s casing.", \
- "You close [src]'s casing.", "You hear a noise.")
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 75, 1)
-
- switch(fixture_type)
-
- if("tube")
- newlight = new /obj/machinery/light/built(src.loc)
- if ("bulb")
- newlight = new /obj/machinery/light/small/built(src.loc)
-
- newlight.dir = src.dir
- src.transfer_fingerprints_to(newlight)
- del(src)
- return
- ..()
-
-/obj/machinery/light_construct/small
- name = "small light fixture frame"
- desc = "A small light fixture under construction."
- icon = 'icons/obj/lighting.dmi'
- icon_state = "bulb-construct-stage1"
- anchored = 1
- layer = 5
- stage = 1
- fixture_type = "bulb"
- sheets_refunded = 1
-
-// the standard tube light fixture
-/obj/machinery/light
- name = "light fixture"
- icon = 'icons/obj/lighting.dmi'
- var/base_state = "tube" // base description and icon_state
- icon_state = "tube1"
- desc = "A lighting fixture."
- anchored = 1
- layer = 5 // They were appearing under mobs which is a little weird - Ostaf
- use_power = 2
- idle_power_usage = 2
- active_power_usage = 20
- power_channel = LIGHT //Lights are calc'd via area so they dont need to be in the machine list
- var/on = 0 // 1 if on, 0 if off
- var/on_gs = 0
- var/brightness = 8 // luminosity when on, also used in power calculation
- var/status = LIGHT_OK // LIGHT_OK, _EMPTY, _BURNED or _BROKEN
- var/flickering = 0
- var/light_type = /obj/item/weapon/light/tube // the type of light item
- var/fitting = "tube"
- var/switchcount = 0 // count of number of times switched on/off
- // this is used to calc the probability the light burns out
-
- var/rigged = 0 // true if rigged to explode
-
-// the smaller bulb light fixture
-
-/obj/machinery/light/small
- icon_state = "bulb1"
- base_state = "bulb"
- fitting = "bulb"
- brightness = 4
- desc = "A small lighting fixture."
- light_type = /obj/item/weapon/light/bulb
-
-
-/obj/machinery/light/Move()
- if(status != LIGHT_BROKEN) broken(1)
- return ..()
-
-/obj/machinery/light/built/New()
- status = LIGHT_EMPTY
- update(0)
- ..()
-
-/obj/machinery/light/small/built/New()
- status = LIGHT_EMPTY
- update(0)
- ..()
-
-
-// create a new lighting fixture
-/obj/machinery/light/New()
- ..()
- spawn(2)
- switch(fitting)
- if("tube")
- brightness = 8
- if(prob(2))
- broken(1)
- if("bulb")
- brightness = 4
- if(prob(5))
- broken(1)
- spawn(1)
- update(0)
-
-/obj/machinery/light/Del()
- var/area/A = get_area(src)
- if(A)
- on = 0
-// A.update_lights()
- ..()
-
-/obj/machinery/light/update_icon()
-
- switch(status) // set icon_states
- if(LIGHT_OK)
- icon_state = "[base_state][on]"
- if(LIGHT_EMPTY)
- icon_state = "[base_state]-empty"
- on = 0
- if(LIGHT_BURNED)
- icon_state = "[base_state]-burned"
- on = 0
- if(LIGHT_BROKEN)
- icon_state = "[base_state]-broken"
- on = 0
- return
-
-// update the icon_state and luminosity of the light depending on its state
-/obj/machinery/light/proc/update(var/trigger = 1)
-
- update_icon()
- if(on)
- if(luminosity != brightness)
- switchcount++
- if(rigged)
- if(status == LIGHT_OK && trigger)
- explode()
- else if( prob( min(60, switchcount*switchcount*0.01) ) )
- if(status == LIGHT_OK && trigger)
- status = LIGHT_BURNED
- icon_state = "[base_state]-burned"
- on = 0
- SetLuminosity(0)
- else
- use_power = 2
- SetLuminosity(brightness)
- else
- use_power = 1
- SetLuminosity(0)
-
- active_power_usage = (luminosity * 10)
- if(on != on_gs)
- on_gs = on
-
-
-// attempt to set the light's on/off status
-// will not switch on if broken/burned/empty
-/obj/machinery/light/proc/seton(var/s)
- on = (s && status == LIGHT_OK)
- update()
-
-// examine verb
-/obj/machinery/light/examine()
- set src in oview(1)
- ..()
- if(usr && !usr.stat)
- switch(status)
- if(LIGHT_OK)
- usr << "It is turned [on? "on" : "off"]."
- if(LIGHT_EMPTY)
- usr << "The [fitting] has been removed."
- if(LIGHT_BURNED)
- usr << "The [fitting] is burnt out."
- if(LIGHT_BROKEN)
- usr << "The [fitting] has been smashed."
-
-
-
-// attack with item - insert light (if right type), otherwise try to break the light
-
-/obj/machinery/light/attackby(obj/item/W, mob/user)
-
- //Light replacer code
- if(istype(W, /obj/item/device/lightreplacer))
- var/obj/item/device/lightreplacer/LR = W
- if(isliving(user))
- var/mob/living/U = user
- LR.ReplaceLight(src, U)
- return
-
- // attempt to insert light
- if(istype(W, /obj/item/weapon/light))
- if(status != LIGHT_EMPTY)
- user << "There is a [fitting] already inserted."
- return
- else
- src.add_fingerprint(user)
- var/obj/item/weapon/light/L = W
- if(istype(L, light_type))
- status = L.status
- user << "You insert the [L.name]."
- switchcount = L.switchcount
- rigged = L.rigged
- brightness = L.brightness
- on = has_power()
- update()
-
- user.drop_item() //drop the item to update overlays and such
- del(L)
-
- if(on && rigged)
- explode()
- else
- user << "This type of light requires a [fitting]."
- return
-
- // attempt to break the light
- //If xenos decide they want to smash a light bulb with a toolbox, who am I to stop them? /N
-
- else if(status != LIGHT_BROKEN && status != LIGHT_EMPTY)
-
-
- if(prob(1+W.force * 5))
-
- user << "You hit the light, and it smashes!"
- for(var/mob/M in viewers(src))
- if(M == user)
- continue
- M.show_message("[user.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2)
- if(on && (W.flags & CONDUCT))
- //if(!user.mutations & COLD_RESISTANCE)
- if (prob(12))
- electrocute_mob(user, get_area(src), src, 0.3)
- broken()
-
- else
- user << "You hit the light!"
-
- // attempt to stick weapon into light socket
- else if(status == LIGHT_EMPTY)
- if(istype(W, /obj/item/weapon/screwdriver)) //If it's a screwdriver open it.
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 75, 1)
- user.visible_message("[user.name] opens [src]'s casing.", \
- "You open [src]'s casing.", "You hear a noise.")
- var/obj/machinery/light_construct/newlight = null
- switch(fitting)
- if("tube")
- newlight = new /obj/machinery/light_construct(src.loc)
- newlight.icon_state = "tube-construct-stage2"
-
- if("bulb")
- newlight = new /obj/machinery/light_construct/small(src.loc)
- newlight.icon_state = "bulb-construct-stage2"
- newlight.dir = src.dir
- newlight.stage = 2
- newlight.fingerprints = src.fingerprints
- newlight.fingerprintshidden = src.fingerprintshidden
- newlight.fingerprintslast = src.fingerprintslast
- del(src)
- return
-
- user << "You stick \the [W] into the light socket!"
- if(has_power() && (W.flags & CONDUCT))
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(3, 1, src)
- s.start()
- //if(!user.mutations & COLD_RESISTANCE)
- if (prob(75))
- electrocute_mob(user, get_area(src), src, rand(0.7,1.0))
-
-
-// returns whether this light has power
-// true if area has power and lightswitch is on
-/obj/machinery/light/proc/has_power()
- var/area/A = src.loc.loc
- return A.master.lightswitch && A.master.power_light
-
-/obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
- if(flickering) return
- flickering = 1
- spawn(0)
- if(on && status == LIGHT_OK)
- for(var/i = 0; i < amount; i++)
- if(status != LIGHT_OK) break
- on = !on
- update(0)
- sleep(rand(5, 15))
- on = (status == LIGHT_OK)
- update(0)
- flickering = 0
-
-// ai attack - make lights flicker, because why not
-
-/obj/machinery/light/attack_ai(mob/user)
- src.flicker(1)
- return
-
-// Aliens smash the bulb but do not get electrocuted./N
-/obj/machinery/light/attack_alien(mob/living/carbon/alien/humanoid/user)//So larva don't go breaking light bulbs.
- if(status == LIGHT_EMPTY||status == LIGHT_BROKEN)
- user << "\green That object is useless to you."
- return
- else if (status == LIGHT_OK||status == LIGHT_BURNED)
- for(var/mob/M in viewers(src))
- M.show_message("\red [user.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2)
- broken()
- return
-
-/obj/machinery/light/attack_animal(mob/living/simple_animal/M)
- if(M.melee_damage_upper == 0) return
- if(status == LIGHT_EMPTY||status == LIGHT_BROKEN)
- M << "\red That object is useless to you."
- return
- else if (status == LIGHT_OK||status == LIGHT_BURNED)
- for(var/mob/O in viewers(src))
- O.show_message("\red [M.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2)
- broken()
- return
-// attack with hand - remove tube/bulb
-// if hands aren't protected and the light is on, burn the player
-
-/obj/machinery/light/attack_hand(mob/user)
-
- add_fingerprint(user)
-
- if(status == LIGHT_EMPTY)
- user << "There is no [fitting] in this light."
- return
-
- // make it burn hands if not wearing fire-insulated gloves
- if(on)
- var/prot = 0
- var/mob/living/carbon/human/H = user
-
- if(istype(H))
-
- if(H.gloves)
- var/obj/item/clothing/gloves/G = H.gloves
- if(G.max_heat_protection_temperature)
- prot = (G.max_heat_protection_temperature > 360)
- else
- prot = 1
-
- if(prot > 0 || (COLD_RESISTANCE in user.mutations))
- user << "You remove the light [fitting]"
- else if(TK in user.mutations)
- user << "You telekinetically remove the light [fitting]."
- else
- user << "You try to remove the light [fitting], but you burn your hand on it!"
-
- var/obj/item/organ/limb/affecting = H.get_organ("[user.hand ? "l" : "r" ]_arm")
- if(affecting.take_damage( 0, 5 )) // 5 burn damage
- H.update_damage_overlays(0)
- H.updatehealth()
- return // if burned, don't remove the light
- else
- user << "You remove the light [fitting]."
- // create a light tube/bulb item and put it in the user's hand
- var/obj/item/weapon/light/L = new light_type()
- L.status = status
- L.rigged = rigged
- L.brightness = brightness
-
- // light item inherits the switchcount, then zero it
- L.switchcount = switchcount
- switchcount = 0
-
- L.update()
- L.add_fingerprint(user)
- L.loc = loc
-
- user.put_in_active_hand(L) //puts it in our active hand
-
- status = LIGHT_EMPTY
- update()
-
-/obj/machinery/light/attack_tk(mob/user)
- if(status == LIGHT_EMPTY)
- user << "There is no [fitting] in this light."
- return
-
- user << "You telekinetically remove the light [fitting]."
- // create a light tube/bulb item and put it in the user's hand
- var/obj/item/weapon/light/L = new light_type()
- L.status = status
- L.rigged = rigged
- L.brightness = brightness
-
- // light item inherits the switchcount, then zero it
- L.switchcount = switchcount
- switchcount = 0
-
- L.update()
- L.add_fingerprint(user)
- L.loc = loc
-
- status = LIGHT_EMPTY
- update()
-
-// break the light and make sparks if was on
-
-/obj/machinery/light/proc/broken(var/skip_sound_and_sparks = 0)
- if(status == LIGHT_EMPTY)
- return
-
- if(!skip_sound_and_sparks)
- if(status == LIGHT_OK || status == LIGHT_BURNED)
- playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
- if(on)
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(3, 1, src)
- s.start()
- status = LIGHT_BROKEN
- update()
-
-/obj/machinery/light/proc/fix()
- if(status == LIGHT_OK)
- return
- status = LIGHT_OK
- brightness = initial(brightness)
- on = 1
- update()
-
-// explosion effect
-// destroy the whole light fixture or just shatter it
-
-/obj/machinery/light/ex_act(severity)
- switch(severity)
- if(1.0)
- del(src)
- return
- if(2.0)
- if (prob(75))
- broken()
- if(3.0)
- if (prob(50))
- broken()
- return
-
-//blob effect
-
-/obj/machinery/light/blob_act()
- if(prob(75))
- broken()
-
-
-// timed process
-// use power
-
-#define LIGHTING_POWER_FACTOR 20 //20W per unit luminosity
-
-/obj/machinery/light/process()//TODO: remove/add this from machines to save on processing as needed ~Carn PRIORITY
- if(on)
- use_power(luminosity * LIGHTING_POWER_FACTOR, LIGHT)
-
-// called when area power state changes
-/obj/machinery/light/power_change()
- spawn(10)
- var/area/A = src.loc.loc
- A = A.master
- seton(A.lightswitch && A.power_light)
-
-// called when on fire
-
-/obj/machinery/light/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
- if(prob(max(0, exposed_temperature - 673))) //0% at <400C, 100% at >500C
- broken()
-
-// explode the light
-
-/obj/machinery/light/proc/explode()
- var/turf/T = get_turf(src.loc)
- spawn(0)
- broken() // break it first to give a warning
- sleep(2)
- explosion(T, 0, 0, 2, 2)
- sleep(1)
- del(src)
-
-// the light item
-// can be tube or bulb subtypes
-// will fit into empty /obj/machinery/light of the corresponding type
-
-/obj/item/weapon/light
- icon = 'icons/obj/lighting.dmi'
- force = 2
- throwforce = 5
- w_class = 1
- var/status = 0 // LIGHT_OK, LIGHT_BURNED or LIGHT_BROKEN
- var/base_state
- var/switchcount = 0 // number of times switched
- m_amt = 60
- var/rigged = 0 // true if rigged to explode
- var/brightness = 2 //how much light it gives off
-
-/obj/item/weapon/light/tube
- name = "light tube"
- desc = "A replacement light tube."
- icon_state = "ltube"
- base_state = "ltube"
- item_state = "c_tube"
- g_amt = 100
- brightness = 8
-
-/obj/item/weapon/light/tube/large
- w_class = 2
- name = "large light tube"
- brightness = 15
-
-/obj/item/weapon/light/bulb
- name = "light bulb"
- desc = "A replacement light bulb."
- icon_state = "lbulb"
- base_state = "lbulb"
- item_state = "contvapour"
- g_amt = 100
- brightness = 5
-
-/obj/item/weapon/light/throw_impact(atom/hit_atom)
- ..()
- shatter()
-
-/obj/item/weapon/light/bulb/fire
- name = "fire bulb"
- desc = "A replacement fire bulb."
- icon_state = "fbulb"
- base_state = "fbulb"
- item_state = "egg4"
- g_amt = 100
- brightness = 5
-
-// update the icon state and description of the light
-
-/obj/item/weapon/light/proc/update()
- switch(status)
- if(LIGHT_OK)
- icon_state = base_state
- desc = "A replacement [name]."
- if(LIGHT_BURNED)
- icon_state = "[base_state]-burned"
- desc = "A burnt-out [name]."
- if(LIGHT_BROKEN)
- icon_state = "[base_state]-broken"
- desc = "A broken [name]."
-
-
-/obj/item/weapon/light/New()
- ..()
- switch(name)
- if("light tube")
- brightness = rand(6,9)
- if("light bulb")
- brightness = rand(4,6)
- update()
-
-
-// attack bulb/tube with object
-// if a syringe, can inject plasma to make it explode
-/obj/item/weapon/light/attackby(var/obj/item/I, var/mob/user)
- ..()
- if(istype(I, /obj/item/weapon/reagent_containers/syringe))
- var/obj/item/weapon/reagent_containers/syringe/S = I
-
- user << "You inject the solution into the [src]."
-
- if(S.reagents.has_reagent("plasma", 5))
-
- rigged = 1
-
- S.reagents.clear_reagents()
- else
- ..()
- return
-
-// called after an attack with a light item
-// shatter light, unless it was an attempt to put it in a light socket
-// now only shatter if the intent was harm
-
-/obj/item/weapon/light/afterattack(atom/target, mob/user,proximity)
- if(!proximity) return
- if(istype(target, /obj/machinery/light))
- return
- if(user.a_intent != "harm")
- return
-
- shatter()
-
-/obj/item/weapon/light/proc/shatter()
- if(status == LIGHT_OK || status == LIGHT_BURNED)
- src.visible_message("\red [name] shatters.","\red You hear a small glass object shatter.")
- status = LIGHT_BROKEN
- force = 5
- playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
- update()
+// The lighting system
+//
+// consists of light fixtures (/obj/machinery/light) and light tube/bulb items (/obj/item/weapon/light)
+
+
+// status values shared between lighting fixtures and items
+#define LIGHT_OK 0
+#define LIGHT_EMPTY 1
+#define LIGHT_BROKEN 2
+#define LIGHT_BURNED 3
+
+
+
+/obj/item/light_fixture_frame
+ name = "light fixture frame"
+ desc = "Used for building lights."
+ icon = 'icons/obj/lighting.dmi'
+ icon_state = "tube-construct-item"
+ flags = CONDUCT
+ var/fixture_type = "tube"
+ var/obj/machinery/light/newlight = null
+ var/sheets_refunded = 2
+
+/obj/item/light_fixture_frame/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if (istype(W, /obj/item/weapon/wrench))
+ new /obj/item/stack/sheet/metal( get_turf(src.loc), sheets_refunded )
+ del(src)
+ return
+ ..()
+
+/obj/item/light_fixture_frame/proc/try_build(turf/on_wall)
+ if (get_dist(on_wall,usr)>1)
+ return
+ var/ndir = get_dir(usr,on_wall)
+ if (!(ndir in cardinal))
+ return
+ var/turf/loc = get_turf(usr)
+ if (!istype(loc, /turf/simulated/floor))
+ usr << "\red [src.name] cannot be placed on this spot."
+ return
+ usr << "Attaching [src] to the wall."
+ playsound(src.loc, 'sound/machines/click.ogg', 75, 1)
+ var/constrdir = usr.dir
+ var/constrloc = usr.loc
+ if (!do_after(usr, 30))
+ return
+ switch(fixture_type)
+ if("bulb")
+ newlight = new /obj/machinery/light_construct/small(constrloc)
+ if("tube")
+ newlight = new /obj/machinery/light_construct(constrloc)
+ newlight.dir = constrdir
+ newlight.fingerprints = src.fingerprints
+ newlight.fingerprintshidden = src.fingerprintshidden
+ newlight.fingerprintslast = src.fingerprintslast
+
+ usr.visible_message("[usr.name] attaches [src] to the wall.", \
+ "You attach [src] to the wall.")
+ del(src)
+
+/obj/item/light_fixture_frame/small
+ name = "small light fixture frame"
+ desc = "Used for building small lights."
+ icon = 'icons/obj/lighting.dmi'
+ icon_state = "bulb-construct-item"
+ flags = CONDUCT
+ fixture_type = "bulb"
+ sheets_refunded = 1
+
+/obj/machinery/light_construct
+ name = "light fixture frame"
+ desc = "A light fixture under construction."
+ icon = 'icons/obj/lighting.dmi'
+ icon_state = "tube-construct-stage1"
+ anchored = 1
+ layer = 5
+ var/stage = 1
+ var/fixture_type = "tube"
+ var/sheets_refunded = 2
+ var/obj/machinery/light/newlight = null
+
+/obj/machinery/light_construct/New()
+ ..()
+ if (fixture_type == "bulb")
+ icon_state = "bulb-construct-stage1"
+
+/obj/machinery/light_construct/examine()
+ set src in view()
+ ..()
+ if (!(usr in view(2))) return
+ switch(src.stage)
+ if(1)
+ usr << "It's an empty frame."
+ return
+ if(2)
+ usr << "It's wired."
+ return
+ if(3)
+ usr << "The casing is closed."
+ return
+
+/obj/machinery/light_construct/attackby(obj/item/weapon/W as obj, mob/user as mob)
+ src.add_fingerprint(user)
+ if (istype(W, /obj/item/weapon/wrench))
+ if (src.stage == 1)
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
+ usr << "You begin deconstructing [src]."
+ if (!do_after(usr, 30))
+ return
+ new /obj/item/stack/sheet/metal( get_turf(src.loc), sheets_refunded )
+ user.visible_message("[user.name] deconstructs [src].", \
+ "You deconstruct [src].", "You hear a noise.")
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 75, 1)
+ del(src)
+ if (src.stage == 2)
+ usr << "You have to remove the wires first."
+ return
+
+ if (src.stage == 3)
+ usr << "You have to unscrew the case first."
+ return
+
+ if(istype(W, /obj/item/weapon/wirecutters))
+ if (src.stage != 2) return
+ src.stage = 1
+ switch(fixture_type)
+ if ("tube")
+ src.icon_state = "tube-construct-stage1"
+ if("bulb")
+ src.icon_state = "bulb-construct-stage1"
+ new /obj/item/stack/cable_coil(get_turf(src.loc), 1, "red")
+ user.visible_message("[user.name] removes the wiring from [src].", \
+ "You remove the wiring from [src].", "You hear a noise.")
+ playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
+ return
+
+ if(istype(W, /obj/item/stack/cable_coil))
+ if (src.stage != 1) return
+ var/obj/item/stack/cable_coil/coil = W
+ coil.use(1)
+ switch(fixture_type)
+ if ("tube")
+ src.icon_state = "tube-construct-stage2"
+ if("bulb")
+ src.icon_state = "bulb-construct-stage2"
+ src.stage = 2
+ user.visible_message("[user.name] adds wires to [src].", \
+ "You add wires to [src].")
+ return
+
+ if(istype(W, /obj/item/weapon/screwdriver))
+ if (src.stage == 2)
+ switch(fixture_type)
+ if ("tube")
+ src.icon_state = "tube-empty"
+ if("bulb")
+ src.icon_state = "bulb-empty"
+ src.stage = 3
+ user.visible_message("[user.name] closes [src]'s casing.", \
+ "You close [src]'s casing.", "You hear a noise.")
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 75, 1)
+
+ switch(fixture_type)
+
+ if("tube")
+ newlight = new /obj/machinery/light/built(src.loc)
+ if ("bulb")
+ newlight = new /obj/machinery/light/small/built(src.loc)
+
+ newlight.dir = src.dir
+ src.transfer_fingerprints_to(newlight)
+ del(src)
+ return
+ ..()
+
+/obj/machinery/light_construct/small
+ name = "small light fixture frame"
+ desc = "A small light fixture under construction."
+ icon = 'icons/obj/lighting.dmi'
+ icon_state = "bulb-construct-stage1"
+ anchored = 1
+ layer = 5
+ stage = 1
+ fixture_type = "bulb"
+ sheets_refunded = 1
+
+// the standard tube light fixture
+/obj/machinery/light
+ name = "light fixture"
+ icon = 'icons/obj/lighting.dmi'
+ var/base_state = "tube" // base description and icon_state
+ icon_state = "tube1"
+ desc = "A lighting fixture."
+ anchored = 1
+ layer = 5 // They were appearing under mobs which is a little weird - Ostaf
+ use_power = 2
+ idle_power_usage = 2
+ active_power_usage = 20
+ power_channel = LIGHT //Lights are calc'd via area so they dont need to be in the machine list
+ var/on = 0 // 1 if on, 0 if off
+ var/on_gs = 0
+ var/brightness = 8 // luminosity when on, also used in power calculation
+ var/status = LIGHT_OK // LIGHT_OK, _EMPTY, _BURNED or _BROKEN
+ var/flickering = 0
+ var/light_type = /obj/item/weapon/light/tube // the type of light item
+ var/fitting = "tube"
+ var/switchcount = 0 // count of number of times switched on/off
+ // this is used to calc the probability the light burns out
+
+ var/rigged = 0 // true if rigged to explode
+
+// the smaller bulb light fixture
+
+/obj/machinery/light/small
+ icon_state = "bulb1"
+ base_state = "bulb"
+ fitting = "bulb"
+ brightness = 4
+ desc = "A small lighting fixture."
+ light_type = /obj/item/weapon/light/bulb
+
+
+/obj/machinery/light/Move()
+ if(status != LIGHT_BROKEN) broken(1)
+ return ..()
+
+/obj/machinery/light/built/New()
+ status = LIGHT_EMPTY
+ update(0)
+ ..()
+
+/obj/machinery/light/small/built/New()
+ status = LIGHT_EMPTY
+ update(0)
+ ..()
+
+
+// create a new lighting fixture
+/obj/machinery/light/New()
+ ..()
+ spawn(2)
+ switch(fitting)
+ if("tube")
+ brightness = 8
+ if(prob(2))
+ broken(1)
+ if("bulb")
+ brightness = 4
+ if(prob(5))
+ broken(1)
+ spawn(1)
+ update(0)
+
+/obj/machinery/light/Del()
+ var/area/A = get_area(src)
+ if(A)
+ on = 0
+// A.update_lights()
+ ..()
+
+/obj/machinery/light/update_icon()
+
+ switch(status) // set icon_states
+ if(LIGHT_OK)
+ icon_state = "[base_state][on]"
+ if(LIGHT_EMPTY)
+ icon_state = "[base_state]-empty"
+ on = 0
+ if(LIGHT_BURNED)
+ icon_state = "[base_state]-burned"
+ on = 0
+ if(LIGHT_BROKEN)
+ icon_state = "[base_state]-broken"
+ on = 0
+ return
+
+// update the icon_state and luminosity of the light depending on its state
+/obj/machinery/light/proc/update(var/trigger = 1)
+
+ update_icon()
+ if(on)
+ if(luminosity != brightness)
+ switchcount++
+ if(rigged)
+ if(status == LIGHT_OK && trigger)
+ explode()
+ else if( prob( min(60, switchcount*switchcount*0.01) ) )
+ if(status == LIGHT_OK && trigger)
+ status = LIGHT_BURNED
+ icon_state = "[base_state]-burned"
+ on = 0
+ SetLuminosity(0)
+ else
+ use_power = 2
+ SetLuminosity(brightness)
+ else
+ use_power = 1
+ SetLuminosity(0)
+
+ active_power_usage = (luminosity * 10)
+ if(on != on_gs)
+ on_gs = on
+
+
+// attempt to set the light's on/off status
+// will not switch on if broken/burned/empty
+/obj/machinery/light/proc/seton(var/s)
+ on = (s && status == LIGHT_OK)
+ update()
+
+// examine verb
+/obj/machinery/light/examine()
+ set src in oview(1)
+ ..()
+ if(usr && !usr.stat)
+ switch(status)
+ if(LIGHT_OK)
+ usr << "It is turned [on? "on" : "off"]."
+ if(LIGHT_EMPTY)
+ usr << "The [fitting] has been removed."
+ if(LIGHT_BURNED)
+ usr << "The [fitting] is burnt out."
+ if(LIGHT_BROKEN)
+ usr << "The [fitting] has been smashed."
+
+
+
+// attack with item - insert light (if right type), otherwise try to break the light
+
+/obj/machinery/light/attackby(obj/item/W, mob/user)
+
+ //Light replacer code
+ if(istype(W, /obj/item/device/lightreplacer))
+ var/obj/item/device/lightreplacer/LR = W
+ if(isliving(user))
+ var/mob/living/U = user
+ LR.ReplaceLight(src, U)
+ return
+
+ // attempt to insert light
+ if(istype(W, /obj/item/weapon/light))
+ if(status != LIGHT_EMPTY)
+ user << "There is a [fitting] already inserted."
+ return
+ else
+ src.add_fingerprint(user)
+ var/obj/item/weapon/light/L = W
+ if(istype(L, light_type))
+ status = L.status
+ user << "You insert the [L.name]."
+ switchcount = L.switchcount
+ rigged = L.rigged
+ brightness = L.brightness
+ on = has_power()
+ update()
+
+ user.drop_item() //drop the item to update overlays and such
+ del(L)
+
+ if(on && rigged)
+ explode()
+ else
+ user << "This type of light requires a [fitting]."
+ return
+
+ // attempt to break the light
+ //If xenos decide they want to smash a light bulb with a toolbox, who am I to stop them? /N
+
+ else if(status != LIGHT_BROKEN && status != LIGHT_EMPTY)
+
+
+ if(prob(1+W.force * 5))
+
+ user << "You hit the light, and it smashes!"
+ for(var/mob/M in viewers(src))
+ if(M == user)
+ continue
+ M.show_message("[user.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2)
+ if(on && (W.flags & CONDUCT))
+ //if(!user.mutations & COLD_RESISTANCE)
+ if (prob(12))
+ electrocute_mob(user, get_area(src), src, 0.3)
+ broken()
+
+ else
+ user << "You hit the light!"
+
+ // attempt to stick weapon into light socket
+ else if(status == LIGHT_EMPTY)
+ if(istype(W, /obj/item/weapon/screwdriver)) //If it's a screwdriver open it.
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 75, 1)
+ user.visible_message("[user.name] opens [src]'s casing.", \
+ "You open [src]'s casing.", "You hear a noise.")
+ var/obj/machinery/light_construct/newlight = null
+ switch(fitting)
+ if("tube")
+ newlight = new /obj/machinery/light_construct(src.loc)
+ newlight.icon_state = "tube-construct-stage2"
+
+ if("bulb")
+ newlight = new /obj/machinery/light_construct/small(src.loc)
+ newlight.icon_state = "bulb-construct-stage2"
+ newlight.dir = src.dir
+ newlight.stage = 2
+ newlight.fingerprints = src.fingerprints
+ newlight.fingerprintshidden = src.fingerprintshidden
+ newlight.fingerprintslast = src.fingerprintslast
+ del(src)
+ return
+
+ user << "You stick \the [W] into the light socket!"
+ if(has_power() && (W.flags & CONDUCT))
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(3, 1, src)
+ s.start()
+ //if(!user.mutations & COLD_RESISTANCE)
+ if (prob(75))
+ electrocute_mob(user, get_area(src), src, rand(0.7,1.0))
+
+
+// returns whether this light has power
+// true if area has power and lightswitch is on
+/obj/machinery/light/proc/has_power()
+ var/area/A = src.loc.loc
+ return A.master.lightswitch && A.master.power_light
+
+/obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
+ if(flickering) return
+ flickering = 1
+ spawn(0)
+ if(on && status == LIGHT_OK)
+ for(var/i = 0; i < amount; i++)
+ if(status != LIGHT_OK) break
+ on = !on
+ update(0)
+ sleep(rand(5, 15))
+ on = (status == LIGHT_OK)
+ update(0)
+ flickering = 0
+
+// ai attack - make lights flicker, because why not
+
+/obj/machinery/light/attack_ai(mob/user)
+ src.flicker(1)
+ return
+
+// Aliens smash the bulb but do not get electrocuted./N
+/obj/machinery/light/attack_alien(mob/living/carbon/alien/humanoid/user)//So larva don't go breaking light bulbs.
+ if(status == LIGHT_EMPTY||status == LIGHT_BROKEN)
+ user << "\green That object is useless to you."
+ return
+ else if (status == LIGHT_OK||status == LIGHT_BURNED)
+ for(var/mob/M in viewers(src))
+ M.show_message("\red [user.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2)
+ broken()
+ return
+
+/obj/machinery/light/attack_animal(mob/living/simple_animal/M)
+ if(M.melee_damage_upper == 0) return
+ if(status == LIGHT_EMPTY||status == LIGHT_BROKEN)
+ M << "\red That object is useless to you."
+ return
+ else if (status == LIGHT_OK||status == LIGHT_BURNED)
+ for(var/mob/O in viewers(src))
+ O.show_message("\red [M.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2)
+ broken()
+ return
+// attack with hand - remove tube/bulb
+// if hands aren't protected and the light is on, burn the player
+
+/obj/machinery/light/attack_hand(mob/user)
+
+ add_fingerprint(user)
+
+ if(status == LIGHT_EMPTY)
+ user << "There is no [fitting] in this light."
+ return
+
+ // make it burn hands if not wearing fire-insulated gloves
+ if(on)
+ var/prot = 0
+ var/mob/living/carbon/human/H = user
+
+ if(istype(H))
+
+ if(H.gloves)
+ var/obj/item/clothing/gloves/G = H.gloves
+ if(G.max_heat_protection_temperature)
+ prot = (G.max_heat_protection_temperature > 360)
+ else
+ prot = 1
+
+ if(prot > 0 || (COLD_RESISTANCE in user.mutations))
+ user << "You remove the light [fitting]"
+ else if(TK in user.mutations)
+ user << "You telekinetically remove the light [fitting]."
+ else
+ user << "You try to remove the light [fitting], but you burn your hand on it!"
+
+ var/obj/item/organ/limb/affecting = H.get_organ("[user.hand ? "l" : "r" ]_arm")
+ if(affecting.take_damage( 0, 5 )) // 5 burn damage
+ H.update_damage_overlays(0)
+ H.updatehealth()
+ return // if burned, don't remove the light
+ else
+ user << "You remove the light [fitting]."
+ // create a light tube/bulb item and put it in the user's hand
+ var/obj/item/weapon/light/L = new light_type()
+ L.status = status
+ L.rigged = rigged
+ L.brightness = brightness
+
+ // light item inherits the switchcount, then zero it
+ L.switchcount = switchcount
+ switchcount = 0
+
+ L.update()
+ L.add_fingerprint(user)
+ L.loc = loc
+
+ user.put_in_active_hand(L) //puts it in our active hand
+
+ status = LIGHT_EMPTY
+ update()
+
+/obj/machinery/light/attack_tk(mob/user)
+ if(status == LIGHT_EMPTY)
+ user << "There is no [fitting] in this light."
+ return
+
+ user << "You telekinetically remove the light [fitting]."
+ // create a light tube/bulb item and put it in the user's hand
+ var/obj/item/weapon/light/L = new light_type()
+ L.status = status
+ L.rigged = rigged
+ L.brightness = brightness
+
+ // light item inherits the switchcount, then zero it
+ L.switchcount = switchcount
+ switchcount = 0
+
+ L.update()
+ L.add_fingerprint(user)
+ L.loc = loc
+
+ status = LIGHT_EMPTY
+ update()
+
+// break the light and make sparks if was on
+
+/obj/machinery/light/proc/broken(var/skip_sound_and_sparks = 0)
+ if(status == LIGHT_EMPTY)
+ return
+
+ if(!skip_sound_and_sparks)
+ if(status == LIGHT_OK || status == LIGHT_BURNED)
+ playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
+ if(on)
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(3, 1, src)
+ s.start()
+ status = LIGHT_BROKEN
+ update()
+
+/obj/machinery/light/proc/fix()
+ if(status == LIGHT_OK)
+ return
+ status = LIGHT_OK
+ brightness = initial(brightness)
+ on = 1
+ update()
+
+// explosion effect
+// destroy the whole light fixture or just shatter it
+
+/obj/machinery/light/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ del(src)
+ return
+ if(2.0)
+ if (prob(75))
+ broken()
+ if(3.0)
+ if (prob(50))
+ broken()
+ return
+
+//blob effect
+
+/obj/machinery/light/blob_act()
+ if(prob(75))
+ broken()
+
+
+// timed process
+// use power
+
+#define LIGHTING_POWER_FACTOR 20 //20W per unit luminosity
+
+/obj/machinery/light/process()//TODO: remove/add this from machines to save on processing as needed ~Carn PRIORITY
+ if(on)
+ use_power(luminosity * LIGHTING_POWER_FACTOR, LIGHT)
+
+// called when area power state changes
+/obj/machinery/light/power_change()
+ spawn(10)
+ var/area/A = src.loc.loc
+ A = A.master
+ seton(A.lightswitch && A.power_light)
+
+// called when on fire
+
+/obj/machinery/light/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ if(prob(max(0, exposed_temperature - 673))) //0% at <400C, 100% at >500C
+ broken()
+
+// explode the light
+
+/obj/machinery/light/proc/explode()
+ var/turf/T = get_turf(src.loc)
+ spawn(0)
+ broken() // break it first to give a warning
+ sleep(2)
+ explosion(T, 0, 0, 2, 2)
+ sleep(1)
+ del(src)
+
+// the light item
+// can be tube or bulb subtypes
+// will fit into empty /obj/machinery/light of the corresponding type
+
+/obj/item/weapon/light
+ icon = 'icons/obj/lighting.dmi'
+ force = 2
+ throwforce = 5
+ w_class = 1
+ var/status = 0 // LIGHT_OK, LIGHT_BURNED or LIGHT_BROKEN
+ var/base_state
+ var/switchcount = 0 // number of times switched
+ m_amt = 60
+ var/rigged = 0 // true if rigged to explode
+ var/brightness = 2 //how much light it gives off
+
+/obj/item/weapon/light/tube
+ name = "light tube"
+ desc = "A replacement light tube."
+ icon_state = "ltube"
+ base_state = "ltube"
+ item_state = "c_tube"
+ g_amt = 100
+ brightness = 8
+
+/obj/item/weapon/light/tube/large
+ w_class = 2
+ name = "large light tube"
+ brightness = 15
+
+/obj/item/weapon/light/bulb
+ name = "light bulb"
+ desc = "A replacement light bulb."
+ icon_state = "lbulb"
+ base_state = "lbulb"
+ item_state = "contvapour"
+ g_amt = 100
+ brightness = 5
+
+/obj/item/weapon/light/throw_impact(atom/hit_atom)
+ ..()
+ shatter()
+
+/obj/item/weapon/light/bulb/fire
+ name = "fire bulb"
+ desc = "A replacement fire bulb."
+ icon_state = "fbulb"
+ base_state = "fbulb"
+ item_state = "egg4"
+ g_amt = 100
+ brightness = 5
+
+// update the icon state and description of the light
+
+/obj/item/weapon/light/proc/update()
+ switch(status)
+ if(LIGHT_OK)
+ icon_state = base_state
+ desc = "A replacement [name]."
+ if(LIGHT_BURNED)
+ icon_state = "[base_state]-burned"
+ desc = "A burnt-out [name]."
+ if(LIGHT_BROKEN)
+ icon_state = "[base_state]-broken"
+ desc = "A broken [name]."
+
+
+/obj/item/weapon/light/New()
+ ..()
+ switch(name)
+ if("light tube")
+ brightness = rand(6,9)
+ if("light bulb")
+ brightness = rand(4,6)
+ update()
+
+
+// attack bulb/tube with object
+// if a syringe, can inject plasma to make it explode
+/obj/item/weapon/light/attackby(var/obj/item/I, var/mob/user)
+ ..()
+ if(istype(I, /obj/item/weapon/reagent_containers/syringe))
+ var/obj/item/weapon/reagent_containers/syringe/S = I
+
+ user << "You inject the solution into the [src]."
+
+ if(S.reagents.has_reagent("plasma", 5))
+
+ rigged = 1
+
+ S.reagents.clear_reagents()
+ else
+ ..()
+ return
+
+// called after an attack with a light item
+// shatter light, unless it was an attempt to put it in a light socket
+// now only shatter if the intent was harm
+
+/obj/item/weapon/light/afterattack(atom/target, mob/user,proximity)
+ if(!proximity) return
+ if(istype(target, /obj/machinery/light))
+ return
+ if(user.a_intent != "harm")
+ return
+
+ shatter()
+
+/obj/item/weapon/light/proc/shatter()
+ if(status == LIGHT_OK || status == LIGHT_BURNED)
+ src.visible_message("\red [name] shatters.","\red You hear a small glass object shatter.")
+ status = LIGHT_BROKEN
+ force = 5
+ playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1)
+ update()
diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm
index 0aea0ce3db8..9ef4629d0b2 100644
--- a/code/modules/power/port_gen.dm
+++ b/code/modules/power/port_gen.dm
@@ -1,334 +1,334 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
-
-/* new portable generator - work in progress
-
-/obj/machinery/power/port_gen
- name = "portable generator"
- desc = "A portable generator used for emergency backup power."
- icon = 'generator.dmi'
- icon_state = "off"
- density = 1
- anchored = 0
- directwired = 0
- var/t_status = 0
- var/t_per = 5000
- var/filter = 1
- var/tank = null
- var/turf/inturf
- var/starter = 0
- var/rpm = 0
- var/rpmtarget = 0
- var/capacity = 1e6
- var/turf/outturf
- var/lastgen
-
-
-/obj/machinery/power/port_gen/process()
-ideally we're looking to generate 5000
-
-/obj/machinery/power/port_gen/attackby(obj/item/weapon/W, mob/user)
-tank [un]loading stuff
-
-/obj/machinery/power/port_gen/attack_hand(mob/user)
-turn on/off
-
-/obj/machinery/power/port_gen/examine()
-display round(lastgen) and plasmatank amount
-
-*/
-
-//Previous code been here forever, adding new framework for portable generators
-
-
-//Baseline portable generator. Has all the default handling. Not intended to be used on it's own (since it generates unlimited power).
-/obj/machinery/power/port_gen
- name = "portable generator"
- desc = "A portable generator for emergency backup power"
- icon = 'icons/obj/power.dmi'
- icon_state = "portgen0"
- density = 1
- anchored = 0
- directwired = 0
- use_power = 0
-
- var/active = 0
- var/power_gen = 5000
- var/recent_fault = 0
- var/power_output = 1
- var/consumption = 0
-
-/obj/machinery/power/port_gen/proc/HasFuel() //Placeholder for fuel check.
- return 1
-
-/obj/machinery/power/port_gen/proc/UseFuel() //Placeholder for fuel use.
- return
-
-/obj/machinery/power/port_gen/proc/DropFuel()
- return
-
-/obj/machinery/power/port_gen/proc/handleInactive()
- return
-
-/obj/machinery/power/port_gen/process()
- if(active && HasFuel() && !crit_fail && anchored && powernet)
- add_avail(power_gen * power_output)
- UseFuel()
- src.updateDialog()
-
- else
- active = 0
- icon_state = initial(icon_state)
- handleInactive()
-
-/obj/machinery/power/port_gen/attack_hand(mob/user as mob)
- if(..())
- return
- if(!anchored)
- return
-
-/obj/machinery/power/port_gen/examine()
- set src in oview(1)
- ..()
- if(active)
- usr << "It is running."
- else
- usr << "It isn't running."
-
-/obj/machinery/power/port_gen/pacman
- name = "\improper P.A.C.M.A.N.-type portable generator"
- var/sheets = 0
- var/max_sheets = 100
- var/sheet_name = ""
- var/sheet_path = /obj/item/stack/sheet/mineral/plasma
- var/board_path = "/obj/item/weapon/circuitboard/pacman"
- var/sheet_left = 0 // How much is left of the sheet
- var/time_per_sheet = 40
- var/heat = 0
-
-/obj/machinery/power/port_gen/pacman/initialize()
- ..()
- if(anchored)
- connect_to_network()
-
-/obj/machinery/power/port_gen/pacman/New()
- ..()
- component_parts = list()
- component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
- component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
- component_parts += new /obj/item/stack/cable_coil(src, 1)
- component_parts += new /obj/item/stack/cable_coil(src, 1)
- component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
- component_parts += new board_path(src)
- var/obj/sheet = new sheet_path(null)
- sheet_name = sheet.name
- RefreshParts()
-
-/obj/machinery/power/port_gen/pacman/Del()
- DropFuel()
- ..()
-
-/obj/machinery/power/port_gen/pacman/RefreshParts()
- var/temp_rating = 0
- var/temp_reliability = 0
- var/consumption_coeff = 0
- for(var/obj/item/weapon/stock_parts/SP in component_parts)
- if(istype(SP, /obj/item/weapon/stock_parts/matter_bin))
- max_sheets = SP.rating * SP.rating * 50
- else if(istype(SP, /obj/item/weapon/stock_parts/capacitor))
- temp_rating += SP.rating
- else
- consumption_coeff += SP.rating
- for(var/obj/item/weapon/CP in component_parts)
- temp_reliability += CP.reliability
- reliability = min(round(temp_reliability / 4), 100)
- power_gen = round(initial(power_gen) * temp_rating * 2)
- consumption = consumption_coeff
-
-/obj/machinery/power/port_gen/pacman/examine()
- ..()
- usr << "\blue The generator has [sheets] units of [sheet_name] fuel left, producing [power_gen] per cycle."
- if(crit_fail) usr << "\red The generator seems to have broken down."
-
-/obj/machinery/power/port_gen/pacman/HasFuel()
- if(sheets >= 1 / (time_per_sheet / power_output) - sheet_left)
- return 1
- return 0
-
-/obj/machinery/power/port_gen/pacman/DropFuel()
- if(sheets)
- var/fail_safe = 0
- while(sheets > 0 && fail_safe < 100)
- fail_safe += 1
- var/obj/item/stack/sheet/S = new sheet_path(loc)
- var/amount = min(sheets, S.max_amount)
- S.amount = amount
- sheets -= amount
-
-/obj/machinery/power/port_gen/pacman/UseFuel()
- var/needed_sheets = 1 / (time_per_sheet * consumption / power_output)
- var/temp = min(needed_sheets, sheet_left)
- needed_sheets -= temp
- sheet_left -= temp
- sheets -= round(needed_sheets)
- needed_sheets -= round(needed_sheets)
- if (sheet_left <= 0 && sheets > 0)
- sheet_left = 1 - needed_sheets
- sheets--
-
- var/lower_limit = 56 + power_output * 10
- var/upper_limit = 76 + power_output * 10
- var/bias = 0
- if (power_output > 4)
- upper_limit = 400
- bias = power_output - consumption * (4 - consumption)
- if (heat < lower_limit)
- heat += 4 - consumption
- else
- heat += rand(-7 + bias, 7 + bias)
- if (heat < lower_limit)
- heat = lower_limit
- if (heat > upper_limit)
- heat = upper_limit
-
- if (heat > 300)
- overheat()
- del(src)
- return
-
-/obj/machinery/power/port_gen/pacman/handleInactive()
-
- if (heat > 0)
- heat = max(heat - 2, 0)
- src.updateDialog()
-
-/obj/machinery/power/port_gen/pacman/proc/overheat()
- explosion(src.loc, 2, 5, 2, -1)
-
-/obj/machinery/power/port_gen/pacman/attackby(var/obj/item/O as obj, var/mob/user as mob)
- if(istype(O, sheet_path))
- var/obj/item/stack/addstack = O
- var/amount = min((max_sheets - sheets), addstack.amount)
- if(amount < 1)
- user << "\blue The [src.name] is full!"
- return
- user << "\blue You add [amount] sheets to the [src.name]."
- sheets += amount
- addstack.use(amount)
- updateUsrDialog()
- return
- else if (istype(O, /obj/item/weapon/card/emag))
- emagged = 1
- emp_act(1)
- else if(!active)
-
- if(istype(O, /obj/item/weapon/wrench))
-
- if(!anchored && !isinspace())
- connect_to_network()
- user << "\blue You secure the generator to the floor."
- anchored = 1
- else if(anchored)
- disconnect_from_network()
- user << "\blue You unsecure the generator from the floor."
- anchored = 0
-
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
-
- else if(istype(O, /obj/item/weapon/screwdriver))
- panel_open = !panel_open
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
- if(panel_open)
- user << "\blue You open the access panel."
- else
- user << "\blue You close the access panel."
- else if(istype(O, /obj/item/weapon/crowbar) && panel_open)
- default_deconstruction_crowbar()
-
-/obj/machinery/power/port_gen/pacman/attack_hand(mob/user as mob)
- ..()
- if (!anchored)
- return
-
- interact(user)
-
-/obj/machinery/power/port_gen/pacman/attack_ai(mob/user as mob)
- interact(user)
-
-/obj/machinery/power/port_gen/pacman/attack_paw(mob/user as mob)
- interact(user)
-
-/obj/machinery/power/port_gen/pacman/interact(mob/user)
- if (get_dist(src, user) > 1 )
- if (!istype(user, /mob/living/silicon/ai))
- user.unset_machine()
- user << browse(null, "window=port_gen")
- return
-
- user.set_machine(src)
-
- var/dat = text("[name]
")
- if (active)
- dat += text("Generator: On
")
- else
- dat += text("Generator: Off
")
- dat += text("[capitalize(sheet_name)]: [sheets] - Eject
")
- var/stack_percent = round(sheet_left * 100, 1)
- dat += text("Current stack: [stack_percent]%
")
- dat += text("Power output: - [power_gen * power_output] +
")
- dat += text("Power current: [(powernet == null ? "Unconnected" : "[avail()]")]
")
- dat += text("Heat: [heat]
")
- dat += "
Close"
- user << browse("[dat]", "window=port_gen")
- onclose(user, "port_gen")
-
-/obj/machinery/power/port_gen/pacman/Topic(href, href_list)
- if(..())
- return
-
- src.add_fingerprint(usr)
- if(href_list["action"])
- if(href_list["action"] == "enable")
- if(!active && HasFuel() && !crit_fail)
- active = 1
- icon_state = "portgen1"
- src.updateUsrDialog()
- if(href_list["action"] == "disable")
- if (active)
- active = 0
- icon_state = "portgen0"
- src.updateUsrDialog()
- if(href_list["action"] == "eject")
- if(!active)
- DropFuel()
- src.updateUsrDialog()
- if(href_list["action"] == "lower_power")
- if (power_output > 1)
- power_output--
- src.updateUsrDialog()
- if (href_list["action"] == "higher_power")
- if (power_output < 4 || emagged)
- power_output++
- src.updateUsrDialog()
- if (href_list["action"] == "close")
- usr << browse(null, "window=port_gen")
- usr.unset_machine()
-
-/obj/machinery/power/port_gen/pacman/super
- name = "\improper S.U.P.E.R.P.A.C.M.A.N.-type portable generator"
- icon_state = "portgen1"
- sheet_path = /obj/item/stack/sheet/mineral/uranium
- power_gen = 15000
- time_per_sheet = 65
- board_path = "/obj/item/weapon/circuitboard/pacman/super"
- overheat()
- explosion(src.loc, 3, 3, 3, -1)
-
-/obj/machinery/power/port_gen/pacman/mrs
- name = "\improper M.R.S.P.A.C.M.A.N.-type portable generator"
- icon_state = "portgen2"
- sheet_path = /obj/item/stack/sheet/mineral/diamond
- power_gen = 40000
- time_per_sheet = 80
- board_path = "/obj/item/weapon/circuitboard/pacman/mrs"
- overheat()
- explosion(src.loc, 4, 4, 4, -1)
+//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
+
+/* new portable generator - work in progress
+
+/obj/machinery/power/port_gen
+ name = "portable generator"
+ desc = "A portable generator used for emergency backup power."
+ icon = 'generator.dmi'
+ icon_state = "off"
+ density = 1
+ anchored = 0
+ directwired = 0
+ var/t_status = 0
+ var/t_per = 5000
+ var/filter = 1
+ var/tank = null
+ var/turf/inturf
+ var/starter = 0
+ var/rpm = 0
+ var/rpmtarget = 0
+ var/capacity = 1e6
+ var/turf/outturf
+ var/lastgen
+
+
+/obj/machinery/power/port_gen/process()
+ideally we're looking to generate 5000
+
+/obj/machinery/power/port_gen/attackby(obj/item/weapon/W, mob/user)
+tank [un]loading stuff
+
+/obj/machinery/power/port_gen/attack_hand(mob/user)
+turn on/off
+
+/obj/machinery/power/port_gen/examine()
+display round(lastgen) and plasmatank amount
+
+*/
+
+//Previous code been here forever, adding new framework for portable generators
+
+
+//Baseline portable generator. Has all the default handling. Not intended to be used on it's own (since it generates unlimited power).
+/obj/machinery/power/port_gen
+ name = "portable generator"
+ desc = "A portable generator for emergency backup power"
+ icon = 'icons/obj/power.dmi'
+ icon_state = "portgen0"
+ density = 1
+ anchored = 0
+ directwired = 0
+ use_power = 0
+
+ var/active = 0
+ var/power_gen = 5000
+ var/recent_fault = 0
+ var/power_output = 1
+ var/consumption = 0
+
+/obj/machinery/power/port_gen/proc/HasFuel() //Placeholder for fuel check.
+ return 1
+
+/obj/machinery/power/port_gen/proc/UseFuel() //Placeholder for fuel use.
+ return
+
+/obj/machinery/power/port_gen/proc/DropFuel()
+ return
+
+/obj/machinery/power/port_gen/proc/handleInactive()
+ return
+
+/obj/machinery/power/port_gen/process()
+ if(active && HasFuel() && !crit_fail && anchored && powernet)
+ add_avail(power_gen * power_output)
+ UseFuel()
+ src.updateDialog()
+
+ else
+ active = 0
+ icon_state = initial(icon_state)
+ handleInactive()
+
+/obj/machinery/power/port_gen/attack_hand(mob/user as mob)
+ if(..())
+ return
+ if(!anchored)
+ return
+
+/obj/machinery/power/port_gen/examine()
+ set src in oview(1)
+ ..()
+ if(active)
+ usr << "It is running."
+ else
+ usr << "It isn't running."
+
+/obj/machinery/power/port_gen/pacman
+ name = "\improper P.A.C.M.A.N.-type portable generator"
+ var/sheets = 0
+ var/max_sheets = 100
+ var/sheet_name = ""
+ var/sheet_path = /obj/item/stack/sheet/mineral/plasma
+ var/board_path = "/obj/item/weapon/circuitboard/pacman"
+ var/sheet_left = 0 // How much is left of the sheet
+ var/time_per_sheet = 40
+ var/heat = 0
+
+/obj/machinery/power/port_gen/pacman/initialize()
+ ..()
+ if(anchored)
+ connect_to_network()
+
+/obj/machinery/power/port_gen/pacman/New()
+ ..()
+ component_parts = list()
+ component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
+ component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
+ component_parts += new /obj/item/stack/cable_coil(src, 1)
+ component_parts += new /obj/item/stack/cable_coil(src, 1)
+ component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
+ component_parts += new board_path(src)
+ var/obj/sheet = new sheet_path(null)
+ sheet_name = sheet.name
+ RefreshParts()
+
+/obj/machinery/power/port_gen/pacman/Del()
+ DropFuel()
+ ..()
+
+/obj/machinery/power/port_gen/pacman/RefreshParts()
+ var/temp_rating = 0
+ var/temp_reliability = 0
+ var/consumption_coeff = 0
+ for(var/obj/item/weapon/stock_parts/SP in component_parts)
+ if(istype(SP, /obj/item/weapon/stock_parts/matter_bin))
+ max_sheets = SP.rating * SP.rating * 50
+ else if(istype(SP, /obj/item/weapon/stock_parts/capacitor))
+ temp_rating += SP.rating
+ else
+ consumption_coeff += SP.rating
+ for(var/obj/item/weapon/CP in component_parts)
+ temp_reliability += CP.reliability
+ reliability = min(round(temp_reliability / 4), 100)
+ power_gen = round(initial(power_gen) * temp_rating * 2)
+ consumption = consumption_coeff
+
+/obj/machinery/power/port_gen/pacman/examine()
+ ..()
+ usr << "\blue The generator has [sheets] units of [sheet_name] fuel left, producing [power_gen] per cycle."
+ if(crit_fail) usr << "\red The generator seems to have broken down."
+
+/obj/machinery/power/port_gen/pacman/HasFuel()
+ if(sheets >= 1 / (time_per_sheet / power_output) - sheet_left)
+ return 1
+ return 0
+
+/obj/machinery/power/port_gen/pacman/DropFuel()
+ if(sheets)
+ var/fail_safe = 0
+ while(sheets > 0 && fail_safe < 100)
+ fail_safe += 1
+ var/obj/item/stack/sheet/S = new sheet_path(loc)
+ var/amount = min(sheets, S.max_amount)
+ S.amount = amount
+ sheets -= amount
+
+/obj/machinery/power/port_gen/pacman/UseFuel()
+ var/needed_sheets = 1 / (time_per_sheet * consumption / power_output)
+ var/temp = min(needed_sheets, sheet_left)
+ needed_sheets -= temp
+ sheet_left -= temp
+ sheets -= round(needed_sheets)
+ needed_sheets -= round(needed_sheets)
+ if (sheet_left <= 0 && sheets > 0)
+ sheet_left = 1 - needed_sheets
+ sheets--
+
+ var/lower_limit = 56 + power_output * 10
+ var/upper_limit = 76 + power_output * 10
+ var/bias = 0
+ if (power_output > 4)
+ upper_limit = 400
+ bias = power_output - consumption * (4 - consumption)
+ if (heat < lower_limit)
+ heat += 4 - consumption
+ else
+ heat += rand(-7 + bias, 7 + bias)
+ if (heat < lower_limit)
+ heat = lower_limit
+ if (heat > upper_limit)
+ heat = upper_limit
+
+ if (heat > 300)
+ overheat()
+ del(src)
+ return
+
+/obj/machinery/power/port_gen/pacman/handleInactive()
+
+ if (heat > 0)
+ heat = max(heat - 2, 0)
+ src.updateDialog()
+
+/obj/machinery/power/port_gen/pacman/proc/overheat()
+ explosion(src.loc, 2, 5, 2, -1)
+
+/obj/machinery/power/port_gen/pacman/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(istype(O, sheet_path))
+ var/obj/item/stack/addstack = O
+ var/amount = min((max_sheets - sheets), addstack.amount)
+ if(amount < 1)
+ user << "\blue The [src.name] is full!"
+ return
+ user << "\blue You add [amount] sheets to the [src.name]."
+ sheets += amount
+ addstack.use(amount)
+ updateUsrDialog()
+ return
+ else if (istype(O, /obj/item/weapon/card/emag))
+ emagged = 1
+ emp_act(1)
+ else if(!active)
+
+ if(istype(O, /obj/item/weapon/wrench))
+
+ if(!anchored && !isinspace())
+ connect_to_network()
+ user << "\blue You secure the generator to the floor."
+ anchored = 1
+ else if(anchored)
+ disconnect_from_network()
+ user << "\blue You unsecure the generator from the floor."
+ anchored = 0
+
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+
+ else if(istype(O, /obj/item/weapon/screwdriver))
+ panel_open = !panel_open
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ if(panel_open)
+ user << "\blue You open the access panel."
+ else
+ user << "\blue You close the access panel."
+ else if(istype(O, /obj/item/weapon/crowbar) && panel_open)
+ default_deconstruction_crowbar()
+
+/obj/machinery/power/port_gen/pacman/attack_hand(mob/user as mob)
+ ..()
+ if (!anchored)
+ return
+
+ interact(user)
+
+/obj/machinery/power/port_gen/pacman/attack_ai(mob/user as mob)
+ interact(user)
+
+/obj/machinery/power/port_gen/pacman/attack_paw(mob/user as mob)
+ interact(user)
+
+/obj/machinery/power/port_gen/pacman/interact(mob/user)
+ if (get_dist(src, user) > 1 )
+ if (!istype(user, /mob/living/silicon/ai))
+ user.unset_machine()
+ user << browse(null, "window=port_gen")
+ return
+
+ user.set_machine(src)
+
+ var/dat = text("[name]
")
+ if (active)
+ dat += text("Generator: On
")
+ else
+ dat += text("Generator: Off
")
+ dat += text("[capitalize(sheet_name)]: [sheets] - Eject
")
+ var/stack_percent = round(sheet_left * 100, 1)
+ dat += text("Current stack: [stack_percent]%
")
+ dat += text("Power output: - [power_gen * power_output] +
")
+ dat += text("Power current: [(powernet == null ? "Unconnected" : "[avail()]")]
")
+ dat += text("Heat: [heat]
")
+ dat += "
Close"
+ user << browse("[dat]", "window=port_gen")
+ onclose(user, "port_gen")
+
+/obj/machinery/power/port_gen/pacman/Topic(href, href_list)
+ if(..())
+ return
+
+ src.add_fingerprint(usr)
+ if(href_list["action"])
+ if(href_list["action"] == "enable")
+ if(!active && HasFuel() && !crit_fail)
+ active = 1
+ icon_state = "portgen1"
+ src.updateUsrDialog()
+ if(href_list["action"] == "disable")
+ if (active)
+ active = 0
+ icon_state = "portgen0"
+ src.updateUsrDialog()
+ if(href_list["action"] == "eject")
+ if(!active)
+ DropFuel()
+ src.updateUsrDialog()
+ if(href_list["action"] == "lower_power")
+ if (power_output > 1)
+ power_output--
+ src.updateUsrDialog()
+ if (href_list["action"] == "higher_power")
+ if (power_output < 4 || emagged)
+ power_output++
+ src.updateUsrDialog()
+ if (href_list["action"] == "close")
+ usr << browse(null, "window=port_gen")
+ usr.unset_machine()
+
+/obj/machinery/power/port_gen/pacman/super
+ name = "\improper S.U.P.E.R.P.A.C.M.A.N.-type portable generator"
+ icon_state = "portgen1"
+ sheet_path = /obj/item/stack/sheet/mineral/uranium
+ power_gen = 15000
+ time_per_sheet = 65
+ board_path = "/obj/item/weapon/circuitboard/pacman/super"
+ overheat()
+ explosion(src.loc, 3, 3, 3, -1)
+
+/obj/machinery/power/port_gen/pacman/mrs
+ name = "\improper M.R.S.P.A.C.M.A.N.-type portable generator"
+ icon_state = "portgen2"
+ sheet_path = /obj/item/stack/sheet/mineral/diamond
+ power_gen = 40000
+ time_per_sheet = 80
+ board_path = "/obj/item/weapon/circuitboard/pacman/mrs"
+ overheat()
+ explosion(src.loc, 4, 4, 4, -1)
diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
index ce6278a2675..65de436a9d7 100644
--- a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
+++ b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
@@ -1,416 +1,416 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
-
-/*Composed of 7 parts
-3 Particle emitters
-proc
-emit_particle()
-
-1 power box
-the only part of this thing that uses power, can hack to mess with the pa/make it better
-
-1 fuel chamber
-contains procs for mixing gas and whatever other fuel it uses
-mix_gas()
-
-1 gas holder WIP
-acts like a tank valve on the ground that you wrench gas tanks onto
-proc
-extract_gas()
-return_gas()
-attach_tank()
-remove_tank()
-get_available_mix()
-
-1 End Cap
-
-1 Control computer
-interface for the pa, acts like a computer with an html menu for diff parts and a status report
-all other parts contain only a ref to this
-a /machine/, tells the others to do work
-contains ref for all parts
-proc
-process()
-check_build()
-
-Setup map
- |EC|
-CC|FC|
- |PB|
-PE|PE|PE
-
-
-Icon Addemdum
-Icon system is much more robust, and the icons are all variable based.
-Each part has a reference string, powered, strength, and contruction values.
-Using this the update_icon() proc is simplified a bit (using for absolutely was problematic with naming),
-so the icon_state comes out be:
-"[reference][strength]", with a switch controlling construction_states and ensuring that it doesn't
-power on while being contructed, and all these variables are set by the computer through it's scan list
-Essential order of the icons:
-Standard - [reference]
-Wrenched - [reference]
-Wired - [reference]w
-Closed - [reference]c
-Powered - [reference]p[strength]
-Strength being set by the computer and a null strength (Computer is powered off or inactive) returns a 'null', counting as empty
-So, hopefully this is helpful if any more icons are to be added/changed/wondering what the hell is going on here
-
-*/
-
-/obj/structure/particle_accelerator
- name = "Particle Accelerator"
- desc = "Part of a Particle Accelerator."
- icon = 'icons/obj/machines/particle_accelerator.dmi'
- icon_state = "none"
- anchored = 0
- density = 1
- var/obj/machinery/particle_accelerator/control_box/master = null
- var/construction_state = 0
- var/reference = null
- var/powered = 0
- var/strength = null
- var/desc_holder = null
-
-/obj/structure/particle_accelerator/Del()
- construction_state = 0
- if(master)
- master.part_scan()
- ..()
-
-/obj/structure/particle_accelerator/end_cap
- name = "Alpha Particle Generation Array"
- desc_holder = "This is where Alpha particles are generated from \[REDACTED\]"
- icon_state = "end_cap"
- reference = "end_cap"
-
-/obj/structure/particle_accelerator/update_icon()
- ..()
- return
-
-
-/obj/structure/particle_accelerator/verb/rotate()
- set name = "Rotate Clockwise"
- set category = "Object"
- set src in oview(1)
-
- if (src.anchored || usr:stat)
- usr << "It is fastened to the floor!"
- return 0
- src.dir = turn(src.dir, 270)
- return 1
-
-/obj/structure/particle_accelerator/verb/rotateccw()
- set name = "Rotate Counter Clockwise"
- set category = "Object"
- set src in oview(1)
-
- if (src.anchored || usr:stat)
- usr << "It is fastened to the floor!"
- return 0
- src.dir = turn(src.dir, 90)
- return 1
-
-/obj/structure/particle_accelerator/examine()
- switch(src.construction_state)
- if(0)
- src.desc = text("A [name], looks like it's not attached to the flooring")
- if(1)
- src.desc = text("A [name], it is missing some cables")
- if(2)
- src.desc = text("A [name], the panel is open")
- if(3)
- src.desc = text("The [name] is assembled")
- if(powered)
- src.desc = src.desc_holder
- ..()
- return
-
-
-/obj/structure/particle_accelerator/attackby(obj/item/W, mob/user)
- if(istool(W))
- if(src.process_tool_hit(W,user))
- return
- ..()
- return
-
-
-/obj/structure/particle_accelerator/Move()
- ..()
- if(master && master.active)
- master.toggle_power()
- investigate_log("was moved whilst active; it powered down.","singulo")
-
-/obj/structure/particle_accelerator/ex_act(severity)
- switch(severity)
- if(1.0)
- del(src)
- return
- if(2.0)
- if (prob(50))
- del(src)
- return
- if(3.0)
- if (prob(25))
- del(src)
- return
- else
- return
-
-
-/obj/structure/particle_accelerator/blob_act()
- if(prob(50))
- del(src)
- return
-
-
-/obj/structure/particle_accelerator/meteorhit()
- if(prob(50))
- del(src)
- return
-
-/obj/structure/particle_accelerator/update_icon()
- switch(construction_state)
- if(0,1)
- icon_state="[reference]"
- if(2)
- icon_state="[reference]w"
- if(3)
- if(powered)
- icon_state="[reference]p[strength]"
- else
- icon_state="[reference]c"
- return
-
-/obj/structure/particle_accelerator/proc/update_state()
- if(master)
- master.update_state()
- return 0
-
-
-/obj/structure/particle_accelerator/proc/report_ready(var/obj/O)
- if(O && (O == master))
- if(construction_state >= 3)
- return 1
- return 0
-
-
-/obj/structure/particle_accelerator/proc/report_master()
- if(master)
- return master
- return 0
-
-
-/obj/structure/particle_accelerator/proc/connect_master(var/obj/O)
- if(O && istype(O,/obj/machinery/particle_accelerator/control_box))
- if(O.dir == src.dir)
- master = O
- return 1
- return 0
-
-
-/obj/structure/particle_accelerator/proc/process_tool_hit(var/obj/O, var/mob/user)
- if(!(O) || !(user))
- return 0
- if(!ismob(user) || !isobj(O))
- return 0
- var/temp_state = src.construction_state
-
- switch(src.construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps
- if(0)
- if(istype(O, /obj/item/weapon/wrench) && !isinspace())
- playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
- src.anchored = 1
- user.visible_message("[user.name] secures the [src.name] to the floor.", \
- "You secure the external bolts.")
- temp_state++
- if(1)
- if(istype(O, /obj/item/weapon/wrench))
- playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
- src.anchored = 0
- user.visible_message("[user.name] detaches the [src.name] from the floor.", \
- "You remove the external bolts.")
- temp_state--
- else if(istype(O, /obj/item/stack/cable_coil))
- if(O:use(1,user))
- user.visible_message("[user.name] adds wires to the [src.name].", \
- "You add some wires.")
- temp_state++
- if(2)
- if(istype(O, /obj/item/weapon/wirecutters))//TODO:Shock user if its on?
- user.visible_message("[user.name] removes some wires from the [src.name].", \
- "You remove some wires.")
- temp_state--
- else if(istype(O, /obj/item/weapon/screwdriver))
- user.visible_message("[user.name] closes the [src.name]'s access panel.", \
- "You close the access panel.")
- temp_state++
- if(3)
- if(istype(O, /obj/item/weapon/screwdriver))
- user.visible_message("[user.name] opens the [src.name]'s access panel.", \
- "You open the access panel.")
- temp_state--
- if(temp_state == src.construction_state)//Nothing changed
- return 0
- else
- src.construction_state = temp_state
- if(src.construction_state < 3)//Was taken apart, update state
- update_state()
- update_icon()
- return 1
- return 0
-
-
-
-/obj/machinery/particle_accelerator
- name = "Particle Accelerator"
- desc = "Part of a Particle Accelerator."
- icon = 'icons/obj/machines/particle_accelerator.dmi'
- icon_state = "none"
- anchored = 0
- density = 1
- use_power = 0
- idle_power_usage = 0
- active_power_usage = 0
- var/construction_state = 0
- var/active = 0
- var/reference = null
- var/powered = null
- var/strength = 0
- var/desc_holder = null
-
-
-/obj/machinery/particle_accelerator/verb/rotate()
- set name = "Rotate Clockwise"
- set category = "Object"
- set src in oview(1)
-
- if (src.anchored || usr:stat)
- usr << "It is fastened to the floor!"
- return 0
- src.dir = turn(src.dir, 270)
- return 1
-
-/obj/machinery/particle_accelerator/verb/rotateccw()
- set name = "Rotate Counter-Clockwise"
- set category = "Object"
- set src in oview(1)
-
- if (src.anchored || usr:stat)
- usr << "It is fastened to the floor!"
- return 0
- src.dir = turn(src.dir, 90)
- return 1
-
-/obj/machinery/particle_accelerator/update_icon()
- return
-
-/obj/machinery/particle_accelerator/examine()
- switch(src.construction_state)
- if(0)
- src.desc = text("A [name], looks like it's not attached to the flooring")
- if(1)
- src.desc = text("A [name], it is missing some cables")
- if(2)
- src.desc = text("A [name], the panel is open")
- if(3)
- src.desc = text("The [name] is assembled")
- if(powered)
- src.desc = src.desc_holder
- ..()
- return
-
-
-/obj/machinery/particle_accelerator/attackby(obj/item/W, mob/user)
- if(istool(W))
- if(src.process_tool_hit(W,user))
- return
- ..()
- return
-
-/obj/machinery/particle_accelerator/ex_act(severity)
- switch(severity)
- if(1.0)
- del(src)
- return
- if(2.0)
- if (prob(50))
- del(src)
- return
- if(3.0)
- if (prob(25))
- del(src)
- return
- else
- return
-
-
-/obj/machinery/particle_accelerator/blob_act()
- if(prob(50))
- del(src)
- return
-
-
-/obj/machinery/particle_accelerator/meteorhit()
- if(prob(50))
- del(src)
- return
-
-
-/obj/machinery/particle_accelerator/proc/update_state()
- return 0
-
-
-/obj/machinery/particle_accelerator/proc/process_tool_hit(var/obj/O, var/mob/user)
- if(!(O) || !(user))
- return 0
- if(!ismob(user) || !isobj(O))
- return 0
- var/temp_state = src.construction_state
- switch(src.construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps
- if(0)
- if(istype(O, /obj/item/weapon/wrench))
- playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
- src.anchored = 1
- user.visible_message("[user.name] secures the [src.name] to the floor.", \
- "You secure the external bolts.")
- temp_state++
- if(1)
- if(istype(O, /obj/item/weapon/wrench))
- playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
- src.anchored = 0
- user.visible_message("[user.name] detaches the [src.name] from the floor.", \
- "You remove the external bolts.")
- temp_state--
- else if(istype(O, /obj/item/stack/cable_coil))
- if(O:use(1))
- user.visible_message("[user.name] adds wires to the [src.name].", \
- "You add some wires.")
- temp_state++
- if(2)
- if(istype(O, /obj/item/weapon/wirecutters))//TODO:Shock user if its on?
- user.visible_message("[user.name] removes some wires from the [src.name].", \
- "You remove some wires.")
- temp_state--
- else if(istype(O, /obj/item/weapon/screwdriver))
- user.visible_message("[user.name] closes the [src.name]'s access panel.", \
- "You close the access panel.")
- temp_state++
- if(3)
- if(istype(O, /obj/item/weapon/screwdriver))
- user.visible_message("[user.name] opens the [src.name]'s access panel.", \
- "You open the access panel.")
- temp_state--
- active = 0
- if(temp_state == src.construction_state)//Nothing changed
- return 0
- else
- if(src.construction_state < 3)//Was taken apart, update state
- update_state()
- if(use_power)
- use_power = 0
- src.construction_state = temp_state
- if(src.construction_state >= 3)
- use_power = 1
- update_icon()
- return 1
- return 0
+//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
+
+/*Composed of 7 parts
+3 Particle emitters
+proc
+emit_particle()
+
+1 power box
+the only part of this thing that uses power, can hack to mess with the pa/make it better
+
+1 fuel chamber
+contains procs for mixing gas and whatever other fuel it uses
+mix_gas()
+
+1 gas holder WIP
+acts like a tank valve on the ground that you wrench gas tanks onto
+proc
+extract_gas()
+return_gas()
+attach_tank()
+remove_tank()
+get_available_mix()
+
+1 End Cap
+
+1 Control computer
+interface for the pa, acts like a computer with an html menu for diff parts and a status report
+all other parts contain only a ref to this
+a /machine/, tells the others to do work
+contains ref for all parts
+proc
+process()
+check_build()
+
+Setup map
+ |EC|
+CC|FC|
+ |PB|
+PE|PE|PE
+
+
+Icon Addemdum
+Icon system is much more robust, and the icons are all variable based.
+Each part has a reference string, powered, strength, and contruction values.
+Using this the update_icon() proc is simplified a bit (using for absolutely was problematic with naming),
+so the icon_state comes out be:
+"[reference][strength]", with a switch controlling construction_states and ensuring that it doesn't
+power on while being contructed, and all these variables are set by the computer through it's scan list
+Essential order of the icons:
+Standard - [reference]
+Wrenched - [reference]
+Wired - [reference]w
+Closed - [reference]c
+Powered - [reference]p[strength]
+Strength being set by the computer and a null strength (Computer is powered off or inactive) returns a 'null', counting as empty
+So, hopefully this is helpful if any more icons are to be added/changed/wondering what the hell is going on here
+
+*/
+
+/obj/structure/particle_accelerator
+ name = "Particle Accelerator"
+ desc = "Part of a Particle Accelerator."
+ icon = 'icons/obj/machines/particle_accelerator.dmi'
+ icon_state = "none"
+ anchored = 0
+ density = 1
+ var/obj/machinery/particle_accelerator/control_box/master = null
+ var/construction_state = 0
+ var/reference = null
+ var/powered = 0
+ var/strength = null
+ var/desc_holder = null
+
+/obj/structure/particle_accelerator/Del()
+ construction_state = 0
+ if(master)
+ master.part_scan()
+ ..()
+
+/obj/structure/particle_accelerator/end_cap
+ name = "Alpha Particle Generation Array"
+ desc_holder = "This is where Alpha particles are generated from \[REDACTED\]"
+ icon_state = "end_cap"
+ reference = "end_cap"
+
+/obj/structure/particle_accelerator/update_icon()
+ ..()
+ return
+
+
+/obj/structure/particle_accelerator/verb/rotate()
+ set name = "Rotate Clockwise"
+ set category = "Object"
+ set src in oview(1)
+
+ if (src.anchored || usr:stat)
+ usr << "It is fastened to the floor!"
+ return 0
+ src.dir = turn(src.dir, 270)
+ return 1
+
+/obj/structure/particle_accelerator/verb/rotateccw()
+ set name = "Rotate Counter Clockwise"
+ set category = "Object"
+ set src in oview(1)
+
+ if (src.anchored || usr:stat)
+ usr << "It is fastened to the floor!"
+ return 0
+ src.dir = turn(src.dir, 90)
+ return 1
+
+/obj/structure/particle_accelerator/examine()
+ switch(src.construction_state)
+ if(0)
+ src.desc = text("A [name], looks like it's not attached to the flooring")
+ if(1)
+ src.desc = text("A [name], it is missing some cables")
+ if(2)
+ src.desc = text("A [name], the panel is open")
+ if(3)
+ src.desc = text("The [name] is assembled")
+ if(powered)
+ src.desc = src.desc_holder
+ ..()
+ return
+
+
+/obj/structure/particle_accelerator/attackby(obj/item/W, mob/user)
+ if(istool(W))
+ if(src.process_tool_hit(W,user))
+ return
+ ..()
+ return
+
+
+/obj/structure/particle_accelerator/Move()
+ ..()
+ if(master && master.active)
+ master.toggle_power()
+ investigate_log("was moved whilst active; it powered down.","singulo")
+
+/obj/structure/particle_accelerator/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ del(src)
+ return
+ if(2.0)
+ if (prob(50))
+ del(src)
+ return
+ if(3.0)
+ if (prob(25))
+ del(src)
+ return
+ else
+ return
+
+
+/obj/structure/particle_accelerator/blob_act()
+ if(prob(50))
+ del(src)
+ return
+
+
+/obj/structure/particle_accelerator/meteorhit()
+ if(prob(50))
+ del(src)
+ return
+
+/obj/structure/particle_accelerator/update_icon()
+ switch(construction_state)
+ if(0,1)
+ icon_state="[reference]"
+ if(2)
+ icon_state="[reference]w"
+ if(3)
+ if(powered)
+ icon_state="[reference]p[strength]"
+ else
+ icon_state="[reference]c"
+ return
+
+/obj/structure/particle_accelerator/proc/update_state()
+ if(master)
+ master.update_state()
+ return 0
+
+
+/obj/structure/particle_accelerator/proc/report_ready(var/obj/O)
+ if(O && (O == master))
+ if(construction_state >= 3)
+ return 1
+ return 0
+
+
+/obj/structure/particle_accelerator/proc/report_master()
+ if(master)
+ return master
+ return 0
+
+
+/obj/structure/particle_accelerator/proc/connect_master(var/obj/O)
+ if(O && istype(O,/obj/machinery/particle_accelerator/control_box))
+ if(O.dir == src.dir)
+ master = O
+ return 1
+ return 0
+
+
+/obj/structure/particle_accelerator/proc/process_tool_hit(var/obj/O, var/mob/user)
+ if(!(O) || !(user))
+ return 0
+ if(!ismob(user) || !isobj(O))
+ return 0
+ var/temp_state = src.construction_state
+
+ switch(src.construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps
+ if(0)
+ if(istype(O, /obj/item/weapon/wrench) && !isinspace())
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
+ src.anchored = 1
+ user.visible_message("[user.name] secures the [src.name] to the floor.", \
+ "You secure the external bolts.")
+ temp_state++
+ if(1)
+ if(istype(O, /obj/item/weapon/wrench))
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
+ src.anchored = 0
+ user.visible_message("[user.name] detaches the [src.name] from the floor.", \
+ "You remove the external bolts.")
+ temp_state--
+ else if(istype(O, /obj/item/stack/cable_coil))
+ if(O:use(1,user))
+ user.visible_message("[user.name] adds wires to the [src.name].", \
+ "You add some wires.")
+ temp_state++
+ if(2)
+ if(istype(O, /obj/item/weapon/wirecutters))//TODO:Shock user if its on?
+ user.visible_message("[user.name] removes some wires from the [src.name].", \
+ "You remove some wires.")
+ temp_state--
+ else if(istype(O, /obj/item/weapon/screwdriver))
+ user.visible_message("[user.name] closes the [src.name]'s access panel.", \
+ "You close the access panel.")
+ temp_state++
+ if(3)
+ if(istype(O, /obj/item/weapon/screwdriver))
+ user.visible_message("[user.name] opens the [src.name]'s access panel.", \
+ "You open the access panel.")
+ temp_state--
+ if(temp_state == src.construction_state)//Nothing changed
+ return 0
+ else
+ src.construction_state = temp_state
+ if(src.construction_state < 3)//Was taken apart, update state
+ update_state()
+ update_icon()
+ return 1
+ return 0
+
+
+
+/obj/machinery/particle_accelerator
+ name = "Particle Accelerator"
+ desc = "Part of a Particle Accelerator."
+ icon = 'icons/obj/machines/particle_accelerator.dmi'
+ icon_state = "none"
+ anchored = 0
+ density = 1
+ use_power = 0
+ idle_power_usage = 0
+ active_power_usage = 0
+ var/construction_state = 0
+ var/active = 0
+ var/reference = null
+ var/powered = null
+ var/strength = 0
+ var/desc_holder = null
+
+
+/obj/machinery/particle_accelerator/verb/rotate()
+ set name = "Rotate Clockwise"
+ set category = "Object"
+ set src in oview(1)
+
+ if (src.anchored || usr:stat)
+ usr << "It is fastened to the floor!"
+ return 0
+ src.dir = turn(src.dir, 270)
+ return 1
+
+/obj/machinery/particle_accelerator/verb/rotateccw()
+ set name = "Rotate Counter-Clockwise"
+ set category = "Object"
+ set src in oview(1)
+
+ if (src.anchored || usr:stat)
+ usr << "It is fastened to the floor!"
+ return 0
+ src.dir = turn(src.dir, 90)
+ return 1
+
+/obj/machinery/particle_accelerator/update_icon()
+ return
+
+/obj/machinery/particle_accelerator/examine()
+ switch(src.construction_state)
+ if(0)
+ src.desc = text("A [name], looks like it's not attached to the flooring")
+ if(1)
+ src.desc = text("A [name], it is missing some cables")
+ if(2)
+ src.desc = text("A [name], the panel is open")
+ if(3)
+ src.desc = text("The [name] is assembled")
+ if(powered)
+ src.desc = src.desc_holder
+ ..()
+ return
+
+
+/obj/machinery/particle_accelerator/attackby(obj/item/W, mob/user)
+ if(istool(W))
+ if(src.process_tool_hit(W,user))
+ return
+ ..()
+ return
+
+/obj/machinery/particle_accelerator/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ del(src)
+ return
+ if(2.0)
+ if (prob(50))
+ del(src)
+ return
+ if(3.0)
+ if (prob(25))
+ del(src)
+ return
+ else
+ return
+
+
+/obj/machinery/particle_accelerator/blob_act()
+ if(prob(50))
+ del(src)
+ return
+
+
+/obj/machinery/particle_accelerator/meteorhit()
+ if(prob(50))
+ del(src)
+ return
+
+
+/obj/machinery/particle_accelerator/proc/update_state()
+ return 0
+
+
+/obj/machinery/particle_accelerator/proc/process_tool_hit(var/obj/O, var/mob/user)
+ if(!(O) || !(user))
+ return 0
+ if(!ismob(user) || !isobj(O))
+ return 0
+ var/temp_state = src.construction_state
+ switch(src.construction_state)//TODO:Might be more interesting to have it need several parts rather than a single list of steps
+ if(0)
+ if(istype(O, /obj/item/weapon/wrench))
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
+ src.anchored = 1
+ user.visible_message("[user.name] secures the [src.name] to the floor.", \
+ "You secure the external bolts.")
+ temp_state++
+ if(1)
+ if(istype(O, /obj/item/weapon/wrench))
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
+ src.anchored = 0
+ user.visible_message("[user.name] detaches the [src.name] from the floor.", \
+ "You remove the external bolts.")
+ temp_state--
+ else if(istype(O, /obj/item/stack/cable_coil))
+ if(O:use(1))
+ user.visible_message("[user.name] adds wires to the [src.name].", \
+ "You add some wires.")
+ temp_state++
+ if(2)
+ if(istype(O, /obj/item/weapon/wirecutters))//TODO:Shock user if its on?
+ user.visible_message("[user.name] removes some wires from the [src.name].", \
+ "You remove some wires.")
+ temp_state--
+ else if(istype(O, /obj/item/weapon/screwdriver))
+ user.visible_message("[user.name] closes the [src.name]'s access panel.", \
+ "You close the access panel.")
+ temp_state++
+ if(3)
+ if(istype(O, /obj/item/weapon/screwdriver))
+ user.visible_message("[user.name] opens the [src.name]'s access panel.", \
+ "You open the access panel.")
+ temp_state--
+ active = 0
+ if(temp_state == src.construction_state)//Nothing changed
+ return 0
+ else
+ if(src.construction_state < 3)//Was taken apart, update state
+ update_state()
+ if(use_power)
+ use_power = 0
+ src.construction_state = temp_state
+ if(src.construction_state >= 3)
+ use_power = 1
+ update_icon()
+ return 1
+ return 0
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 588dacc1141..743e682d7e9 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -1,99 +1,99 @@
-/obj/item/weapon/gun
- name = "gun"
- desc = "It's a gun. It's pretty terrible, though."
- icon = 'icons/obj/gun.dmi'
- icon_state = "detective"
- item_state = "gun"
- flags = CONDUCT
- slot_flags = SLOT_BELT
- m_amt = 2000
- w_class = 3.0
- throwforce = 5
- throw_speed = 4
- throw_range = 5
- force = 5.0
- origin_tech = "combat=1"
- attack_verb = list("struck", "hit", "bashed")
-
- var/fire_sound = "gunshot"
- var/silenced = 0
- var/recoil = 0
- var/clumsy_check = 1
- var/obj/item/ammo_casing/chambered = null
- var/trigger_guard = 1
-
- proc/process_chamber()
- return 0
-
- proc/special_check(var/mob/M) //Placeholder for any special checks, like detective's revolver.
- return 1
-
- proc/shoot_with_empty_chamber(mob/living/user as mob|obj)
- user << "*click*"
- return
-
- proc/shoot_live_shot(mob/living/user as mob|obj)
- if(recoil)
- spawn()
- shake_camera(user, recoil + 1, recoil)
-
- if(silenced)
- playsound(user, fire_sound, 10, 1)
- else
- playsound(user, fire_sound, 50, 1)
- user.visible_message("[user] fires [src]!", "You fire [src]!", "You hear a [istype(src, /obj/item/weapon/gun/energy) ? "laser blast" : "gunshot"]!")
-
- emp_act(severity)
- for(var/obj/O in contents)
- O.emp_act(severity)
-
-
- afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, flag, params)//TODO: go over this
- if(flag) //It's adjacent, is the user, or is on the user's person
- return
-
- //Exclude lasertag guns from the CLUMSY check.
- if(clumsy_check)
- if(istype(user, /mob/living))
- var/mob/living/M = user
- if ((CLUMSY in M.mutations) && prob(40))
- M << "You shoot yourself in the foot with \the [src]!"
- afterattack(user, user)
- M.drop_item()
- return
-
- if (!user.IsAdvancedToolUser())
- user << "You don't have the dexterity to do this!"
- return
-
- if(trigger_guard)
- if(istype(user, /mob/living))
- var/mob/living/M = user
- if (HULK in M.mutations)
- M << "Your meaty finger is much too large for the trigger guard!"
- return
- if(ishuman(user))
- var/mob/living/carbon/human/H = user
- if(H.dna && H.dna.mutantrace == "adamantine")
- user << "Your metal fingers don't fit in the trigger guard!"
- return
-
- add_fingerprint(user)
-
- if(!special_check(user))
- return
- if(chambered)
- if(!chambered.fire(target, user, params, , silenced))
- shoot_with_empty_chamber(user)
- else
- shoot_live_shot(user)
- else
- shoot_with_empty_chamber(user)
- process_chamber()
- update_icon()
-
- if(user.hand)
- user.update_inv_l_hand(0)
- else
- user.update_inv_r_hand(0)
-
+/obj/item/weapon/gun
+ name = "gun"
+ desc = "It's a gun. It's pretty terrible, though."
+ icon = 'icons/obj/gun.dmi'
+ icon_state = "detective"
+ item_state = "gun"
+ flags = CONDUCT
+ slot_flags = SLOT_BELT
+ m_amt = 2000
+ w_class = 3.0
+ throwforce = 5
+ throw_speed = 4
+ throw_range = 5
+ force = 5.0
+ origin_tech = "combat=1"
+ attack_verb = list("struck", "hit", "bashed")
+
+ var/fire_sound = "gunshot"
+ var/silenced = 0
+ var/recoil = 0
+ var/clumsy_check = 1
+ var/obj/item/ammo_casing/chambered = null
+ var/trigger_guard = 1
+
+ proc/process_chamber()
+ return 0
+
+ proc/special_check(var/mob/M) //Placeholder for any special checks, like detective's revolver.
+ return 1
+
+ proc/shoot_with_empty_chamber(mob/living/user as mob|obj)
+ user << "*click*"
+ return
+
+ proc/shoot_live_shot(mob/living/user as mob|obj)
+ if(recoil)
+ spawn()
+ shake_camera(user, recoil + 1, recoil)
+
+ if(silenced)
+ playsound(user, fire_sound, 10, 1)
+ else
+ playsound(user, fire_sound, 50, 1)
+ user.visible_message("[user] fires [src]!", "You fire [src]!", "You hear a [istype(src, /obj/item/weapon/gun/energy) ? "laser blast" : "gunshot"]!")
+
+ emp_act(severity)
+ for(var/obj/O in contents)
+ O.emp_act(severity)
+
+
+ afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, flag, params)//TODO: go over this
+ if(flag) //It's adjacent, is the user, or is on the user's person
+ return
+
+ //Exclude lasertag guns from the CLUMSY check.
+ if(clumsy_check)
+ if(istype(user, /mob/living))
+ var/mob/living/M = user
+ if ((CLUMSY in M.mutations) && prob(40))
+ M << "You shoot yourself in the foot with \the [src]!"
+ afterattack(user, user)
+ M.drop_item()
+ return
+
+ if (!user.IsAdvancedToolUser())
+ user << "You don't have the dexterity to do this!"
+ return
+
+ if(trigger_guard)
+ if(istype(user, /mob/living))
+ var/mob/living/M = user
+ if (HULK in M.mutations)
+ M << "Your meaty finger is much too large for the trigger guard!"
+ return
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(H.dna && H.dna.mutantrace == "adamantine")
+ user << "Your metal fingers don't fit in the trigger guard!"
+ return
+
+ add_fingerprint(user)
+
+ if(!special_check(user))
+ return
+ if(chambered)
+ if(!chambered.fire(target, user, params, , silenced))
+ shoot_with_empty_chamber(user)
+ else
+ shoot_live_shot(user)
+ else
+ shoot_with_empty_chamber(user)
+ process_chamber()
+ update_icon()
+
+ if(user.hand)
+ user.update_inv_l_hand(0)
+ else
+ user.update_inv_r_hand(0)
+
diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm
index 970dfd54a0a..51f0bd79ea8 100644
--- a/code/modules/recycling/disposal.dm
+++ b/code/modules/recycling/disposal.dm
@@ -1,1341 +1,1341 @@
-// Disposal bin
-// Holds items for disposal into pipe system
-// Draws air from turf, gradually charges internal reservoir
-// Once full (~1 atm), uses air resv to flush items into the pipes
-// Automatically recharges air (unless off), will flush when ready if pre-set
-// Can hold items and human size things, no other draggables
-// Toilets are a type of disposal bin for small objects only and work on magic. By magic, I mean torque rotation
-#define SEND_PRESSURE 0.05*ONE_ATMOSPHERE
-
-/obj/machinery/disposal
- name = "disposal unit"
- desc = "A pneumatic waste disposal unit."
- icon = 'icons/obj/pipes/disposal.dmi'
- icon_state = "disposal"
- anchored = 1
- density = 1
- var/datum/gas_mixture/air_contents // internal reservoir
- var/mode = 1 // item mode 0=off 1=charging 2=charged
- var/flush = 0 // true if flush handle is pulled
- var/obj/structure/disposalpipe/trunk/trunk = null // the attached pipe trunk
- var/flushing = 0 // true if flushing in progress
- var/flush_every_ticks = 30 //Every 30 ticks it will look whether it is ready to flush
- var/flush_count = 0 //this var adds 1 once per tick. When it reaches flush_every_ticks it resets and tries to flush.
- var/last_sound = 0
-
- // create a new disposal
- // find the attached trunk (if present) and init gas resvr.
-/obj/machinery/disposal/New()
- ..()
-
- trunk_check()
-
- air_contents = new/datum/gas_mixture()
- //gas.volume = 1.05 * CELLSTANDARD
- update()
-
-/obj/machinery/disposal/proc/trunk_check()
- trunk = locate() in src.loc
- if(!trunk)
- mode = 0
- flush = 0
- else
- mode = initial(mode)
- flush = initial(flush)
- trunk.linked = src // link the pipe trunk to self
-
-/obj/machinery/disposal/Del()
- for(var/atom/movable/AM in contents)
- AM.loc = src.loc
- ..()
-
-/obj/machinery/disposal/initialize()
- // this will get a copy of the air turf and take a SEND PRESSURE amount of air from it
- var/atom/L = loc
- var/datum/gas_mixture/env = new
- env.copy_from(L.return_air())
- var/datum/gas_mixture/removed = env.remove(SEND_PRESSURE + 1)
- air_contents.merge(removed)
- trunk_check()
-
- // attack by item places it in to disposal
-/obj/machinery/disposal/attackby(var/obj/item/I, var/mob/user)
- if(stat & BROKEN || !I || !user)
- return
-
- if(isrobot(user) && !istype(I, /obj/item/weapon/storage/bag/trash))
- return
- src.add_fingerprint(user)
- if(mode<=0) // It's off
- if(istype(I, /obj/item/weapon/screwdriver))
- if(contents.len > 0)
- user << "Eject the items first!"
- return
- if(mode==0) // It's off but still not unscrewed
- mode=-1 // Set it to doubleoff l0l
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
- user << "You remove the screws around the power connection."
- return
- else if(mode==-1)
- mode=0
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
- user << "You attach the screws around the power connection."
- return
- else if(istype(I,/obj/item/weapon/weldingtool) && mode==-1)
- if(contents.len > 0)
- user << "Eject the items first!"
- return
- var/obj/item/weapon/weldingtool/W = I
- if(W.remove_fuel(0,user))
- playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
- user << "You start slicing the floorweld off \the [src]."
-
- if(do_after(user,20))
- if(!src || !W.isOn()) return
- user << "You slice the floorweld off \the [src]."
- var/obj/structure/disposalconstruct/C = new (src.loc)
- src.transfer_fingerprints_to(C)
- C.ptype = 6 // 6 = disposal unit
- C.anchored = 1
- C.density = 1
- C.update()
- del(src)
- return
- else
- user << "You need more welding fuel to complete this task."
- return
-
- if(istype(I, /obj/item/weapon/melee/energy/blade))
- user << "You can't place \the [I] into \the [src]."
- return
-
- if(istype(I, /obj/item/weapon/storage/bag/trash))
- var/obj/item/weapon/storage/bag/trash/T = I
- user << "\blue You empty the bag."
- for(var/obj/item/O in T.contents)
- T.remove_from_storage(O,src)
- T.update_icon()
- update()
- return
-
- var/obj/item/weapon/grab/G = I
- if(istype(G)) // handle grabbed mob
- if(ismob(G.affecting))
- var/mob/GM = G.affecting
- for (var/mob/V in viewers(usr))
- V.show_message("[usr] starts putting [GM.name] into \the [src].", 3)
- if(do_after(usr, 20))
- if (GM.client)
- GM.client.perspective = EYE_PERSPECTIVE
- GM.client.eye = src
- GM.loc = src
- for (var/mob/C in viewers(src))
- C.show_message("\red [GM.name] has been placed in \the [src] by [user].", 3)
- del(G)
- return
-
- if(!I) return
-
- user.drop_item()
- if(I)
- I.loc = src
-
- user << "You place \the [I] into \the [src]."
- for(var/mob/M in viewers(src))
- if(M == user)
- continue
- M.show_message("[user.name] places \the [I] into \the [src].", 3)
-
- update()
-
-// mouse drop another mob or self
-//
-/obj/machinery/disposal/MouseDrop_T(mob/target, mob/user)
- if (!istype(target) || target.buckled || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || istype(user, /mob/living/silicon/ai))
- return
- src.add_fingerprint(user)
- var/target_loc = target.loc
- var/msg
- for (var/mob/V in viewers(usr))
- if(target == user && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
- V.show_message("[usr] starts climbing into \the [src].", 3)
- if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
- if(target.anchored) return
- if(!ishuman(user) && !ismonkey(user)) return
- V.show_message("[usr] starts stuffing [target.name] into \the [src].", 3)
- if(!do_after(usr, 20))
- return
- if(target_loc != target.loc)
- return
- if(target == user && !user.stat && !user.weakened && !user.stunned && !user.paralysis) // if drop self, then climbed in
- // must be awake, not stunned or whatever
- msg = "[user.name] climbs into \the [src]."
- user << "You climb into \the [src]."
- else if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
- msg = "[user.name] stuffs [target.name] into \the [src]!"
- user << "You stuff [target.name] into \the [src]!"
- else
- return
- if (target.client)
- target.client.perspective = EYE_PERSPECTIVE
- target.client.eye = src
- target.loc = src
-
- for (var/mob/C in viewers(src))
- if(C == user)
- continue
- C.show_message(msg, 3)
-
- update()
- return
-
-// can breath normally in the disposal
-/obj/machinery/disposal/alter_health()
- return get_turf(src)
-
-/obj/machinery/disposal/relaymove(mob/user as mob)
- attempt_escape(user)
-
-// resist to escape the bin
-/obj/machinery/disposal/container_resist()
- attempt_escape(usr)
-
-/obj/machinery/disposal/proc/attempt_escape(mob/user as mob)
- if(src.flushing)
- return
- go_out(user)
- return
-
-// leave the disposal
-/obj/machinery/disposal/proc/go_out(mob/user)
-
- if (user.client)
- user.client.eye = user.client.mob
- user.client.perspective = MOB_PERSPECTIVE
- user.loc = src.loc
- update()
- return
-
-
-// monkeys can only pull the flush lever
-/obj/machinery/disposal/attack_paw(mob/user as mob)
- if(stat & BROKEN)
- return
-
- flush = !flush
- update()
- return
-
-// ai as human but can't flush
-/obj/machinery/disposal/attack_ai(mob/user as mob)
- interact(user, 1)
-
-// human interact with machine
-/obj/machinery/disposal/attack_hand(mob/user as mob)
- if(user && user.loc == src)
- usr << "\red You cannot reach the controls from inside."
- return
- /*
- if(mode==-1)
- usr << "\red The disposal units power is disabled."
- return
- */
- interact(user, 0)
-
-// hostile mob escape from disposals
-/obj/machinery/disposal/attack_animal(var/mob/living/simple_animal/M)
- if(M.environment_smash)
- visible_message("[M.name] smashes \the [src] apart!")
- del(src)
- return
-
-// user interaction
-/obj/machinery/disposal/interact(mob/user, var/ai=0)
-
- src.add_fingerprint(user)
- if(stat & BROKEN)
- user.unset_machine()
- return
-
- var/dat = "Waste Disposal Unit Waste Disposal Unit
"
-
- if(!ai) // AI can't pull flush handle
- if(flush)
- dat += "Disposal handle: Disengage Engaged"
- else
- dat += "Disposal handle: Disengaged Engage"
-
- dat += "
Eject contents
"
-
- if(mode <= 0)
- dat += "Pump: Off On
"
- else if(mode == 1)
- dat += "Pump: Off On (pressurizing)
"
- else
- dat += "Pump: Off On (idle)
"
-
- var/per = Clamp(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 100)
-
- dat += "Pressure: [round(per, 1)]%
"
-
-
- user.set_machine(src)
- user << browse(dat, "window=disposal;size=360x170")
- onclose(user, "disposal")
-
-// handle machine interaction
-
-/obj/machinery/disposal/Topic(href, href_list)
- if(..())
- return
- if(usr.loc == src)
- usr << "\red You cannot reach the controls from inside."
- return
-
- if(mode==-1 && !href_list["eject"]) // only allow ejecting if mode is -1
- usr << "\red \The [src]'s power is disabled."
- return
- ..()
- usr.set_machine(src)
-
- if(href_list["close"])
- usr.unset_machine()
- usr << browse(null, "window=disposal")
- return
-
- if(href_list["pump"])
- if(text2num(href_list["pump"]))
- mode = 1
- else
- mode = 0
- update()
-
- if(href_list["handle"])
- flush = text2num(href_list["handle"])
- update()
-
- if(href_list["eject"])
- eject()
- return
-
-// eject the contents of the disposal unit
-/obj/machinery/disposal/proc/eject()
- for(var/atom/movable/AM in src)
- AM.loc = src.loc
- AM.pipe_eject(0)
- update()
-
-// update the icon & overlays to reflect mode & status
-/obj/machinery/disposal/proc/update()
- overlays.Cut()
- if(stat & BROKEN)
- icon_state = "disposal-broken"
- mode = 0
- flush = 0
- return
-
- // flush handle
- if(flush)
- overlays += image('icons/obj/pipes/disposal.dmi', "dispover-handle")
-
- // only handle is shown if no power
- if(stat & NOPOWER || mode == -1)
- return
-
- // check for items in disposal - occupied light
- if(contents.len > 0)
- overlays += image('icons/obj/pipes/disposal.dmi', "dispover-full")
-
- // charging and ready light
- if(mode == 1)
- overlays += image('icons/obj/pipes/disposal.dmi', "dispover-charge")
- else if(mode == 2)
- overlays += image('icons/obj/pipes/disposal.dmi', "dispover-ready")
-
-// timed process
-// charge the gas reservoir and perform flush if ready
-/obj/machinery/disposal/process()
- if(stat & BROKEN) // nothing can happen if broken
- return
-
- flush_count++
- if( flush_count >= flush_every_ticks )
- if( contents.len )
- if(mode == 2)
- spawn(0)
- feedback_inc("disposal_auto_flush",1)
- flush()
- flush_count = 0
-
- src.updateDialog()
-
- if(flush && air_contents.return_pressure() >= SEND_PRESSURE ) // flush can happen even without power
- spawn(0)
- flush()
-
- if(stat & NOPOWER) // won't charge if no power
- return
-
- use_power(100) // base power usage
-
- if(mode != 1) // if off or ready, no need to charge
- return
-
- // otherwise charge
- use_power(500) // charging power usage
-
- var/atom/L = loc // recharging from loc turf
-
- var/datum/gas_mixture/env = L.return_air()
- var/pressure_delta = (SEND_PRESSURE*1.01) - air_contents.return_pressure()
-
- if(env.temperature > 0)
- var/transfer_moles = 0.1 * pressure_delta*air_contents.volume/(env.temperature * R_IDEAL_GAS_EQUATION)
-
- //Actually transfer the gas
- var/datum/gas_mixture/removed = env.remove(transfer_moles)
- air_contents.merge(removed)
- air_update_turf()
-
-
- // if full enough, switch to ready mode
- if(air_contents.return_pressure() >= SEND_PRESSURE)
- mode = 2
- update()
- return
-
-// perform a flush
-/obj/machinery/disposal/proc/flush()
-
- flushing = 1
- flick("[icon_state]-flush", src)
-
- var/wrapcheck = 0
- var/obj/structure/disposalholder/H = new() // virtual holder object which actually
- // travels through the pipes.
- for(var/obj/item/smallDelivery/O in src)
- wrapcheck = 1
-
- if(wrapcheck == 1)
- H.tomail = 1
-
- sleep(10)
- if(last_sound < world.time + 1)
- playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0)
- last_sound = world.time
- sleep(5) // wait for animation to finish
-
- H.init(src) // copy the contents of disposer to holder
- air_contents = new() // new empty gas resv.
-
- H.start(src) // start the holder processing movement
- flushing = 0
- // now reset disposal state
- flush = 0
- if(mode == 2) // if was ready,
- mode = 1 // switch to charging
- update()
- return
-
-
-// called when area power changes
-/obj/machinery/disposal/power_change()
- ..() // do default setting/reset of stat NOPOWER bit
- update() // update icon
- return
-
-
-// called when holder is expelled from a disposal
-// should usually only occur if the pipe network is modified
-/obj/machinery/disposal/proc/expel(var/obj/structure/disposalholder/H)
-
- var/turf/target
- playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
- if(H) // Somehow, someone managed to flush a window which broke mid-transit and caused the disposal to go in an infinite loop trying to expel null, hopefully this fixes it
- for(var/atom/movable/AM in H)
- target = get_offset_target_turf(src.loc, rand(5)-rand(5), rand(5)-rand(5))
-
- AM.loc = src.loc
- AM.pipe_eject(0)
- spawn(1)
- if(AM)
- AM.throw_at(target, 5, 1)
-
- H.vent_gas(loc)
- del(H)
-
-/obj/machinery/disposal/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
- if (istype(mover,/obj/item) && mover.throwing)
- var/obj/item/I = mover
- if(istype(I, /obj/item/projectile))
- return
- if(prob(75))
- I.loc = src
- for(var/mob/M in viewers(src))
- M.show_message("\the [I] lands in \the [src].", 3)
- else
- for(var/mob/M in viewers(src))
- M.show_message("\the [I] bounces off of \the [src]'s rim!.", 3)
- return 0
- else
- return ..(mover, target, height, air_group)
-
-// virtual disposal object
-// travels through pipes in lieu of actual items
-// contents will be items flushed by the disposal
-// this allows the gas flushed to be tracked
-
-/obj/structure/disposalholder
- invisibility = 101
- var/datum/gas_mixture/gas = null // gas used to flush, will appear at exit point
- var/active = 0 // true if the holder is moving, otherwise inactive
- dir = 0
- var/count = 1000 //*** can travel 1000 steps before going inactive (in case of loops)
- var/has_fat_guy = 0 // true if contains a fat person
- var/destinationTag = 0 // changes if contains a delivery container
- var/tomail = 0 //changes if contains wrapped package
- var/hasmob = 0 //If it contains a mob
-
-
- // initialize a holder from the contents of a disposal unit
- proc/init(var/obj/machinery/disposal/D)
- gas = D.air_contents// transfer gas resv. into holder object
-
- //Check for any living mobs trigger hasmob.
- //hasmob effects whether the package goes to cargo or its tagged destination.
- for(var/mob/living/M in D)
- if(M && M.stat != 2)
- hasmob = 1
-
- //Checks 1 contents level deep. This means that players can be sent through disposals...
- //...but it should require a second person to open the package. (i.e. person inside a wrapped locker)
- for(var/obj/O in D)
- if(O.contents)
- for(var/mob/living/M in O.contents)
- if(M && M.stat != 2)
- hasmob = 1
-
- // now everything inside the disposal gets put into the holder
- // note AM since can contain mobs or objs
- for(var/atom/movable/AM in D)
- AM.loc = src
- if(istype(AM, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = AM
- if(FAT in H.mutations) // is a human and fat?
- has_fat_guy = 1 // set flag on holder
- if(istype(AM, /obj/structure/bigDelivery) && !hasmob)
- var/obj/structure/bigDelivery/T = AM
- src.destinationTag = T.sortTag
- if(istype(AM, /obj/item/smallDelivery) && !hasmob)
- var/obj/item/smallDelivery/T = AM
- src.destinationTag = T.sortTag
-
-
- // start the movement process
- // argument is the disposal unit the holder started in
- proc/start(var/obj/machinery/disposal/D)
- if(!D.trunk)
- D.expel(src) // no trunk connected, so expel immediately
- return
-
- loc = D.trunk
- active = 1
- dir = DOWN
- spawn(1)
- move() // spawn off the movement process
-
- return
-
- // movement process, persists while holder is moving through pipes
- proc/move()
- var/obj/structure/disposalpipe/last
- while(active)
- if(has_fat_guy && prob(2)) // chance of becoming stuck per segment if contains a fat guy
- active = 0
- // find the fat guys
- for(var/mob/living/carbon/human/H in src)
-
- break
- sleep(1) // was 1
- var/obj/structure/disposalpipe/curr = loc
- last = curr
- curr = curr.transfer(src)
- if(!curr)
- last.expel(src, loc, dir)
-
- //
- if(!(count--))
- active = 0
- return
-
-
-
- // find the turf which should contain the next pipe
- proc/nextloc()
- return get_step(loc,dir)
-
- // find a matching pipe on a turf
- proc/findpipe(var/turf/T)
-
- if(!T)
- return null
-
- var/fdir = turn(dir, 180) // flip the movement direction
- for(var/obj/structure/disposalpipe/P in T)
- if(fdir & P.dpdir) // find pipe direction mask that matches flipped dir
- return P
- // if no matching pipe, return null
- return null
-
- // merge two holder objects
- // used when a a holder meets a stuck holder
- proc/merge(var/obj/structure/disposalholder/other)
- for(var/atom/movable/AM in other)
- AM.loc = src // move everything in other holder to this one
- if(ismob(AM))
- var/mob/M = AM
- if(M.client) // if a client mob, update eye to follow this holder
- M.client.eye = src
-
- if(other.has_fat_guy)
- has_fat_guy = 1
- del(other)
-
-
- // called when player tries to move while in a pipe
- relaymove(mob/user as mob)
- if (user.stat)
- return
- if (src.loc)
- for (var/mob/M in hearers(src.loc.loc))
- M << "CLONG, clong!"
-
- playsound(src.loc, 'sound/effects/clang.ogg', 50, 0, 0)
-
- // called to vent all gas in holder to a location
- proc/vent_gas(var/atom/location)
- location.assume_air(gas) // vent all gas to turf
- return
-
-// Disposal pipes
-
-/obj/structure/disposalpipe
- icon = 'icons/obj/pipes/disposal.dmi'
- name = "disposal pipe"
- desc = "An underfloor disposal pipe."
- anchored = 1
- density = 0
-
- level = 1 // underfloor only
- var/dpdir = 0 // bitmask of pipe directions
- dir = 0 // dir will contain dominant direction for junction pipes
- var/health = 10 // health points 0-10
- layer = 2.3 // slightly lower than wires and other pipes
- var/base_icon_state // initial icon state on map
-
- // new pipe, set the icon_state as on map
- New()
- ..()
- base_icon_state = icon_state
- return
-
-
- // pipe is deleted
- // ensure if holder is present, it is expelled
- Del()
- var/obj/structure/disposalholder/H = locate() in src
- if(H)
- // holder was present
- H.active = 0
- var/turf/T = src.loc
- if(T.density)
- // deleting pipe is inside a dense turf (wall)
- // this is unlikely, but just dump out everything into the turf in case
-
- for(var/atom/movable/AM in H)
- AM.loc = T
- AM.pipe_eject(0)
- del(H)
- ..()
- return
-
- // otherwise, do normal expel from turf
- if(H)
- expel(H, T, 0)
- ..()
-
- // returns the direction of the next pipe object, given the entrance dir
- // by default, returns the bitmask of remaining directions
- proc/nextdir(var/fromdir)
- return dpdir & (~turn(fromdir, 180))
-
- // transfer the holder through this pipe segment
- // overriden for special behaviour
- //
- proc/transfer(var/obj/structure/disposalholder/H)
- var/nextdir = nextdir(H.dir)
- H.dir = nextdir
- var/turf/T = H.nextloc()
- var/obj/structure/disposalpipe/P = H.findpipe(T)
-
- if(P)
- // find other holder in next loc, if inactive merge it with current
- var/obj/structure/disposalholder/H2 = locate() in P
- if(H2 && !H2.active)
- H.merge(H2)
-
- H.loc = P
- else // if wasn't a pipe, then set loc to turf
- H.loc = T
- return null
-
- return P
-
-
- // update the icon_state to reflect hidden status
- proc/update()
- var/turf/T = src.loc
- hide(T.intact && !istype(T,/turf/space)) // space never hides pipes
-
- // hide called by levelupdate if turf intact status changes
- // change visibility status and force update of icon
- hide(var/intact)
- invisibility = intact ? 101: 0 // hide if floor is intact
- updateicon()
-
- // update actual icon_state depending on visibility
- // if invisible, append "f" to icon_state to show faded version
- // this will be revealed if a T-scanner is used
- // if visible, use regular icon_state
- proc/updateicon()
- if(invisibility)
- icon_state = "[base_icon_state]f"
- else
- icon_state = base_icon_state
- return
-
-
- // expel the held objects into a turf
- // called when there is a break in the pipe
- //
-
- proc/expel(var/obj/structure/disposalholder/H, var/turf/T, var/direction)
-
- var/turf/target
-
- if(istype(T, /turf/simulated/floor)) //intact floor, pop the tile
- var/turf/simulated/floor/F = T
- if(F.floor_tile)
- F.floor_tile.loc = H //It took me a day to figure out this was the right way to do it. ¯\_(;_;)_/¯
- F.floor_tile = null //So it doesn't get deleted in make_plating()
- F.make_plating()
-
- if(direction) // direction is specified
- if(istype(T, /turf/space)) // if ended in space, then range is unlimited
- target = get_edge_target_turf(T, direction)
- else // otherwise limit to 10 tiles
- target = get_ranged_target_turf(T, direction, 10)
-
- playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
- if(H)
- for(var/atom/movable/AM in H)
- AM.loc = T
- AM.pipe_eject(direction)
- spawn(1)
- if(AM)
- AM.throw_at(target, 100, 1)
-
- else // no specified direction, so throw in random direction
-
- playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
- if(H)
- for(var/atom/movable/AM in H)
- target = get_offset_target_turf(T, rand(5)-rand(5), rand(5)-rand(5))
-
- AM.loc = T
- AM.pipe_eject(0)
- spawn(1)
- if(AM)
- AM.throw_at(target, 5, 1)
- H.vent_gas(T)
- del(H)
- return
-
- // call to break the pipe
- // will expel any holder inside at the time
- // then delete the pipe
- // remains : set to leave broken pipe pieces in place
- proc/broken(var/remains = 0)
- if(remains)
- for(var/D in cardinal)
- if(D & dpdir)
- var/obj/structure/disposalpipe/broken/P = new(src.loc)
- P.dir = D
-
- src.invisibility = 101 // make invisible (since we won't delete the pipe immediately)
- var/obj/structure/disposalholder/H = locate() in src
- if(H)
- // holder was present
- H.active = 0
- var/turf/T = src.loc
- if(T.density)
- // broken pipe is inside a dense turf (wall)
- // this is unlikely, but just dump out everything into the turf in case
-
- for(var/atom/movable/AM in H)
- AM.loc = T
- AM.pipe_eject(0)
- del(H)
- return
-
- // otherwise, do normal expel from turf
- if(H)
- expel(H, T, 0)
-
- spawn(2) // delete pipe after 2 ticks to ensure expel proc finished
- del(src)
-
-
- // pipe affected by explosion
- ex_act(severity)
-
- switch(severity)
- if(1.0)
- broken(0)
- return
- if(2.0)
- health -= rand(5,15)
- healthcheck()
- return
- if(3.0)
- health -= rand(0,15)
- healthcheck()
- return
-
-
- // test health for brokenness
- proc/healthcheck()
- if(health < -2)
- broken(0)
- else if(health<1)
- broken(1)
- return
-
- //attack by item
- //weldingtool: unfasten and convert to obj/disposalconstruct
-
- attackby(var/obj/item/I, var/mob/user)
-
- var/turf/T = src.loc
- if(T.intact)
- return // prevent interaction with T-scanner revealed pipes
- src.add_fingerprint(user)
- if(istype(I, /obj/item/weapon/weldingtool))
- var/obj/item/weapon/weldingtool/W = I
-
- if(W.remove_fuel(0,user))
- playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
- // check if anything changed over 2 seconds
- var/turf/uloc = user.loc
- var/atom/wloc = W.loc
- user << "Slicing the disposal pipe."
- sleep(30)
- if(!W.isOn()) return
- if(user.loc == uloc && wloc == W.loc)
- welded()
- else
- user << "You must stay still while welding the pipe."
- else
- user << "You need more welding fuel to cut the pipe."
- return
-
- // called when pipe is cut with welder
- proc/welded()
-
- var/obj/structure/disposalconstruct/C = new (src.loc)
- switch(base_icon_state)
- if("pipe-s")
- C.ptype = 0
- if("pipe-c")
- C.ptype = 1
- if("pipe-j1")
- C.ptype = 2
- if("pipe-j2")
- C.ptype = 3
- if("pipe-y")
- C.ptype = 4
- if("pipe-t")
- C.ptype = 5
- if("pipe-j1s")
- C.ptype = 9
- if("pipe-j2s")
- C.ptype = 10
- src.transfer_fingerprints_to(C)
- C.dir = dir
- C.density = 0
- C.anchored = 1
- C.update()
-
- del(src)
-
-// *** TEST verb
-//client/verb/dispstop()
-// for(var/obj/structure/disposalholder/H in world)
-// H.active = 0
-
-// a straight or bent segment
-/obj/structure/disposalpipe/segment
- icon_state = "pipe-s"
-
- New()
- ..()
- if(icon_state == "pipe-s")
- dpdir = dir | turn(dir, 180)
- else
- dpdir = dir | turn(dir, -90)
-
- update()
- return
-
-
-
-
-//a three-way junction with dir being the dominant direction
-/obj/structure/disposalpipe/junction
- icon_state = "pipe-j1"
-
- New()
- ..()
- if(icon_state == "pipe-j1")
- dpdir = dir | turn(dir, -90) | turn(dir,180)
- else if(icon_state == "pipe-j2")
- dpdir = dir | turn(dir, 90) | turn(dir,180)
- else // pipe-y
- dpdir = dir | turn(dir,90) | turn(dir, -90)
- update()
- return
-
-
- // next direction to move
- // if coming in from secondary dirs, then next is primary dir
- // if coming in from primary dir, then next is equal chance of other dirs
-
- nextdir(var/fromdir)
- var/flipdir = turn(fromdir, 180)
- if(flipdir != dir) // came from secondary dir
- return dir // so exit through primary
- else // came from primary
- // so need to choose either secondary exit
- var/mask = ..(fromdir)
-
- // find a bit which is set
- var/setbit = 0
- if(mask & NORTH)
- setbit = NORTH
- else if(mask & SOUTH)
- setbit = SOUTH
- else if(mask & EAST)
- setbit = EAST
- else
- setbit = WEST
-
- if(prob(50)) // 50% chance to choose the found bit or the other one
- return setbit
- else
- return mask & (~setbit)
-
-//a three-way junction that sorts objects
-/obj/structure/disposalpipe/sortjunction
-
- icon_state = "pipe-j1s"
- var/sortType = 0 //Look at the list called TAGGERLOCATIONS in setup.dm
- var/posdir = 0
- var/negdir = 0
- var/sortdir = 0
-
- proc/updatedesc()
- desc = "An underfloor disposal pipe with a package sorting mechanism."
- if(sortType>0)
- var/tag = uppertext(TAGGERLOCATIONS[sortType])
- desc += "\nIt's tagged with [tag]"
-
- proc/updatedir()
- posdir = dir
- negdir = turn(posdir, 180)
-
- if(icon_state == "pipe-j1s")
- sortdir = turn(posdir, -90)
- else
- icon_state = "pipe-j2s"
- sortdir = turn(posdir, 90)
-
- dpdir = sortdir | posdir | negdir
-
- New()
- ..()
- updatedir()
- updatedesc()
- update()
- return
-
- attackby(var/obj/item/I, var/mob/user)
- if(..())
- return
-
- if(istype(I, /obj/item/device/destTagger))
- var/obj/item/device/destTagger/O = I
-
- if(O.currTag > 0)// Tag set
- sortType = O.currTag
- playsound(src.loc, 'sound/machines/twobeep.ogg', 100, 1)
- var/tag = uppertext(TAGGERLOCATIONS[O.currTag])
- user << "\blue Changed filter to [tag]"
- updatedesc()
-
-
- // next direction to move
- // if coming in from negdir, then next is primary dir or sortdir
- // if coming in from posdir, then flip around and go back to posdir
- // if coming in from sortdir, go to posdir
-
- nextdir(var/fromdir, var/sortTag)
- //var/flipdir = turn(fromdir, 180)
- if(fromdir != sortdir) // probably came from the negdir
-
- if(src.sortType == sortTag) //if destination matches filtered type...
- return sortdir // exit through sortdirection
- else
- return posdir
- else // came from sortdir
- // so go with the flow to positive direction
- return posdir
-
- transfer(var/obj/structure/disposalholder/H)
- var/nextdir = nextdir(H.dir, H.destinationTag)
- H.dir = nextdir
- var/turf/T = H.nextloc()
- var/obj/structure/disposalpipe/P = H.findpipe(T)
-
- if(P)
- // find other holder in next loc, if inactive merge it with current
- var/obj/structure/disposalholder/H2 = locate() in P
- if(H2 && !H2.active)
- H.merge(H2)
-
- H.loc = P
- else // if wasn't a pipe, then set loc to turf
- H.loc = T
- return null
-
- return P
-
-
-//a three-way junction that sorts objects destined for the mail office mail table (tomail = 1)
-/obj/structure/disposalpipe/wrapsortjunction
-
- desc = "An underfloor disposal pipe which sorts wrapped and unwrapped objects."
- icon_state = "pipe-j1s"
- var/posdir = 0
- var/negdir = 0
- var/sortdir = 0
-
- New()
- ..()
- posdir = dir
- if(icon_state == "pipe-j1s")
- sortdir = turn(posdir, -90)
- negdir = turn(posdir, 180)
- else
- icon_state = "pipe-j2s"
- sortdir = turn(posdir, 90)
- negdir = turn(posdir, 180)
- dpdir = sortdir | posdir | negdir
-
- update()
- return
-
- // next direction to move
- // if coming in from negdir, then next is primary dir or sortdir
- // if coming in from posdir, then flip around and go back to posdir
- // if coming in from sortdir, go to posdir
-
- nextdir(var/fromdir, var/istomail)
- //var/flipdir = turn(fromdir, 180)
- if(fromdir != sortdir) // probably came from the negdir
-
- if(istomail) //if destination matches filtered type...
- return sortdir // exit through sortdirection
- else
- return posdir
- else // came from sortdir
- // so go with the flow to positive direction
- return posdir
-
- transfer(var/obj/structure/disposalholder/H)
- var/nextdir = nextdir(H.dir, H.tomail)
- H.dir = nextdir
- var/turf/T = H.nextloc()
- var/obj/structure/disposalpipe/P = H.findpipe(T)
-
- if(P)
- // find other holder in next loc, if inactive merge it with current
- var/obj/structure/disposalholder/H2 = locate() in P
- if(H2 && !H2.active)
- H.merge(H2)
-
- H.loc = P
- else // if wasn't a pipe, then set loc to turf
- H.loc = T
- return null
-
- return P
-
-
-
-
-
-//a trunk joining to a disposal bin or outlet on the same turf
-/obj/structure/disposalpipe/trunk
- icon_state = "pipe-t"
- var/obj/linked // the linked obj/machinery/disposal or obj/disposaloutlet
-
-/obj/structure/disposalpipe/trunk/New()
- ..()
- dpdir = dir
- spawn(1)
- getlinked()
-
- update()
- return
-
-/obj/structure/disposalpipe/trunk/proc/getlinked()
- linked = null
- var/obj/machinery/disposal/D = locate() in src.loc
- if(D)
- linked = D
- if (!D.trunk)
- D.trunk = src
-
- var/obj/structure/disposaloutlet/O = locate() in src.loc
- if(O)
- linked = O
-
- update()
- return
-
- // Override attackby so we disallow trunkremoval when somethings ontop
-/obj/structure/disposalpipe/trunk/attackby(var/obj/item/I, var/mob/user)
-
- //Disposal bins or chutes
- /*
- These shouldn't be required
- var/obj/machinery/disposal/D = locate() in src.loc
- if(D && D.anchored)
- return
-
- //Disposal outlet
- var/obj/structure/disposaloutlet/O = locate() in src.loc
- if(O && O.anchored)
- return
- */
-
- //Disposal constructors
- var/obj/structure/disposalconstruct/C = locate() in src.loc
- if(C && C.anchored)
- return
-
- var/turf/T = src.loc
- if(T.intact)
- return // prevent interaction with T-scanner revealed pipes
- src.add_fingerprint(user)
- if(istype(I, /obj/item/weapon/weldingtool))
- var/obj/item/weapon/weldingtool/W = I
-
- if(linked)
- user << "You need to deconstruct disposal machinery above this pipe."
- return
-
- if(W.remove_fuel(0,user))
- playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
- // check if anything changed over 2 seconds
- var/turf/uloc = user.loc
- var/atom/wloc = W.loc
- user << "Slicing the disposal pipe."
- sleep(30)
- if(!W.isOn()) return
- if(user.loc == uloc && wloc == W.loc)
- welded()
- else
- user << "You must stay still while welding the pipe."
- else
- user << "You need more welding fuel to cut the pipe."
-
- return
-
- // would transfer to next pipe segment, but we are in a trunk
- // if not entering from disposal bin,
- // transfer to linked object (outlet or bin)
-
-/obj/structure/disposalpipe/trunk/transfer(var/obj/structure/disposalholder/H)
-
- if(H.dir == DOWN) // we just entered from a disposer
- return ..() // so do base transfer proc
- // otherwise, go to the linked object
- if(linked)
- var/obj/structure/disposaloutlet/O = linked
- if(istype(O) && (H))
- O.expel(H) // expel at outlet
- else
- var/obj/machinery/disposal/D = linked
- if(H)
- D.expel(H) // expel at disposal
- else
- if(H)
- src.expel(H, src.loc, 0) // expel at turf
- return null
-
- // nextdir
-
-/obj/structure/disposalpipe/trunk/nextdir(var/fromdir)
- if(fromdir == DOWN)
- return dir
- else
- return 0
-
-// a broken pipe
-/obj/structure/disposalpipe/broken
- icon_state = "pipe-b"
- dpdir = 0 // broken pipes have dpdir=0 so they're not found as 'real' pipes
- // i.e. will be treated as an empty turf
- desc = "A broken piece of disposal pipe."
-
- New()
- ..()
- update()
- return
-
- // called when welded
- // for broken pipe, remove and turn into scrap
-
- welded()
-// var/obj/item/scrap/S = new(src.loc)
-// S.set_components(200,0,0)
- del(src)
-
-// the disposal outlet machine
-
-/obj/structure/disposaloutlet
- name = "disposal outlet"
- desc = "An outlet for the pneumatic disposal system."
- icon = 'icons/obj/pipes/disposal.dmi'
- icon_state = "outlet"
- density = 1
- anchored = 1
- var/active = 0
- var/turf/target // this will be where the output objects are 'thrown' to.
- var/mode = 0
- var/start_eject = 0
- var/eject_range = 2
-
- New()
- ..()
-
- spawn(1)
- target = get_ranged_target_turf(src, dir, 10)
-
-
- var/obj/structure/disposalpipe/trunk/trunk = locate() in src.loc
- if(trunk)
- trunk.linked = src // link the pipe trunk to self
-
- // expel the contents of the holder object, then delete it
- // called when the holder exits the outlet
- proc/expel(var/obj/structure/disposalholder/H)
-
- flick("outlet-open", src)
- if((start_eject + 30) < world.time)
- start_eject = world.time
- playsound(src, 'sound/machines/warning-buzzer.ogg', 50, 0, 0)
- sleep(20)
- playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
- else
- sleep(20)
- if(H)
- for(var/atom/movable/AM in H)
- AM.loc = src.loc
- AM.pipe_eject(dir)
- spawn(5)
- if(AM)
- AM.throw_at(target, eject_range, 1)
- H.vent_gas(src.loc)
- del(H)
- return
-
- attackby(var/obj/item/I, var/mob/user)
- if(!I || !user)
- return
- src.add_fingerprint(user)
- if(istype(I, /obj/item/weapon/screwdriver))
- if(mode==0)
- mode=1
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
- user << "You remove the screws around the power connection."
- return
- else if(mode==1)
- mode=0
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
- user << "You attach the screws around the power connection."
- return
- else if(istype(I,/obj/item/weapon/weldingtool) && mode==1)
- var/obj/item/weapon/weldingtool/W = I
- if(W.remove_fuel(0,user))
- playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
- user << "You start slicing the floorweld off \the [src]."
- if(do_after(user,20))
- if(!src || !W.isOn()) return
- user << "You slice the floorweld off \the [src]."
- var/obj/structure/disposalconstruct/C = new (src.loc)
- src.transfer_fingerprints_to(C)
- C.ptype = 7 // 7 = outlet
- C.update()
- C.anchored = 1
- C.density = 1
- del(src)
- return
- else
- user << "You need more welding fuel to complete this task."
- return
-
-
-
-// called when movable is expelled from a disposal pipe or outlet
-// by default does nothing, override for special behaviour
-
-/atom/movable/proc/pipe_eject(var/direction)
- return
-
-// check if mob has client, if so restore client view on eject
-/mob/pipe_eject(var/direction)
- if (src.client)
- src.client.perspective = MOB_PERSPECTIVE
- src.client.eye = src
-
- return
-
-/obj/effect/decal/cleanable/blood/gibs/pipe_eject(var/direction)
- var/list/dirs
- if(direction)
- dirs = list( direction, turn(direction, -45), turn(direction, 45))
- else
- dirs = alldirs.Copy()
-
- src.streak(dirs)
-
-/obj/effect/decal/cleanable/robot_debris/gib/pipe_eject(var/direction)
- var/list/dirs
- if(direction)
- dirs = list( direction, turn(direction, -45), turn(direction, 45))
- else
- dirs = alldirs.Copy()
-
- src.streak(dirs)
+// Disposal bin
+// Holds items for disposal into pipe system
+// Draws air from turf, gradually charges internal reservoir
+// Once full (~1 atm), uses air resv to flush items into the pipes
+// Automatically recharges air (unless off), will flush when ready if pre-set
+// Can hold items and human size things, no other draggables
+// Toilets are a type of disposal bin for small objects only and work on magic. By magic, I mean torque rotation
+#define SEND_PRESSURE 0.05*ONE_ATMOSPHERE
+
+/obj/machinery/disposal
+ name = "disposal unit"
+ desc = "A pneumatic waste disposal unit."
+ icon = 'icons/obj/pipes/disposal.dmi'
+ icon_state = "disposal"
+ anchored = 1
+ density = 1
+ var/datum/gas_mixture/air_contents // internal reservoir
+ var/mode = 1 // item mode 0=off 1=charging 2=charged
+ var/flush = 0 // true if flush handle is pulled
+ var/obj/structure/disposalpipe/trunk/trunk = null // the attached pipe trunk
+ var/flushing = 0 // true if flushing in progress
+ var/flush_every_ticks = 30 //Every 30 ticks it will look whether it is ready to flush
+ var/flush_count = 0 //this var adds 1 once per tick. When it reaches flush_every_ticks it resets and tries to flush.
+ var/last_sound = 0
+
+ // create a new disposal
+ // find the attached trunk (if present) and init gas resvr.
+/obj/machinery/disposal/New()
+ ..()
+
+ trunk_check()
+
+ air_contents = new/datum/gas_mixture()
+ //gas.volume = 1.05 * CELLSTANDARD
+ update()
+
+/obj/machinery/disposal/proc/trunk_check()
+ trunk = locate() in src.loc
+ if(!trunk)
+ mode = 0
+ flush = 0
+ else
+ mode = initial(mode)
+ flush = initial(flush)
+ trunk.linked = src // link the pipe trunk to self
+
+/obj/machinery/disposal/Del()
+ for(var/atom/movable/AM in contents)
+ AM.loc = src.loc
+ ..()
+
+/obj/machinery/disposal/initialize()
+ // this will get a copy of the air turf and take a SEND PRESSURE amount of air from it
+ var/atom/L = loc
+ var/datum/gas_mixture/env = new
+ env.copy_from(L.return_air())
+ var/datum/gas_mixture/removed = env.remove(SEND_PRESSURE + 1)
+ air_contents.merge(removed)
+ trunk_check()
+
+ // attack by item places it in to disposal
+/obj/machinery/disposal/attackby(var/obj/item/I, var/mob/user)
+ if(stat & BROKEN || !I || !user)
+ return
+
+ if(isrobot(user) && !istype(I, /obj/item/weapon/storage/bag/trash))
+ return
+ src.add_fingerprint(user)
+ if(mode<=0) // It's off
+ if(istype(I, /obj/item/weapon/screwdriver))
+ if(contents.len > 0)
+ user << "Eject the items first!"
+ return
+ if(mode==0) // It's off but still not unscrewed
+ mode=-1 // Set it to doubleoff l0l
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ user << "You remove the screws around the power connection."
+ return
+ else if(mode==-1)
+ mode=0
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ user << "You attach the screws around the power connection."
+ return
+ else if(istype(I,/obj/item/weapon/weldingtool) && mode==-1)
+ if(contents.len > 0)
+ user << "Eject the items first!"
+ return
+ var/obj/item/weapon/weldingtool/W = I
+ if(W.remove_fuel(0,user))
+ playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
+ user << "You start slicing the floorweld off \the [src]."
+
+ if(do_after(user,20))
+ if(!src || !W.isOn()) return
+ user << "You slice the floorweld off \the [src]."
+ var/obj/structure/disposalconstruct/C = new (src.loc)
+ src.transfer_fingerprints_to(C)
+ C.ptype = 6 // 6 = disposal unit
+ C.anchored = 1
+ C.density = 1
+ C.update()
+ del(src)
+ return
+ else
+ user << "You need more welding fuel to complete this task."
+ return
+
+ if(istype(I, /obj/item/weapon/melee/energy/blade))
+ user << "You can't place \the [I] into \the [src]."
+ return
+
+ if(istype(I, /obj/item/weapon/storage/bag/trash))
+ var/obj/item/weapon/storage/bag/trash/T = I
+ user << "\blue You empty the bag."
+ for(var/obj/item/O in T.contents)
+ T.remove_from_storage(O,src)
+ T.update_icon()
+ update()
+ return
+
+ var/obj/item/weapon/grab/G = I
+ if(istype(G)) // handle grabbed mob
+ if(ismob(G.affecting))
+ var/mob/GM = G.affecting
+ for (var/mob/V in viewers(usr))
+ V.show_message("[usr] starts putting [GM.name] into \the [src].", 3)
+ if(do_after(usr, 20))
+ if (GM.client)
+ GM.client.perspective = EYE_PERSPECTIVE
+ GM.client.eye = src
+ GM.loc = src
+ for (var/mob/C in viewers(src))
+ C.show_message("\red [GM.name] has been placed in \the [src] by [user].", 3)
+ del(G)
+ return
+
+ if(!I) return
+
+ user.drop_item()
+ if(I)
+ I.loc = src
+
+ user << "You place \the [I] into \the [src]."
+ for(var/mob/M in viewers(src))
+ if(M == user)
+ continue
+ M.show_message("[user.name] places \the [I] into \the [src].", 3)
+
+ update()
+
+// mouse drop another mob or self
+//
+/obj/machinery/disposal/MouseDrop_T(mob/target, mob/user)
+ if (!istype(target) || target.buckled || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || istype(user, /mob/living/silicon/ai))
+ return
+ src.add_fingerprint(user)
+ var/target_loc = target.loc
+ var/msg
+ for (var/mob/V in viewers(usr))
+ if(target == user && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
+ V.show_message("[usr] starts climbing into \the [src].", 3)
+ if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
+ if(target.anchored) return
+ if(!ishuman(user) && !ismonkey(user)) return
+ V.show_message("[usr] starts stuffing [target.name] into \the [src].", 3)
+ if(!do_after(usr, 20))
+ return
+ if(target_loc != target.loc)
+ return
+ if(target == user && !user.stat && !user.weakened && !user.stunned && !user.paralysis) // if drop self, then climbed in
+ // must be awake, not stunned or whatever
+ msg = "[user.name] climbs into \the [src]."
+ user << "You climb into \the [src]."
+ else if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
+ msg = "[user.name] stuffs [target.name] into \the [src]!"
+ user << "You stuff [target.name] into \the [src]!"
+ else
+ return
+ if (target.client)
+ target.client.perspective = EYE_PERSPECTIVE
+ target.client.eye = src
+ target.loc = src
+
+ for (var/mob/C in viewers(src))
+ if(C == user)
+ continue
+ C.show_message(msg, 3)
+
+ update()
+ return
+
+// can breath normally in the disposal
+/obj/machinery/disposal/alter_health()
+ return get_turf(src)
+
+/obj/machinery/disposal/relaymove(mob/user as mob)
+ attempt_escape(user)
+
+// resist to escape the bin
+/obj/machinery/disposal/container_resist()
+ attempt_escape(usr)
+
+/obj/machinery/disposal/proc/attempt_escape(mob/user as mob)
+ if(src.flushing)
+ return
+ go_out(user)
+ return
+
+// leave the disposal
+/obj/machinery/disposal/proc/go_out(mob/user)
+
+ if (user.client)
+ user.client.eye = user.client.mob
+ user.client.perspective = MOB_PERSPECTIVE
+ user.loc = src.loc
+ update()
+ return
+
+
+// monkeys can only pull the flush lever
+/obj/machinery/disposal/attack_paw(mob/user as mob)
+ if(stat & BROKEN)
+ return
+
+ flush = !flush
+ update()
+ return
+
+// ai as human but can't flush
+/obj/machinery/disposal/attack_ai(mob/user as mob)
+ interact(user, 1)
+
+// human interact with machine
+/obj/machinery/disposal/attack_hand(mob/user as mob)
+ if(user && user.loc == src)
+ usr << "\red You cannot reach the controls from inside."
+ return
+ /*
+ if(mode==-1)
+ usr << "\red The disposal units power is disabled."
+ return
+ */
+ interact(user, 0)
+
+// hostile mob escape from disposals
+/obj/machinery/disposal/attack_animal(var/mob/living/simple_animal/M)
+ if(M.environment_smash)
+ visible_message("[M.name] smashes \the [src] apart!")
+ del(src)
+ return
+
+// user interaction
+/obj/machinery/disposal/interact(mob/user, var/ai=0)
+
+ src.add_fingerprint(user)
+ if(stat & BROKEN)
+ user.unset_machine()
+ return
+
+ var/dat = "Waste Disposal Unit Waste Disposal Unit
"
+
+ if(!ai) // AI can't pull flush handle
+ if(flush)
+ dat += "Disposal handle: Disengage Engaged"
+ else
+ dat += "Disposal handle: Disengaged Engage"
+
+ dat += "
Eject contents
"
+
+ if(mode <= 0)
+ dat += "Pump: Off On
"
+ else if(mode == 1)
+ dat += "Pump: Off On (pressurizing)
"
+ else
+ dat += "Pump: Off On (idle)
"
+
+ var/per = Clamp(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 100)
+
+ dat += "Pressure: [round(per, 1)]%
"
+
+
+ user.set_machine(src)
+ user << browse(dat, "window=disposal;size=360x170")
+ onclose(user, "disposal")
+
+// handle machine interaction
+
+/obj/machinery/disposal/Topic(href, href_list)
+ if(..())
+ return
+ if(usr.loc == src)
+ usr << "\red You cannot reach the controls from inside."
+ return
+
+ if(mode==-1 && !href_list["eject"]) // only allow ejecting if mode is -1
+ usr << "\red \The [src]'s power is disabled."
+ return
+ ..()
+ usr.set_machine(src)
+
+ if(href_list["close"])
+ usr.unset_machine()
+ usr << browse(null, "window=disposal")
+ return
+
+ if(href_list["pump"])
+ if(text2num(href_list["pump"]))
+ mode = 1
+ else
+ mode = 0
+ update()
+
+ if(href_list["handle"])
+ flush = text2num(href_list["handle"])
+ update()
+
+ if(href_list["eject"])
+ eject()
+ return
+
+// eject the contents of the disposal unit
+/obj/machinery/disposal/proc/eject()
+ for(var/atom/movable/AM in src)
+ AM.loc = src.loc
+ AM.pipe_eject(0)
+ update()
+
+// update the icon & overlays to reflect mode & status
+/obj/machinery/disposal/proc/update()
+ overlays.Cut()
+ if(stat & BROKEN)
+ icon_state = "disposal-broken"
+ mode = 0
+ flush = 0
+ return
+
+ // flush handle
+ if(flush)
+ overlays += image('icons/obj/pipes/disposal.dmi', "dispover-handle")
+
+ // only handle is shown if no power
+ if(stat & NOPOWER || mode == -1)
+ return
+
+ // check for items in disposal - occupied light
+ if(contents.len > 0)
+ overlays += image('icons/obj/pipes/disposal.dmi', "dispover-full")
+
+ // charging and ready light
+ if(mode == 1)
+ overlays += image('icons/obj/pipes/disposal.dmi', "dispover-charge")
+ else if(mode == 2)
+ overlays += image('icons/obj/pipes/disposal.dmi', "dispover-ready")
+
+// timed process
+// charge the gas reservoir and perform flush if ready
+/obj/machinery/disposal/process()
+ if(stat & BROKEN) // nothing can happen if broken
+ return
+
+ flush_count++
+ if( flush_count >= flush_every_ticks )
+ if( contents.len )
+ if(mode == 2)
+ spawn(0)
+ feedback_inc("disposal_auto_flush",1)
+ flush()
+ flush_count = 0
+
+ src.updateDialog()
+
+ if(flush && air_contents.return_pressure() >= SEND_PRESSURE ) // flush can happen even without power
+ spawn(0)
+ flush()
+
+ if(stat & NOPOWER) // won't charge if no power
+ return
+
+ use_power(100) // base power usage
+
+ if(mode != 1) // if off or ready, no need to charge
+ return
+
+ // otherwise charge
+ use_power(500) // charging power usage
+
+ var/atom/L = loc // recharging from loc turf
+
+ var/datum/gas_mixture/env = L.return_air()
+ var/pressure_delta = (SEND_PRESSURE*1.01) - air_contents.return_pressure()
+
+ if(env.temperature > 0)
+ var/transfer_moles = 0.1 * pressure_delta*air_contents.volume/(env.temperature * R_IDEAL_GAS_EQUATION)
+
+ //Actually transfer the gas
+ var/datum/gas_mixture/removed = env.remove(transfer_moles)
+ air_contents.merge(removed)
+ air_update_turf()
+
+
+ // if full enough, switch to ready mode
+ if(air_contents.return_pressure() >= SEND_PRESSURE)
+ mode = 2
+ update()
+ return
+
+// perform a flush
+/obj/machinery/disposal/proc/flush()
+
+ flushing = 1
+ flick("[icon_state]-flush", src)
+
+ var/wrapcheck = 0
+ var/obj/structure/disposalholder/H = new() // virtual holder object which actually
+ // travels through the pipes.
+ for(var/obj/item/smallDelivery/O in src)
+ wrapcheck = 1
+
+ if(wrapcheck == 1)
+ H.tomail = 1
+
+ sleep(10)
+ if(last_sound < world.time + 1)
+ playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0)
+ last_sound = world.time
+ sleep(5) // wait for animation to finish
+
+ H.init(src) // copy the contents of disposer to holder
+ air_contents = new() // new empty gas resv.
+
+ H.start(src) // start the holder processing movement
+ flushing = 0
+ // now reset disposal state
+ flush = 0
+ if(mode == 2) // if was ready,
+ mode = 1 // switch to charging
+ update()
+ return
+
+
+// called when area power changes
+/obj/machinery/disposal/power_change()
+ ..() // do default setting/reset of stat NOPOWER bit
+ update() // update icon
+ return
+
+
+// called when holder is expelled from a disposal
+// should usually only occur if the pipe network is modified
+/obj/machinery/disposal/proc/expel(var/obj/structure/disposalholder/H)
+
+ var/turf/target
+ playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
+ if(H) // Somehow, someone managed to flush a window which broke mid-transit and caused the disposal to go in an infinite loop trying to expel null, hopefully this fixes it
+ for(var/atom/movable/AM in H)
+ target = get_offset_target_turf(src.loc, rand(5)-rand(5), rand(5)-rand(5))
+
+ AM.loc = src.loc
+ AM.pipe_eject(0)
+ spawn(1)
+ if(AM)
+ AM.throw_at(target, 5, 1)
+
+ H.vent_gas(loc)
+ del(H)
+
+/obj/machinery/disposal/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
+ if (istype(mover,/obj/item) && mover.throwing)
+ var/obj/item/I = mover
+ if(istype(I, /obj/item/projectile))
+ return
+ if(prob(75))
+ I.loc = src
+ for(var/mob/M in viewers(src))
+ M.show_message("\the [I] lands in \the [src].", 3)
+ else
+ for(var/mob/M in viewers(src))
+ M.show_message("\the [I] bounces off of \the [src]'s rim!.", 3)
+ return 0
+ else
+ return ..(mover, target, height, air_group)
+
+// virtual disposal object
+// travels through pipes in lieu of actual items
+// contents will be items flushed by the disposal
+// this allows the gas flushed to be tracked
+
+/obj/structure/disposalholder
+ invisibility = 101
+ var/datum/gas_mixture/gas = null // gas used to flush, will appear at exit point
+ var/active = 0 // true if the holder is moving, otherwise inactive
+ dir = 0
+ var/count = 1000 //*** can travel 1000 steps before going inactive (in case of loops)
+ var/has_fat_guy = 0 // true if contains a fat person
+ var/destinationTag = 0 // changes if contains a delivery container
+ var/tomail = 0 //changes if contains wrapped package
+ var/hasmob = 0 //If it contains a mob
+
+
+ // initialize a holder from the contents of a disposal unit
+ proc/init(var/obj/machinery/disposal/D)
+ gas = D.air_contents// transfer gas resv. into holder object
+
+ //Check for any living mobs trigger hasmob.
+ //hasmob effects whether the package goes to cargo or its tagged destination.
+ for(var/mob/living/M in D)
+ if(M && M.stat != 2)
+ hasmob = 1
+
+ //Checks 1 contents level deep. This means that players can be sent through disposals...
+ //...but it should require a second person to open the package. (i.e. person inside a wrapped locker)
+ for(var/obj/O in D)
+ if(O.contents)
+ for(var/mob/living/M in O.contents)
+ if(M && M.stat != 2)
+ hasmob = 1
+
+ // now everything inside the disposal gets put into the holder
+ // note AM since can contain mobs or objs
+ for(var/atom/movable/AM in D)
+ AM.loc = src
+ if(istype(AM, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = AM
+ if(FAT in H.mutations) // is a human and fat?
+ has_fat_guy = 1 // set flag on holder
+ if(istype(AM, /obj/structure/bigDelivery) && !hasmob)
+ var/obj/structure/bigDelivery/T = AM
+ src.destinationTag = T.sortTag
+ if(istype(AM, /obj/item/smallDelivery) && !hasmob)
+ var/obj/item/smallDelivery/T = AM
+ src.destinationTag = T.sortTag
+
+
+ // start the movement process
+ // argument is the disposal unit the holder started in
+ proc/start(var/obj/machinery/disposal/D)
+ if(!D.trunk)
+ D.expel(src) // no trunk connected, so expel immediately
+ return
+
+ loc = D.trunk
+ active = 1
+ dir = DOWN
+ spawn(1)
+ move() // spawn off the movement process
+
+ return
+
+ // movement process, persists while holder is moving through pipes
+ proc/move()
+ var/obj/structure/disposalpipe/last
+ while(active)
+ if(has_fat_guy && prob(2)) // chance of becoming stuck per segment if contains a fat guy
+ active = 0
+ // find the fat guys
+ for(var/mob/living/carbon/human/H in src)
+
+ break
+ sleep(1) // was 1
+ var/obj/structure/disposalpipe/curr = loc
+ last = curr
+ curr = curr.transfer(src)
+ if(!curr)
+ last.expel(src, loc, dir)
+
+ //
+ if(!(count--))
+ active = 0
+ return
+
+
+
+ // find the turf which should contain the next pipe
+ proc/nextloc()
+ return get_step(loc,dir)
+
+ // find a matching pipe on a turf
+ proc/findpipe(var/turf/T)
+
+ if(!T)
+ return null
+
+ var/fdir = turn(dir, 180) // flip the movement direction
+ for(var/obj/structure/disposalpipe/P in T)
+ if(fdir & P.dpdir) // find pipe direction mask that matches flipped dir
+ return P
+ // if no matching pipe, return null
+ return null
+
+ // merge two holder objects
+ // used when a a holder meets a stuck holder
+ proc/merge(var/obj/structure/disposalholder/other)
+ for(var/atom/movable/AM in other)
+ AM.loc = src // move everything in other holder to this one
+ if(ismob(AM))
+ var/mob/M = AM
+ if(M.client) // if a client mob, update eye to follow this holder
+ M.client.eye = src
+
+ if(other.has_fat_guy)
+ has_fat_guy = 1
+ del(other)
+
+
+ // called when player tries to move while in a pipe
+ relaymove(mob/user as mob)
+ if (user.stat)
+ return
+ if (src.loc)
+ for (var/mob/M in hearers(src.loc.loc))
+ M << "CLONG, clong!"
+
+ playsound(src.loc, 'sound/effects/clang.ogg', 50, 0, 0)
+
+ // called to vent all gas in holder to a location
+ proc/vent_gas(var/atom/location)
+ location.assume_air(gas) // vent all gas to turf
+ return
+
+// Disposal pipes
+
+/obj/structure/disposalpipe
+ icon = 'icons/obj/pipes/disposal.dmi'
+ name = "disposal pipe"
+ desc = "An underfloor disposal pipe."
+ anchored = 1
+ density = 0
+
+ level = 1 // underfloor only
+ var/dpdir = 0 // bitmask of pipe directions
+ dir = 0 // dir will contain dominant direction for junction pipes
+ var/health = 10 // health points 0-10
+ layer = 2.3 // slightly lower than wires and other pipes
+ var/base_icon_state // initial icon state on map
+
+ // new pipe, set the icon_state as on map
+ New()
+ ..()
+ base_icon_state = icon_state
+ return
+
+
+ // pipe is deleted
+ // ensure if holder is present, it is expelled
+ Del()
+ var/obj/structure/disposalholder/H = locate() in src
+ if(H)
+ // holder was present
+ H.active = 0
+ var/turf/T = src.loc
+ if(T.density)
+ // deleting pipe is inside a dense turf (wall)
+ // this is unlikely, but just dump out everything into the turf in case
+
+ for(var/atom/movable/AM in H)
+ AM.loc = T
+ AM.pipe_eject(0)
+ del(H)
+ ..()
+ return
+
+ // otherwise, do normal expel from turf
+ if(H)
+ expel(H, T, 0)
+ ..()
+
+ // returns the direction of the next pipe object, given the entrance dir
+ // by default, returns the bitmask of remaining directions
+ proc/nextdir(var/fromdir)
+ return dpdir & (~turn(fromdir, 180))
+
+ // transfer the holder through this pipe segment
+ // overriden for special behaviour
+ //
+ proc/transfer(var/obj/structure/disposalholder/H)
+ var/nextdir = nextdir(H.dir)
+ H.dir = nextdir
+ var/turf/T = H.nextloc()
+ var/obj/structure/disposalpipe/P = H.findpipe(T)
+
+ if(P)
+ // find other holder in next loc, if inactive merge it with current
+ var/obj/structure/disposalholder/H2 = locate() in P
+ if(H2 && !H2.active)
+ H.merge(H2)
+
+ H.loc = P
+ else // if wasn't a pipe, then set loc to turf
+ H.loc = T
+ return null
+
+ return P
+
+
+ // update the icon_state to reflect hidden status
+ proc/update()
+ var/turf/T = src.loc
+ hide(T.intact && !istype(T,/turf/space)) // space never hides pipes
+
+ // hide called by levelupdate if turf intact status changes
+ // change visibility status and force update of icon
+ hide(var/intact)
+ invisibility = intact ? 101: 0 // hide if floor is intact
+ updateicon()
+
+ // update actual icon_state depending on visibility
+ // if invisible, append "f" to icon_state to show faded version
+ // this will be revealed if a T-scanner is used
+ // if visible, use regular icon_state
+ proc/updateicon()
+ if(invisibility)
+ icon_state = "[base_icon_state]f"
+ else
+ icon_state = base_icon_state
+ return
+
+
+ // expel the held objects into a turf
+ // called when there is a break in the pipe
+ //
+
+ proc/expel(var/obj/structure/disposalholder/H, var/turf/T, var/direction)
+
+ var/turf/target
+
+ if(istype(T, /turf/simulated/floor)) //intact floor, pop the tile
+ var/turf/simulated/floor/F = T
+ if(F.floor_tile)
+ F.floor_tile.loc = H //It took me a day to figure out this was the right way to do it. ¯\_(;_;)_/¯
+ F.floor_tile = null //So it doesn't get deleted in make_plating()
+ F.make_plating()
+
+ if(direction) // direction is specified
+ if(istype(T, /turf/space)) // if ended in space, then range is unlimited
+ target = get_edge_target_turf(T, direction)
+ else // otherwise limit to 10 tiles
+ target = get_ranged_target_turf(T, direction, 10)
+
+ playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
+ if(H)
+ for(var/atom/movable/AM in H)
+ AM.loc = T
+ AM.pipe_eject(direction)
+ spawn(1)
+ if(AM)
+ AM.throw_at(target, 100, 1)
+
+ else // no specified direction, so throw in random direction
+
+ playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
+ if(H)
+ for(var/atom/movable/AM in H)
+ target = get_offset_target_turf(T, rand(5)-rand(5), rand(5)-rand(5))
+
+ AM.loc = T
+ AM.pipe_eject(0)
+ spawn(1)
+ if(AM)
+ AM.throw_at(target, 5, 1)
+ H.vent_gas(T)
+ del(H)
+ return
+
+ // call to break the pipe
+ // will expel any holder inside at the time
+ // then delete the pipe
+ // remains : set to leave broken pipe pieces in place
+ proc/broken(var/remains = 0)
+ if(remains)
+ for(var/D in cardinal)
+ if(D & dpdir)
+ var/obj/structure/disposalpipe/broken/P = new(src.loc)
+ P.dir = D
+
+ src.invisibility = 101 // make invisible (since we won't delete the pipe immediately)
+ var/obj/structure/disposalholder/H = locate() in src
+ if(H)
+ // holder was present
+ H.active = 0
+ var/turf/T = src.loc
+ if(T.density)
+ // broken pipe is inside a dense turf (wall)
+ // this is unlikely, but just dump out everything into the turf in case
+
+ for(var/atom/movable/AM in H)
+ AM.loc = T
+ AM.pipe_eject(0)
+ del(H)
+ return
+
+ // otherwise, do normal expel from turf
+ if(H)
+ expel(H, T, 0)
+
+ spawn(2) // delete pipe after 2 ticks to ensure expel proc finished
+ del(src)
+
+
+ // pipe affected by explosion
+ ex_act(severity)
+
+ switch(severity)
+ if(1.0)
+ broken(0)
+ return
+ if(2.0)
+ health -= rand(5,15)
+ healthcheck()
+ return
+ if(3.0)
+ health -= rand(0,15)
+ healthcheck()
+ return
+
+
+ // test health for brokenness
+ proc/healthcheck()
+ if(health < -2)
+ broken(0)
+ else if(health<1)
+ broken(1)
+ return
+
+ //attack by item
+ //weldingtool: unfasten and convert to obj/disposalconstruct
+
+ attackby(var/obj/item/I, var/mob/user)
+
+ var/turf/T = src.loc
+ if(T.intact)
+ return // prevent interaction with T-scanner revealed pipes
+ src.add_fingerprint(user)
+ if(istype(I, /obj/item/weapon/weldingtool))
+ var/obj/item/weapon/weldingtool/W = I
+
+ if(W.remove_fuel(0,user))
+ playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
+ // check if anything changed over 2 seconds
+ var/turf/uloc = user.loc
+ var/atom/wloc = W.loc
+ user << "Slicing the disposal pipe."
+ sleep(30)
+ if(!W.isOn()) return
+ if(user.loc == uloc && wloc == W.loc)
+ welded()
+ else
+ user << "You must stay still while welding the pipe."
+ else
+ user << "You need more welding fuel to cut the pipe."
+ return
+
+ // called when pipe is cut with welder
+ proc/welded()
+
+ var/obj/structure/disposalconstruct/C = new (src.loc)
+ switch(base_icon_state)
+ if("pipe-s")
+ C.ptype = 0
+ if("pipe-c")
+ C.ptype = 1
+ if("pipe-j1")
+ C.ptype = 2
+ if("pipe-j2")
+ C.ptype = 3
+ if("pipe-y")
+ C.ptype = 4
+ if("pipe-t")
+ C.ptype = 5
+ if("pipe-j1s")
+ C.ptype = 9
+ if("pipe-j2s")
+ C.ptype = 10
+ src.transfer_fingerprints_to(C)
+ C.dir = dir
+ C.density = 0
+ C.anchored = 1
+ C.update()
+
+ del(src)
+
+// *** TEST verb
+//client/verb/dispstop()
+// for(var/obj/structure/disposalholder/H in world)
+// H.active = 0
+
+// a straight or bent segment
+/obj/structure/disposalpipe/segment
+ icon_state = "pipe-s"
+
+ New()
+ ..()
+ if(icon_state == "pipe-s")
+ dpdir = dir | turn(dir, 180)
+ else
+ dpdir = dir | turn(dir, -90)
+
+ update()
+ return
+
+
+
+
+//a three-way junction with dir being the dominant direction
+/obj/structure/disposalpipe/junction
+ icon_state = "pipe-j1"
+
+ New()
+ ..()
+ if(icon_state == "pipe-j1")
+ dpdir = dir | turn(dir, -90) | turn(dir,180)
+ else if(icon_state == "pipe-j2")
+ dpdir = dir | turn(dir, 90) | turn(dir,180)
+ else // pipe-y
+ dpdir = dir | turn(dir,90) | turn(dir, -90)
+ update()
+ return
+
+
+ // next direction to move
+ // if coming in from secondary dirs, then next is primary dir
+ // if coming in from primary dir, then next is equal chance of other dirs
+
+ nextdir(var/fromdir)
+ var/flipdir = turn(fromdir, 180)
+ if(flipdir != dir) // came from secondary dir
+ return dir // so exit through primary
+ else // came from primary
+ // so need to choose either secondary exit
+ var/mask = ..(fromdir)
+
+ // find a bit which is set
+ var/setbit = 0
+ if(mask & NORTH)
+ setbit = NORTH
+ else if(mask & SOUTH)
+ setbit = SOUTH
+ else if(mask & EAST)
+ setbit = EAST
+ else
+ setbit = WEST
+
+ if(prob(50)) // 50% chance to choose the found bit or the other one
+ return setbit
+ else
+ return mask & (~setbit)
+
+//a three-way junction that sorts objects
+/obj/structure/disposalpipe/sortjunction
+
+ icon_state = "pipe-j1s"
+ var/sortType = 0 //Look at the list called TAGGERLOCATIONS in setup.dm
+ var/posdir = 0
+ var/negdir = 0
+ var/sortdir = 0
+
+ proc/updatedesc()
+ desc = "An underfloor disposal pipe with a package sorting mechanism."
+ if(sortType>0)
+ var/tag = uppertext(TAGGERLOCATIONS[sortType])
+ desc += "\nIt's tagged with [tag]"
+
+ proc/updatedir()
+ posdir = dir
+ negdir = turn(posdir, 180)
+
+ if(icon_state == "pipe-j1s")
+ sortdir = turn(posdir, -90)
+ else
+ icon_state = "pipe-j2s"
+ sortdir = turn(posdir, 90)
+
+ dpdir = sortdir | posdir | negdir
+
+ New()
+ ..()
+ updatedir()
+ updatedesc()
+ update()
+ return
+
+ attackby(var/obj/item/I, var/mob/user)
+ if(..())
+ return
+
+ if(istype(I, /obj/item/device/destTagger))
+ var/obj/item/device/destTagger/O = I
+
+ if(O.currTag > 0)// Tag set
+ sortType = O.currTag
+ playsound(src.loc, 'sound/machines/twobeep.ogg', 100, 1)
+ var/tag = uppertext(TAGGERLOCATIONS[O.currTag])
+ user << "\blue Changed filter to [tag]"
+ updatedesc()
+
+
+ // next direction to move
+ // if coming in from negdir, then next is primary dir or sortdir
+ // if coming in from posdir, then flip around and go back to posdir
+ // if coming in from sortdir, go to posdir
+
+ nextdir(var/fromdir, var/sortTag)
+ //var/flipdir = turn(fromdir, 180)
+ if(fromdir != sortdir) // probably came from the negdir
+
+ if(src.sortType == sortTag) //if destination matches filtered type...
+ return sortdir // exit through sortdirection
+ else
+ return posdir
+ else // came from sortdir
+ // so go with the flow to positive direction
+ return posdir
+
+ transfer(var/obj/structure/disposalholder/H)
+ var/nextdir = nextdir(H.dir, H.destinationTag)
+ H.dir = nextdir
+ var/turf/T = H.nextloc()
+ var/obj/structure/disposalpipe/P = H.findpipe(T)
+
+ if(P)
+ // find other holder in next loc, if inactive merge it with current
+ var/obj/structure/disposalholder/H2 = locate() in P
+ if(H2 && !H2.active)
+ H.merge(H2)
+
+ H.loc = P
+ else // if wasn't a pipe, then set loc to turf
+ H.loc = T
+ return null
+
+ return P
+
+
+//a three-way junction that sorts objects destined for the mail office mail table (tomail = 1)
+/obj/structure/disposalpipe/wrapsortjunction
+
+ desc = "An underfloor disposal pipe which sorts wrapped and unwrapped objects."
+ icon_state = "pipe-j1s"
+ var/posdir = 0
+ var/negdir = 0
+ var/sortdir = 0
+
+ New()
+ ..()
+ posdir = dir
+ if(icon_state == "pipe-j1s")
+ sortdir = turn(posdir, -90)
+ negdir = turn(posdir, 180)
+ else
+ icon_state = "pipe-j2s"
+ sortdir = turn(posdir, 90)
+ negdir = turn(posdir, 180)
+ dpdir = sortdir | posdir | negdir
+
+ update()
+ return
+
+ // next direction to move
+ // if coming in from negdir, then next is primary dir or sortdir
+ // if coming in from posdir, then flip around and go back to posdir
+ // if coming in from sortdir, go to posdir
+
+ nextdir(var/fromdir, var/istomail)
+ //var/flipdir = turn(fromdir, 180)
+ if(fromdir != sortdir) // probably came from the negdir
+
+ if(istomail) //if destination matches filtered type...
+ return sortdir // exit through sortdirection
+ else
+ return posdir
+ else // came from sortdir
+ // so go with the flow to positive direction
+ return posdir
+
+ transfer(var/obj/structure/disposalholder/H)
+ var/nextdir = nextdir(H.dir, H.tomail)
+ H.dir = nextdir
+ var/turf/T = H.nextloc()
+ var/obj/structure/disposalpipe/P = H.findpipe(T)
+
+ if(P)
+ // find other holder in next loc, if inactive merge it with current
+ var/obj/structure/disposalholder/H2 = locate() in P
+ if(H2 && !H2.active)
+ H.merge(H2)
+
+ H.loc = P
+ else // if wasn't a pipe, then set loc to turf
+ H.loc = T
+ return null
+
+ return P
+
+
+
+
+
+//a trunk joining to a disposal bin or outlet on the same turf
+/obj/structure/disposalpipe/trunk
+ icon_state = "pipe-t"
+ var/obj/linked // the linked obj/machinery/disposal or obj/disposaloutlet
+
+/obj/structure/disposalpipe/trunk/New()
+ ..()
+ dpdir = dir
+ spawn(1)
+ getlinked()
+
+ update()
+ return
+
+/obj/structure/disposalpipe/trunk/proc/getlinked()
+ linked = null
+ var/obj/machinery/disposal/D = locate() in src.loc
+ if(D)
+ linked = D
+ if (!D.trunk)
+ D.trunk = src
+
+ var/obj/structure/disposaloutlet/O = locate() in src.loc
+ if(O)
+ linked = O
+
+ update()
+ return
+
+ // Override attackby so we disallow trunkremoval when somethings ontop
+/obj/structure/disposalpipe/trunk/attackby(var/obj/item/I, var/mob/user)
+
+ //Disposal bins or chutes
+ /*
+ These shouldn't be required
+ var/obj/machinery/disposal/D = locate() in src.loc
+ if(D && D.anchored)
+ return
+
+ //Disposal outlet
+ var/obj/structure/disposaloutlet/O = locate() in src.loc
+ if(O && O.anchored)
+ return
+ */
+
+ //Disposal constructors
+ var/obj/structure/disposalconstruct/C = locate() in src.loc
+ if(C && C.anchored)
+ return
+
+ var/turf/T = src.loc
+ if(T.intact)
+ return // prevent interaction with T-scanner revealed pipes
+ src.add_fingerprint(user)
+ if(istype(I, /obj/item/weapon/weldingtool))
+ var/obj/item/weapon/weldingtool/W = I
+
+ if(linked)
+ user << "You need to deconstruct disposal machinery above this pipe."
+ return
+
+ if(W.remove_fuel(0,user))
+ playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
+ // check if anything changed over 2 seconds
+ var/turf/uloc = user.loc
+ var/atom/wloc = W.loc
+ user << "Slicing the disposal pipe."
+ sleep(30)
+ if(!W.isOn()) return
+ if(user.loc == uloc && wloc == W.loc)
+ welded()
+ else
+ user << "You must stay still while welding the pipe."
+ else
+ user << "You need more welding fuel to cut the pipe."
+
+ return
+
+ // would transfer to next pipe segment, but we are in a trunk
+ // if not entering from disposal bin,
+ // transfer to linked object (outlet or bin)
+
+/obj/structure/disposalpipe/trunk/transfer(var/obj/structure/disposalholder/H)
+
+ if(H.dir == DOWN) // we just entered from a disposer
+ return ..() // so do base transfer proc
+ // otherwise, go to the linked object
+ if(linked)
+ var/obj/structure/disposaloutlet/O = linked
+ if(istype(O) && (H))
+ O.expel(H) // expel at outlet
+ else
+ var/obj/machinery/disposal/D = linked
+ if(H)
+ D.expel(H) // expel at disposal
+ else
+ if(H)
+ src.expel(H, src.loc, 0) // expel at turf
+ return null
+
+ // nextdir
+
+/obj/structure/disposalpipe/trunk/nextdir(var/fromdir)
+ if(fromdir == DOWN)
+ return dir
+ else
+ return 0
+
+// a broken pipe
+/obj/structure/disposalpipe/broken
+ icon_state = "pipe-b"
+ dpdir = 0 // broken pipes have dpdir=0 so they're not found as 'real' pipes
+ // i.e. will be treated as an empty turf
+ desc = "A broken piece of disposal pipe."
+
+ New()
+ ..()
+ update()
+ return
+
+ // called when welded
+ // for broken pipe, remove and turn into scrap
+
+ welded()
+// var/obj/item/scrap/S = new(src.loc)
+// S.set_components(200,0,0)
+ del(src)
+
+// the disposal outlet machine
+
+/obj/structure/disposaloutlet
+ name = "disposal outlet"
+ desc = "An outlet for the pneumatic disposal system."
+ icon = 'icons/obj/pipes/disposal.dmi'
+ icon_state = "outlet"
+ density = 1
+ anchored = 1
+ var/active = 0
+ var/turf/target // this will be where the output objects are 'thrown' to.
+ var/mode = 0
+ var/start_eject = 0
+ var/eject_range = 2
+
+ New()
+ ..()
+
+ spawn(1)
+ target = get_ranged_target_turf(src, dir, 10)
+
+
+ var/obj/structure/disposalpipe/trunk/trunk = locate() in src.loc
+ if(trunk)
+ trunk.linked = src // link the pipe trunk to self
+
+ // expel the contents of the holder object, then delete it
+ // called when the holder exits the outlet
+ proc/expel(var/obj/structure/disposalholder/H)
+
+ flick("outlet-open", src)
+ if((start_eject + 30) < world.time)
+ start_eject = world.time
+ playsound(src, 'sound/machines/warning-buzzer.ogg', 50, 0, 0)
+ sleep(20)
+ playsound(src, 'sound/machines/hiss.ogg', 50, 0, 0)
+ else
+ sleep(20)
+ if(H)
+ for(var/atom/movable/AM in H)
+ AM.loc = src.loc
+ AM.pipe_eject(dir)
+ spawn(5)
+ if(AM)
+ AM.throw_at(target, eject_range, 1)
+ H.vent_gas(src.loc)
+ del(H)
+ return
+
+ attackby(var/obj/item/I, var/mob/user)
+ if(!I || !user)
+ return
+ src.add_fingerprint(user)
+ if(istype(I, /obj/item/weapon/screwdriver))
+ if(mode==0)
+ mode=1
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ user << "You remove the screws around the power connection."
+ return
+ else if(mode==1)
+ mode=0
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ user << "You attach the screws around the power connection."
+ return
+ else if(istype(I,/obj/item/weapon/weldingtool) && mode==1)
+ var/obj/item/weapon/weldingtool/W = I
+ if(W.remove_fuel(0,user))
+ playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
+ user << "You start slicing the floorweld off \the [src]."
+ if(do_after(user,20))
+ if(!src || !W.isOn()) return
+ user << "You slice the floorweld off \the [src]."
+ var/obj/structure/disposalconstruct/C = new (src.loc)
+ src.transfer_fingerprints_to(C)
+ C.ptype = 7 // 7 = outlet
+ C.update()
+ C.anchored = 1
+ C.density = 1
+ del(src)
+ return
+ else
+ user << "You need more welding fuel to complete this task."
+ return
+
+
+
+// called when movable is expelled from a disposal pipe or outlet
+// by default does nothing, override for special behaviour
+
+/atom/movable/proc/pipe_eject(var/direction)
+ return
+
+// check if mob has client, if so restore client view on eject
+/mob/pipe_eject(var/direction)
+ if (src.client)
+ src.client.perspective = MOB_PERSPECTIVE
+ src.client.eye = src
+
+ return
+
+/obj/effect/decal/cleanable/blood/gibs/pipe_eject(var/direction)
+ var/list/dirs
+ if(direction)
+ dirs = list( direction, turn(direction, -45), turn(direction, 45))
+ else
+ dirs = alldirs.Copy()
+
+ src.streak(dirs)
+
+/obj/effect/decal/cleanable/robot_debris/gib/pipe_eject(var/direction)
+ var/list/dirs
+ if(direction)
+ dirs = list( direction, turn(direction, -45), turn(direction, 45))
+ else
+ dirs = alldirs.Copy()
+
+ src.streak(dirs)
diff --git a/code/modules/research/server.dm b/code/modules/research/server.dm
index 11279e3db07..b0989b6570c 100644
--- a/code/modules/research/server.dm
+++ b/code/modules/research/server.dm
@@ -1,343 +1,343 @@
-/obj/machinery/r_n_d/server
- name = "R&D Server"
- icon = 'icons/obj/machines/research.dmi'
- icon_state = "server"
- var/datum/research/files
- var/health = 100
- var/list/id_with_upload = list() //List of R&D consoles with upload to server access.
- var/list/id_with_download = list() //List of R&D consoles with download from server access.
- var/id_with_upload_string = "" //String versions for easy editing in map editor.
- var/id_with_download_string = ""
- var/server_id = 0
- var/heat_gen = 100
- var/heating_power = 40000
- var/delay = 10
- req_access = list(access_rd) //Only the R&D can change server settings.
-
-/obj/machinery/r_n_d/server/New()
- ..()
- component_parts = list()
- component_parts += new /obj/item/weapon/circuitboard/rdserver(null)
- component_parts += new /obj/item/weapon/stock_parts/scanning_module(null)
- component_parts += new /obj/item/stack/cable_coil(null, 1)
- component_parts += new /obj/item/stack/cable_coil(null, 1)
- RefreshParts()
- src.initialize(); //Agouri
-
-/obj/machinery/r_n_d/server/Del()
- griefProtection()
- ..()
-
-/obj/machinery/r_n_d/server/RefreshParts()
- var/tot_rating = 0
- for(var/obj/item/weapon/stock_parts/SP in src)
- tot_rating += SP.rating
- heat_gen /= max(1, tot_rating)
-
-/obj/machinery/r_n_d/server/initialize()
- if(!files) files = new /datum/research(src)
- var/list/temp_list
- if(!id_with_upload.len)
- temp_list = list()
- temp_list = text2list(id_with_upload_string, ";")
- for(var/N in temp_list)
- id_with_upload += text2num(N)
- if(!id_with_download.len)
- temp_list = list()
- temp_list = text2list(id_with_download_string, ";")
- for(var/N in temp_list)
- id_with_download += text2num(N)
-
-/obj/machinery/r_n_d/server/process()
- var/datum/gas_mixture/environment = loc.return_air()
- switch(environment.temperature)
- if(0 to T0C)
- health = min(100, health + 1)
- if(T0C to (T20C + 20))
- health = Clamp(health, 0, 100)
- if((T20C + 20) to (T0C + 70))
- health = max(0, health - 1)
- if(health <= 0)
- /*griefProtection() This seems to get called twice before running any code that deletes/damages the server or it's files anwyay.
- refreshParts and the hasReq procs that get called by this are laggy and do not need to be called by every server on the map every tick */
- var/updateRD = 0
- files.known_designs = list()
- for(var/datum/tech/T in files.known_tech)
- if(prob(1))
- updateRD++
- T.level--
- if(updateRD)
- files.RefreshResearch()
- if(delay)
- delay--
- else
- produce_heat(heat_gen)
- delay = initial(delay)
-
-/obj/machinery/r_n_d/server/meteorhit(var/obj/O as obj)
- griefProtection()
- ..()
-
-
-/obj/machinery/r_n_d/server/emp_act(severity)
- griefProtection()
- ..()
-
-
-/obj/machinery/r_n_d/server/ex_act(severity)
- griefProtection()
- ..()
-
-
-/obj/machinery/r_n_d/server/blob_act()
- griefProtection()
- ..()
-
-
-
-//Backup files to centcom to help admins recover data after greifer attacks
-/obj/machinery/r_n_d/server/proc/griefProtection()
- for(var/obj/machinery/r_n_d/server/centcom/C in world)
- for(var/datum/tech/T in files.known_tech)
- C.files.AddTech2Known(T)
- for(var/datum/design/D in files.known_designs)
- C.files.AddDesign2Known(D)
- C.files.RefreshResearch()
-
-/obj/machinery/r_n_d/server/proc/produce_heat(heat_amt)
- if(!(stat & (NOPOWER|BROKEN))) //Blatently stolen from space heater.
- var/turf/simulated/L = loc
- if(istype(L))
- var/datum/gas_mixture/env = L.return_air()
- if(env.temperature < (heat_amt+T0C))
-
- var/transfer_moles = 0.25 * env.total_moles()
-
- var/datum/gas_mixture/removed = env.remove(transfer_moles)
-
- if(removed)
-
- var/heat_capacity = removed.heat_capacity()
- if(heat_capacity == 0 || heat_capacity == null)
- heat_capacity = 1
- removed.temperature = min((removed.temperature*heat_capacity + heating_power)/heat_capacity, 1000)
-
- env.merge(removed)
- air_update_turf()
-
-/obj/machinery/r_n_d/server/attackby(var/obj/item/O as obj, var/mob/user as mob)
- if (disabled)
- return
- if (shocked)
- shock(user,50)
- if (istype(O, /obj/item/weapon/screwdriver))
- default_deconstruction_screwdriver(user, "server_o", "server")
- return
- if (panel_open)
- if(istype(O, /obj/item/weapon/crowbar))
- griefProtection()
- default_deconstruction_crowbar()
- return 1
-
-/obj/machinery/r_n_d/server/attack_hand(mob/user as mob) // I guess only exists to stop ninjas or hell does it even work I dunno. See also ninja gloves.
- if (disabled)
- return
- if (shocked)
- shock(user,50)
- return
-
-/obj/machinery/r_n_d/server/centcom
- name = "Centcom Central R&D Database"
- server_id = -1
-
-/obj/machinery/r_n_d/server/centcom/initialize()
- ..()
- var/list/no_id_servers = list()
- var/list/server_ids = list()
- for(var/obj/machinery/r_n_d/server/S in world)
- switch(S.server_id)
- if(-1)
- continue
- if(0)
- no_id_servers += S
- else
- server_ids += S.server_id
-
- for(var/obj/machinery/r_n_d/server/S in no_id_servers)
- var/num = 1
- while(!S.server_id)
- if(num in server_ids)
- num++
- else
- S.server_id = num
- server_ids += num
- no_id_servers -= S
-
-/obj/machinery/r_n_d/server/centcom/process()
- return PROCESS_KILL //don't need process()
-
-
-/obj/machinery/computer/rdservercontrol
- name = "R&D Server Controller"
- icon_state = "rdcomp"
- var/screen = 0
- var/obj/machinery/r_n_d/server/temp_server
- var/list/servers = list()
- var/list/consoles = list()
- var/badmin = 0
- circuit = /obj/item/weapon/circuitboard/rdservercontrol
-
-/obj/machinery/computer/rdservercontrol/Topic(href, href_list)
- if(..())
- return
-
- add_fingerprint(usr)
- usr.set_machine(src)
- if(!src.allowed(usr) && !emagged)
- usr << "\red You do not have the required access level"
- return
-
- if(href_list["main"])
- screen = 0
-
- else if(href_list["access"] || href_list["data"] || href_list["transfer"])
- temp_server = null
- consoles = list()
- servers = list()
- for(var/obj/machinery/r_n_d/server/S in world)
- if(S.server_id == text2num(href_list["access"]) || S.server_id == text2num(href_list["data"]) || S.server_id == text2num(href_list["transfer"]))
- temp_server = S
- break
- if(href_list["access"])
- screen = 1
- for(var/obj/machinery/computer/rdconsole/C in world)
- if(C.sync)
- consoles += C
- else if(href_list["data"])
- screen = 2
- else if(href_list["transfer"])
- screen = 3
- for(var/obj/machinery/r_n_d/server/S in world)
- if(S == src)
- continue
- servers += S
-
- else if(href_list["upload_toggle"])
- var/num = text2num(href_list["upload_toggle"])
- if(num in temp_server.id_with_upload)
- temp_server.id_with_upload -= num
- else
- temp_server.id_with_upload += num
-
- else if(href_list["download_toggle"])
- var/num = text2num(href_list["download_toggle"])
- if(num in temp_server.id_with_download)
- temp_server.id_with_download -= num
- else
- temp_server.id_with_download += num
-
- else if(href_list["reset_tech"])
- var/choice = alert("Technology Data Rest", "Are you sure you want to reset this technology to its default data? Data lost cannot be recovered.", "Continue", "Cancel")
- if(choice == "Continue")
- for(var/datum/tech/T in temp_server.files.known_tech)
- if(T.id == href_list["reset_tech"])
- T.level = 1
- break
- temp_server.files.RefreshResearch()
-
- else if(href_list["reset_design"])
- var/choice = alert("Design Data Deletion", "Are you sure you want to delete this design? If you still have the prerequisites for the design, it'll reset to its base reliability. Data lost cannot be recovered.", "Continue", "Cancel")
- if(choice == "Continue")
- for(var/datum/design/D in temp_server.files.known_designs)
- if(D.id == href_list["reset_design"])
- temp_server.files.known_designs -= D
- break
- temp_server.files.RefreshResearch()
-
- updateUsrDialog()
- return
-
-/obj/machinery/computer/rdservercontrol/attack_hand(mob/user as mob)
- if(..())
- return
- user.set_machine(src)
- var/dat = ""
-
- switch(screen)
- if(0) //Main Menu
- dat += "Connected Servers:
"
-
- for(var/obj/machinery/r_n_d/server/S in world)
- if(istype(S, /obj/machinery/r_n_d/server/centcom) && !badmin)
- continue
- dat += "[S.name] || "
- dat += " Access Rights | "
- dat += "Data Management"
- if(badmin) dat += " | Server-to-Server Transfer"
- dat += "
"
-
- if(1) //Access rights menu
- dat += "[temp_server.name] Access Rights
"
- dat += "Consoles with Upload Access
"
- for(var/obj/machinery/computer/rdconsole/C in consoles)
- var/turf/console_turf = get_turf(C)
- dat += "* [console_turf.loc]" //FYI, these are all numeric ids, eventually.
- if(C.id in temp_server.id_with_upload)
- dat += " (Remove)
"
- else
- dat += " (Add)
"
- dat += "Consoles with Download Access
"
- for(var/obj/machinery/computer/rdconsole/C in consoles)
- var/turf/console_turf = get_turf(C)
- dat += "* [console_turf.loc]"
- if(C.id in temp_server.id_with_download)
- dat += " (Remove)
"
- else
- dat += " (Add)
"
- dat += "
Main Menu"
-
- if(2) //Data Management menu
- dat += "[temp_server.name] Data ManagementP
"
- dat += "Known Technologies
"
- for(var/datum/tech/T in temp_server.files.known_tech)
- dat += "* [T.name] "
- dat += "(Reset)
" //FYI, these are all strings.
- dat += "Known Designs
"
- for(var/datum/design/D in temp_server.files.known_designs)
- dat += "* [D.name] "
- dat += "(Delete)
"
- dat += "
Main Menu"
-
- if(3) //Server Data Transfer
- dat += "[temp_server.name] Server to Server Transfer
"
- dat += "Send Data to what server?
"
- for(var/obj/machinery/r_n_d/server/S in servers)
- dat += "[S.name] (Transfer)
"
- dat += "
Main Menu"
- user << browse("R&D Server Control
[dat]", "window=server_control;size=575x400")
- onclose(user, "server_control")
- return
-
-/obj/machinery/computer/rdservercontrol/attackby(var/obj/item/weapon/D as obj, var/mob/user as mob)
- if(istype(D, /obj/item/weapon/card/emag) && !emagged)
- playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1)
- emagged = 1
- user << "\blue You you disable the security protocols"
- else
- ..()
- src.updateUsrDialog()
- return
-
-
-/obj/machinery/r_n_d/server/robotics
- name = "Robotics R&D Server"
- id_with_upload_string = "1;2"
- id_with_download_string = "1;2"
- server_id = 2
-
-
-/obj/machinery/r_n_d/server/core
- name = "Core R&D Server"
- id_with_upload_string = "1"
- id_with_download_string = "1"
+/obj/machinery/r_n_d/server
+ name = "R&D Server"
+ icon = 'icons/obj/machines/research.dmi'
+ icon_state = "server"
+ var/datum/research/files
+ var/health = 100
+ var/list/id_with_upload = list() //List of R&D consoles with upload to server access.
+ var/list/id_with_download = list() //List of R&D consoles with download from server access.
+ var/id_with_upload_string = "" //String versions for easy editing in map editor.
+ var/id_with_download_string = ""
+ var/server_id = 0
+ var/heat_gen = 100
+ var/heating_power = 40000
+ var/delay = 10
+ req_access = list(access_rd) //Only the R&D can change server settings.
+
+/obj/machinery/r_n_d/server/New()
+ ..()
+ component_parts = list()
+ component_parts += new /obj/item/weapon/circuitboard/rdserver(null)
+ component_parts += new /obj/item/weapon/stock_parts/scanning_module(null)
+ component_parts += new /obj/item/stack/cable_coil(null, 1)
+ component_parts += new /obj/item/stack/cable_coil(null, 1)
+ RefreshParts()
+ src.initialize(); //Agouri
+
+/obj/machinery/r_n_d/server/Del()
+ griefProtection()
+ ..()
+
+/obj/machinery/r_n_d/server/RefreshParts()
+ var/tot_rating = 0
+ for(var/obj/item/weapon/stock_parts/SP in src)
+ tot_rating += SP.rating
+ heat_gen /= max(1, tot_rating)
+
+/obj/machinery/r_n_d/server/initialize()
+ if(!files) files = new /datum/research(src)
+ var/list/temp_list
+ if(!id_with_upload.len)
+ temp_list = list()
+ temp_list = text2list(id_with_upload_string, ";")
+ for(var/N in temp_list)
+ id_with_upload += text2num(N)
+ if(!id_with_download.len)
+ temp_list = list()
+ temp_list = text2list(id_with_download_string, ";")
+ for(var/N in temp_list)
+ id_with_download += text2num(N)
+
+/obj/machinery/r_n_d/server/process()
+ var/datum/gas_mixture/environment = loc.return_air()
+ switch(environment.temperature)
+ if(0 to T0C)
+ health = min(100, health + 1)
+ if(T0C to (T20C + 20))
+ health = Clamp(health, 0, 100)
+ if((T20C + 20) to (T0C + 70))
+ health = max(0, health - 1)
+ if(health <= 0)
+ /*griefProtection() This seems to get called twice before running any code that deletes/damages the server or it's files anwyay.
+ refreshParts and the hasReq procs that get called by this are laggy and do not need to be called by every server on the map every tick */
+ var/updateRD = 0
+ files.known_designs = list()
+ for(var/datum/tech/T in files.known_tech)
+ if(prob(1))
+ updateRD++
+ T.level--
+ if(updateRD)
+ files.RefreshResearch()
+ if(delay)
+ delay--
+ else
+ produce_heat(heat_gen)
+ delay = initial(delay)
+
+/obj/machinery/r_n_d/server/meteorhit(var/obj/O as obj)
+ griefProtection()
+ ..()
+
+
+/obj/machinery/r_n_d/server/emp_act(severity)
+ griefProtection()
+ ..()
+
+
+/obj/machinery/r_n_d/server/ex_act(severity)
+ griefProtection()
+ ..()
+
+
+/obj/machinery/r_n_d/server/blob_act()
+ griefProtection()
+ ..()
+
+
+
+//Backup files to centcom to help admins recover data after greifer attacks
+/obj/machinery/r_n_d/server/proc/griefProtection()
+ for(var/obj/machinery/r_n_d/server/centcom/C in world)
+ for(var/datum/tech/T in files.known_tech)
+ C.files.AddTech2Known(T)
+ for(var/datum/design/D in files.known_designs)
+ C.files.AddDesign2Known(D)
+ C.files.RefreshResearch()
+
+/obj/machinery/r_n_d/server/proc/produce_heat(heat_amt)
+ if(!(stat & (NOPOWER|BROKEN))) //Blatently stolen from space heater.
+ var/turf/simulated/L = loc
+ if(istype(L))
+ var/datum/gas_mixture/env = L.return_air()
+ if(env.temperature < (heat_amt+T0C))
+
+ var/transfer_moles = 0.25 * env.total_moles()
+
+ var/datum/gas_mixture/removed = env.remove(transfer_moles)
+
+ if(removed)
+
+ var/heat_capacity = removed.heat_capacity()
+ if(heat_capacity == 0 || heat_capacity == null)
+ heat_capacity = 1
+ removed.temperature = min((removed.temperature*heat_capacity + heating_power)/heat_capacity, 1000)
+
+ env.merge(removed)
+ air_update_turf()
+
+/obj/machinery/r_n_d/server/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if (disabled)
+ return
+ if (shocked)
+ shock(user,50)
+ if (istype(O, /obj/item/weapon/screwdriver))
+ default_deconstruction_screwdriver(user, "server_o", "server")
+ return
+ if (panel_open)
+ if(istype(O, /obj/item/weapon/crowbar))
+ griefProtection()
+ default_deconstruction_crowbar()
+ return 1
+
+/obj/machinery/r_n_d/server/attack_hand(mob/user as mob) // I guess only exists to stop ninjas or hell does it even work I dunno. See also ninja gloves.
+ if (disabled)
+ return
+ if (shocked)
+ shock(user,50)
+ return
+
+/obj/machinery/r_n_d/server/centcom
+ name = "Centcom Central R&D Database"
+ server_id = -1
+
+/obj/machinery/r_n_d/server/centcom/initialize()
+ ..()
+ var/list/no_id_servers = list()
+ var/list/server_ids = list()
+ for(var/obj/machinery/r_n_d/server/S in world)
+ switch(S.server_id)
+ if(-1)
+ continue
+ if(0)
+ no_id_servers += S
+ else
+ server_ids += S.server_id
+
+ for(var/obj/machinery/r_n_d/server/S in no_id_servers)
+ var/num = 1
+ while(!S.server_id)
+ if(num in server_ids)
+ num++
+ else
+ S.server_id = num
+ server_ids += num
+ no_id_servers -= S
+
+/obj/machinery/r_n_d/server/centcom/process()
+ return PROCESS_KILL //don't need process()
+
+
+/obj/machinery/computer/rdservercontrol
+ name = "R&D Server Controller"
+ icon_state = "rdcomp"
+ var/screen = 0
+ var/obj/machinery/r_n_d/server/temp_server
+ var/list/servers = list()
+ var/list/consoles = list()
+ var/badmin = 0
+ circuit = /obj/item/weapon/circuitboard/rdservercontrol
+
+/obj/machinery/computer/rdservercontrol/Topic(href, href_list)
+ if(..())
+ return
+
+ add_fingerprint(usr)
+ usr.set_machine(src)
+ if(!src.allowed(usr) && !emagged)
+ usr << "\red You do not have the required access level"
+ return
+
+ if(href_list["main"])
+ screen = 0
+
+ else if(href_list["access"] || href_list["data"] || href_list["transfer"])
+ temp_server = null
+ consoles = list()
+ servers = list()
+ for(var/obj/machinery/r_n_d/server/S in world)
+ if(S.server_id == text2num(href_list["access"]) || S.server_id == text2num(href_list["data"]) || S.server_id == text2num(href_list["transfer"]))
+ temp_server = S
+ break
+ if(href_list["access"])
+ screen = 1
+ for(var/obj/machinery/computer/rdconsole/C in world)
+ if(C.sync)
+ consoles += C
+ else if(href_list["data"])
+ screen = 2
+ else if(href_list["transfer"])
+ screen = 3
+ for(var/obj/machinery/r_n_d/server/S in world)
+ if(S == src)
+ continue
+ servers += S
+
+ else if(href_list["upload_toggle"])
+ var/num = text2num(href_list["upload_toggle"])
+ if(num in temp_server.id_with_upload)
+ temp_server.id_with_upload -= num
+ else
+ temp_server.id_with_upload += num
+
+ else if(href_list["download_toggle"])
+ var/num = text2num(href_list["download_toggle"])
+ if(num in temp_server.id_with_download)
+ temp_server.id_with_download -= num
+ else
+ temp_server.id_with_download += num
+
+ else if(href_list["reset_tech"])
+ var/choice = alert("Technology Data Rest", "Are you sure you want to reset this technology to its default data? Data lost cannot be recovered.", "Continue", "Cancel")
+ if(choice == "Continue")
+ for(var/datum/tech/T in temp_server.files.known_tech)
+ if(T.id == href_list["reset_tech"])
+ T.level = 1
+ break
+ temp_server.files.RefreshResearch()
+
+ else if(href_list["reset_design"])
+ var/choice = alert("Design Data Deletion", "Are you sure you want to delete this design? If you still have the prerequisites for the design, it'll reset to its base reliability. Data lost cannot be recovered.", "Continue", "Cancel")
+ if(choice == "Continue")
+ for(var/datum/design/D in temp_server.files.known_designs)
+ if(D.id == href_list["reset_design"])
+ temp_server.files.known_designs -= D
+ break
+ temp_server.files.RefreshResearch()
+
+ updateUsrDialog()
+ return
+
+/obj/machinery/computer/rdservercontrol/attack_hand(mob/user as mob)
+ if(..())
+ return
+ user.set_machine(src)
+ var/dat = ""
+
+ switch(screen)
+ if(0) //Main Menu
+ dat += "Connected Servers:
"
+
+ for(var/obj/machinery/r_n_d/server/S in world)
+ if(istype(S, /obj/machinery/r_n_d/server/centcom) && !badmin)
+ continue
+ dat += "[S.name] || "
+ dat += " Access Rights | "
+ dat += "Data Management"
+ if(badmin) dat += " | Server-to-Server Transfer"
+ dat += "
"
+
+ if(1) //Access rights menu
+ dat += "[temp_server.name] Access Rights
"
+ dat += "Consoles with Upload Access
"
+ for(var/obj/machinery/computer/rdconsole/C in consoles)
+ var/turf/console_turf = get_turf(C)
+ dat += "* [console_turf.loc]" //FYI, these are all numeric ids, eventually.
+ if(C.id in temp_server.id_with_upload)
+ dat += " (Remove)
"
+ else
+ dat += " (Add)
"
+ dat += "Consoles with Download Access
"
+ for(var/obj/machinery/computer/rdconsole/C in consoles)
+ var/turf/console_turf = get_turf(C)
+ dat += "* [console_turf.loc]"
+ if(C.id in temp_server.id_with_download)
+ dat += " (Remove)
"
+ else
+ dat += " (Add)
"
+ dat += "
Main Menu"
+
+ if(2) //Data Management menu
+ dat += "[temp_server.name] Data ManagementP
"
+ dat += "Known Technologies
"
+ for(var/datum/tech/T in temp_server.files.known_tech)
+ dat += "* [T.name] "
+ dat += "(Reset)
" //FYI, these are all strings.
+ dat += "Known Designs
"
+ for(var/datum/design/D in temp_server.files.known_designs)
+ dat += "* [D.name] "
+ dat += "(Delete)
"
+ dat += "
Main Menu"
+
+ if(3) //Server Data Transfer
+ dat += "[temp_server.name] Server to Server Transfer
"
+ dat += "Send Data to what server?
"
+ for(var/obj/machinery/r_n_d/server/S in servers)
+ dat += "[S.name] (Transfer)
"
+ dat += "
Main Menu"
+ user << browse("R&D Server Control
[dat]", "window=server_control;size=575x400")
+ onclose(user, "server_control")
+ return
+
+/obj/machinery/computer/rdservercontrol/attackby(var/obj/item/weapon/D as obj, var/mob/user as mob)
+ if(istype(D, /obj/item/weapon/card/emag) && !emagged)
+ playsound(src.loc, 'sound/effects/sparks4.ogg', 75, 1)
+ emagged = 1
+ user << "\blue You you disable the security protocols"
+ else
+ ..()
+ src.updateUsrDialog()
+ return
+
+
+/obj/machinery/r_n_d/server/robotics
+ name = "Robotics R&D Server"
+ id_with_upload_string = "1;2"
+ id_with_download_string = "1;2"
+ server_id = 2
+
+
+/obj/machinery/r_n_d/server/core
+ name = "Core R&D Server"
+ id_with_upload_string = "1"
+ id_with_download_string = "1"
server_id = 1
\ No newline at end of file
diff --git a/code/modules/surgery/generic_steps.dm b/code/modules/surgery/generic_steps.dm
index 700d2b87e59..ea066277ed3 100644
--- a/code/modules/surgery/generic_steps.dm
+++ b/code/modules/surgery/generic_steps.dm
@@ -1,68 +1,68 @@
-
-//make incision
-/datum/surgery_step/incise
- implements = list(/obj/item/weapon/scalpel = 100, /obj/item/weapon/kitchenknife = 65, /obj/item/weapon/shard = 45)
- time = 24
-
-/datum/surgery_step/incise/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
- user.visible_message("[user] begins to make an incision in [target]'s [parse_zone(target_zone)].")
-
-
-
-//clamp bleeders
-/datum/surgery_step/clamp_bleeders
- implements = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/wirecutters = 60, /obj/item/stack/cable_coil = 15)
- time = 48
-
-/datum/surgery_step/clamp_bleeders/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
- user.visible_message("[user] begins to clamp bleeders in [target]'s [parse_zone(target_zone)].")
-
-
-//retract skin
-/datum/surgery_step/retract_skin
- implements = list(/obj/item/weapon/retractor = 100, /obj/item/weapon/screwdriver = 45, /obj/item/weapon/wirecutters = 35)
- time = 32
-
-/datum/surgery_step/retract_skin/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
- user.visible_message("[user] begins to retract the skin in [target]'s [parse_zone(target_zone)].")
-
-
-
-//close incision
-/datum/surgery_step/close
- implements = list(/obj/item/weapon/cautery = 100, /obj/item/weapon/weldingtool = 70, /obj/item/weapon/lighter = 45, /obj/item/weapon/match = 20)
- time = 32
-
-/datum/surgery_step/close/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
- user.visible_message("[user] begins to mend the incision in [target]'s [parse_zone(target_zone)].")
-
-
-/datum/surgery_step/close/tool_check(mob/user, obj/item/tool)
- if(istype(tool, /obj/item/weapon/cautery))
- return 1
-
- if(istype(tool, /obj/item/weapon/weldingtool))
- var/obj/item/weapon/weldingtool/WT = tool
- if(WT.isOn()) return 1
-
- else if(istype(tool, /obj/item/weapon/lighter))
- var/obj/item/weapon/lighter/L = tool
- if(L.lit) return 1
-
- else if(istype(tool, /obj/item/weapon/match))
- var/obj/item/weapon/match/M = tool
- if(M.lit) return 1
-
- return 0
-
-
-//saw bone
-/datum/surgery_step/saw
- implements = list(/obj/item/weapon/circular_saw = 100, /obj/item/weapon/melee/arm_blade = 75, /obj/item/weapon/hatchet = 35, /obj/item/weapon/butch = 25)
- time = 64
-
-/datum/surgery_step/saw/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
- user.visible_message("[user] begins to saw through the bone in [target]'s [parse_zone(target_zone)].")
-
-
-
+
+//make incision
+/datum/surgery_step/incise
+ implements = list(/obj/item/weapon/scalpel = 100, /obj/item/weapon/kitchenknife = 65, /obj/item/weapon/shard = 45)
+ time = 24
+
+/datum/surgery_step/incise/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ user.visible_message("[user] begins to make an incision in [target]'s [parse_zone(target_zone)].")
+
+
+
+//clamp bleeders
+/datum/surgery_step/clamp_bleeders
+ implements = list(/obj/item/weapon/hemostat = 100, /obj/item/weapon/wirecutters = 60, /obj/item/stack/cable_coil = 15)
+ time = 48
+
+/datum/surgery_step/clamp_bleeders/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ user.visible_message("[user] begins to clamp bleeders in [target]'s [parse_zone(target_zone)].")
+
+
+//retract skin
+/datum/surgery_step/retract_skin
+ implements = list(/obj/item/weapon/retractor = 100, /obj/item/weapon/screwdriver = 45, /obj/item/weapon/wirecutters = 35)
+ time = 32
+
+/datum/surgery_step/retract_skin/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ user.visible_message("[user] begins to retract the skin in [target]'s [parse_zone(target_zone)].")
+
+
+
+//close incision
+/datum/surgery_step/close
+ implements = list(/obj/item/weapon/cautery = 100, /obj/item/weapon/weldingtool = 70, /obj/item/weapon/lighter = 45, /obj/item/weapon/match = 20)
+ time = 32
+
+/datum/surgery_step/close/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ user.visible_message("[user] begins to mend the incision in [target]'s [parse_zone(target_zone)].")
+
+
+/datum/surgery_step/close/tool_check(mob/user, obj/item/tool)
+ if(istype(tool, /obj/item/weapon/cautery))
+ return 1
+
+ if(istype(tool, /obj/item/weapon/weldingtool))
+ var/obj/item/weapon/weldingtool/WT = tool
+ if(WT.isOn()) return 1
+
+ else if(istype(tool, /obj/item/weapon/lighter))
+ var/obj/item/weapon/lighter/L = tool
+ if(L.lit) return 1
+
+ else if(istype(tool, /obj/item/weapon/match))
+ var/obj/item/weapon/match/M = tool
+ if(M.lit) return 1
+
+ return 0
+
+
+//saw bone
+/datum/surgery_step/saw
+ implements = list(/obj/item/weapon/circular_saw = 100, /obj/item/weapon/melee/arm_blade = 75, /obj/item/weapon/hatchet = 35, /obj/item/weapon/butch = 25)
+ time = 64
+
+/datum/surgery_step/saw/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ user.visible_message("[user] begins to saw through the bone in [target]'s [parse_zone(target_zone)].")
+
+
+
diff --git a/code/unused/Agouri_stuff.dm b/code/unused/Agouri_stuff.dm
index 3844884fe05..b567de3b53e 100644
--- a/code/unused/Agouri_stuff.dm
+++ b/code/unused/Agouri_stuff.dm
@@ -1,1949 +1,1949 @@
-/*
-/obj/vehicle/airtight
- //inner atmos
- var/use_internal_tank = 0
- var/internal_tank_valve = ONE_ATMOSPHERE
- var/obj/machinery/portable_atmospherics/canister/internal_tank
- var/datum/gas_mixture/cabin_air
- var/obj/machinery/atmospherics/portables_connector/connected_port = null
-
- 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
-
-
-/obj/vehicle/airtight/New()
- ..()
- src.add_airtank()
- src.add_cabin()
- src.add_airtight_iterators()
-
-
-
-
-//######################################### Helpers for airtight vehicles #########################################
-
-/obj/vehicle/airtight/proc/add_cabin()
- cabin_air = new
- cabin_air.temperature = T20C
- cabin_air.volume = 200
- cabin_air.oxygen = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
- cabin_air.nitrogen = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
- return cabin_air
-
-/obj/vehicle/airtight/proc/add_airtank()
- internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src)
- return internal_tank
-
-/obj/vehicle/airtight/proc/add_airtight_iterators()
- pr_int_temp_processor = new /datum/global_iterator/vehicle_preserve_temp(list(src))
- pr_give_air = new /datum/global_iterator/vehicle_tank_give_air(list(src))
-
-
-//######################################### Specific datums for airtight vehicles #################################
-
-
-/datum/global_iterator/vehicle_preserve_temp //normalizing cabin air temperature to 20 degrees celsium
- delay = 20
-
- process(var/obj/vehicle/airtight/V)
- if(V.cabin_air && V.cabin_air.return_volume() > 0)
- var/delta = V.cabin_air.temperature - T20C
- V.cabin_air.temperature -= max(-10, min(10, round(delta/4,0.1)))
- return
-
-
-/datum/global_iterator/vehicle_tank_give_air
- delay = 15
-
- process(var/obj/vehicle/airtight/V)
- if(V.internal_tank)
- var/datum/gas_mixture/tank_air = V.internal_tank.return_air()
- var/datum/gas_mixture/cabin_air = V.cabin_air
-
- var/release_pressure = V.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 = V.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
- del(removed)
- else
- return stop()
- return
-
-
-//######################################### Atmospherics for vehicles #############################################
-
-
-/obj/vehicle/proc/get_turf_air()
- var/turf/T = get_turf(src)
- if(T)
- . = T.return_air()
- return
-
-/obj/vehicle/airtight/remove_air(amount)
- if(use_internal_tank)
- return cabin_air.remove(amount)
- else
- var/turf/T = get_turf(src)
- if(T)
- return T.remove_air(amount)
- return
-
-/obj/vehicle/airtight/return_air()
- if(use_internal_tank)
- return cabin_air
- return get_turf_air()
-
-/obj/vehicle/airtight/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
-
-
-/obj/vehicle/airtight/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
-
-/obj/vehicle/airtight/proc/connect(obj/machinery/atmospherics/portables_connector/new_port)
- //Make sure not already connected to something else
- if(connected_port || !new_port || new_port.connected_device)
- return 0
-
- //Make sure are close enough for a valid connection
- if(new_port.loc != src.loc)
- return 0
-
- //Perform the connection
- connected_port = new_port
- connected_port.connected_device = src
-
- //Actually enforce the air sharing
- var/datum/pipe_network/network = connected_port.return_network(src)
- if(network && !(internal_tank.return_air() in network.gases))
- network.gases += internal_tank.return_air()
- network.update = 1
- log_message("Vehicle airtank connected to external port.")
- return 1
-
-/obj/vehicle/airtight/proc/disconnect()
- if(!connected_port)
- return 0
-
- var/datum/pipe_network/network = connected_port.return_network(src)
- if(network)
- network.gases -= internal_tank.return_air()
-
- connected_port.connected_device = null
- connected_port = null
- src.log_message("Vehicle airtank disconnected from external port.")
- return 1
-
-
-
-
-/////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////
-
-
-
-/obj/vehicle
- name = "Vehicle"
- icon = 'icons/vehicles/vehicles.dmi'
- density = 1
- anchored = 1
- unacidable = 1 //To avoid the pilot-deleting shit that came with mechas
- layer = MOB_LAYER
- //var/can_move = 1
- var/mob/living/carbon/occupant = null
- //var/step_in = 10 //make a step in step_in/10 sec.
- //var/dir_in = 2//What direction will the mech face when entered/powered on? Defaults to South.
- //var/step_energy_drain = 10
- var/health = 300 //health is health
- //var/deflect_chance = 10 //chance to deflect the incoming projectiles, hits, or lesser the effect of ex_act.
- //the values in this list show how much damage will pass through, not how much will be absorbed.
- var/list/damage_absorption = list("brute"=0.8,"fire"=1.2,"bullet"=0.9,"laser"=1,"energy"=1,"bomb"=1)
- var/obj/item/weapon/cell/cell //Our power source
- var/state = 0
- var/list/log = new
- var/last_message = 0
- var/add_req_access = 1
- var/maint_access = 1
- //var/dna //dna-locking the mech
- var/list/proc_res = list() //stores proc owners, like proc_res["functionname"] = owner reference
- var/datum/effect/effect/system/spark_spread/spark_system = new
- var/lights = 0
- var/lights_power = 6
-
- //inner atmos //These go in airtight.dm, not all vehicles are space-faring -Agouri
- //var/use_internal_tank = 0
- //var/internal_tank_valve = ONE_ATMOSPHERE
- //var/obj/machinery/portable_atmospherics/canister/internal_tank
- //var/datum/gas_mixture/cabin_air
- //var/obj/machinery/atmospherics/portables_connector/connected_port = null
-
- var/obj/item/device/radio/radio = null
-
- var/max_temperature = 2500
- //var/internal_damage_threshold = 50 //health percentage below which internal damage is possible
- var/internal_damage = 0 //contains bitflags
-
- 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 //In airtight.dm you go -Agouri
- var/datum/global_iterator/pr_inertial_movement //controls intertial movement in spesss
-
- //var/datum/global_iterator/pr_give_air //moves air from tank to cabin //Y-you too -Agouri
-
- var/datum/global_iterator/pr_internal_damage //processes internal damage
-
-
- var/wreckage
-
- var/list/equipment = new
- var/obj/selected
- //var/max_equip = 3
-
- var/datum/events/events
-
-
-
-/obj/vehicle/New()
- ..()
- events = new
- icon_state += "-unmanned"
- add_radio()
- //add_cabin() //No cabin for non-airtights
-
- spark_system.set_up(2, 0, src)
- spark_system.attach(src)
- add_cell()
- add_iterators()
- removeVerb(/obj/mecha/verb/disconnect_from_port)
- removeVerb(/atom/movable/verb/pull)
- log_message("[src.name]'s functions initialised. Work protocols active - Entering IDLE mode.")
- loc.Entered(src)
- return
-
-
-//################ Helpers ###########################################################
-
-
-/obj/vehicle/proc/removeVerb(verb_path)
- verbs -= verb_path
-
-/obj/vehicle/proc/addVerb(verb_path)
- verbs += verb_path
-
-/*/obj/vehicle/proc/add_airtank() //In airtight.dm -Agouri
- internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src)
- return internal_tank*/
-
-/obj/vehicle/proc/add_cell(var/obj/item/weapon/cell/C=null)
- if(C)
- C.forceMove(src)
- cell = C
- return
- cell = new(src)
- cell.charge = 15000
- cell.maxcharge = 15000
-
-/*/obj/vehicle/proc/add_cabin() //In airtight.dm -Agouri
- cabin_air = new
- cabin_air.temperature = T20C
- cabin_air.volume = 200
- cabin_air.oxygen = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
- cabin_air.nitrogen = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
- return cabin_air*/
-
-/obj/vehicle/proc/add_radio()
- radio = new(src)
- radio.name = "[src] radio"
- radio.icon = icon
- radio.icon_state = icon_state
- radio.subspace_transmission = 1
-
-/obj/vehicle/proc/add_iterators()
- pr_inertial_movement = new /datum/global_iterator/vehicle_intertial_movement(null,0)
- //pr_internal_damage = new /datum/global_iterator/vehicle_internal_damage(list(src),0)
- //pr_int_temp_processor = new /datum/global_iterator/vehicle_preserve_temp(list(src)) //In airtight.dm's add_airtight_iterators -Agouri
- //pr_give_air = new /datum/global_iterator/vehicle_tank_give_air(list(src) //Same here -Agouri
-
-/obj/vehicle/proc/check_for_support()
- if(locate(/obj/structure/grille, orange(1, src)) || locate(/obj/structure/lattice, orange(1, src)) || locate(/turf/simulated, orange(1, src)) || locate(/turf/unsimulated, orange(1, src)))
- return 1
- else
- return 0
-
-//################ Logs and messages ############################################
-
-
-/obj/vehicle/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
-
-
-
-//################ Global Iterator Datums ######################################
-
-
-/datum/global_iterator/vehicle_intertial_movement //inertial movement in space
- delay = 7
-
- process(var/obj/vehicle/V as obj, direction)
- if(direction)
- if(!step(V, direction)||V.check_for_support())
- src.stop()
- else
- src.stop()
- return
-
-
-/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
- del(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)
- return
-
-
-*/
-
-
-
-
-
-/////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////
-
-
-
-
-/*/turf/DblClick()
- if(istype(usr, /mob/living/silicon/ai))
- return move_camera_by_click()
- if(usr.stat || usr.restrained() || usr.lying)
- return ..()
-
- if(usr.hand && istype(usr.l_hand, /obj/item/weapon/flamethrower))
- var/turflist = getline(usr,src)
- var/obj/item/weapon/flamethrower/F = usr.l_hand
- F.flame_turf(turflist)
- else if(!usr.hand && istype(usr.r_hand, /obj/item/weapon/flamethrower))
- var/turflist = getline(usr,src)
- var/obj/item/weapon/flamethrower/F = usr.r_hand
- F.flame_turf(turflist)
-
- return ..()
-
-/turf/New()
- ..()
- for(var/atom/movable/AM as mob|obj in src)
- spawn( 0 )
- src.Entered(AM)
- return
- return
-
-/turf/ex_act(severity)
- return 0
-
-
-/turf/bullet_act(var/obj/item/projectile/Proj)
- if(istype(Proj ,/obj/item/projectile/beam/pulse))
- src.ex_act(2)
- ..()
- return 0
-
-/turf/bullet_act(var/obj/item/projectile/Proj)
- if(istype(Proj ,/obj/item/projectile/bullet/gyro))
- explosion(src, -1, 0, 2)
- ..()
- return 0
-
-/turf/Enter(atom/movable/mover as mob|obj, atom/forget as mob|obj|turf|area)
- if (!mover || !isturf(mover.loc))
- return 1
-
-
- //First, check objects to block exit that are not on the border
- for(var/obj/obstacle in mover.loc)
- if((obstacle.flags & ~ON_BORDER) && (mover != obstacle) && (forget != obstacle))
- if(!obstacle.CheckExit(mover, src))
- mover.Bump(obstacle, 1)
- return 0
-
- //Now, check objects to block exit that are on the border
- for(var/obj/border_obstacle in mover.loc)
- if((border_obstacle.flags & ON_BORDER) && (mover != border_obstacle) && (forget != border_obstacle))
- if(!border_obstacle.CheckExit(mover, src))
- mover.Bump(border_obstacle, 1)
- return 0
-
- //Next, check objects to block entry that are on the border
- for(var/obj/border_obstacle in src)
- if(border_obstacle.flags & ON_BORDER)
- if(!border_obstacle.CanPass(mover, mover.loc, 1, 0) && (forget != border_obstacle))
- mover.Bump(border_obstacle, 1)
- return 0
-
- //Then, check the turf itself
- if (!src.CanPass(mover, src))
- mover.Bump(src, 1)
- return 0
-
- //Finally, check objects/mobs to block entry that are not on the border
- for(var/atom/movable/obstacle in src)
- if(obstacle.flags & ~ON_BORDER)
- if(!obstacle.CanPass(mover, mover.loc, 1, 0) && (forget != obstacle))
- mover.Bump(obstacle, 1)
- return 0
- return 1 //Nothing found to block so return success!
-
-
-/turf/Entered(atom/movable/M as mob|obj)
- var/loopsanity = 100
- if(ismob(M))
- if(!M:lastarea)
- M:lastarea = get_area(M.loc)
- if(M:lastarea.has_gravity == 0)
- inertial_drift(M)
-
- /*
- if(M.flags & NOGRAV)
- inertial_drift(M)
- */
-
-
-
- else if(!istype(src, /turf/space))
- M:inertia_dir = 0
- ..()
- var/objects = 0
- for(var/atom/A as mob|obj|turf|area in src)
- if(objects > loopsanity) break
- objects++
- spawn( 0 )
- if ((A && M))
- A.HasEntered(M, 1)
- return
- objects = 0
- for(var/atom/A as mob|obj|turf|area in range(1))
- if(objects > loopsanity) break
- objects++
- spawn( 0 )
- if ((A && M))
- A.HasProximity(M, 1)
- return
- return
-
-/turf/proc/inertial_drift(atom/movable/A as mob|obj)
- if(!(A.last_move)) return
- if((istype(A, /mob/) && src.x > 2 && src.x < (world.maxx - 1) && src.y > 2 && src.y < (world.maxy-1)))
- var/mob/M = A
- if(M.Process_Spacemove(1))
- M.inertia_dir = 0
- return
- spawn(5)
- if((M && !(M.anchored) && (M.loc == src)))
- if(M.inertia_dir)
- step(M, M.inertia_dir)
- return
- M.inertia_dir = M.last_move
- step(M, M.inertia_dir)
- return
-
-/turf/proc/levelupdate()
- for(var/obj/O in src)
- if(O.level == 1)
- O.hide(src.intact)
-
-// override for space turfs, since they should never hide anything
-/turf/space/levelupdate()
- for(var/obj/O in src)
- if(O.level == 1)
- O.hide(0)
-
-// Removes all signs of lattice on the pos of the turf -Donkieyo
-/turf/proc/RemoveLattice()
- var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
- if(L)
- del L
-
-/turf/proc/ReplaceWithFloor(explode=0)
- var/prior_icon = icon_old
- var/old_dir = dir
-
- var/turf/simulated/floor/W = new /turf/simulated/floor( locate(src.x, src.y, src.z) )
-
- W.RemoveLattice()
- W.dir = old_dir
- if(prior_icon) W.icon_state = prior_icon
- else W.icon_state = "floor"
-
- if (!explode)
- W.opacity = 1
- W.sd_SetOpacity(0)
- //This is probably gonna make lighting go a bit wonky in bombed areas, but sd_SetOpacity was the primary reason bombs have been so laggy. --NEO
- W.levelupdate()
- return W
-
-/turf/proc/ReplaceWithPlating()
- var/prior_icon = icon_old
- var/old_dir = dir
-
- var/turf/simulated/floor/plating/W = new /turf/simulated/floor/plating( locate(src.x, src.y, src.z) )
-
- W.RemoveLattice()
- W.dir = old_dir
- if(prior_icon) W.icon_state = prior_icon
- else W.icon_state = "plating"
- W.opacity = 1
- W.sd_SetOpacity(0)
- W.levelupdate()
- return W
-
-/turf/proc/ReplaceWithEngineFloor()
- var/old_dir = dir
-
- var/turf/simulated/floor/engine/E = new /turf/simulated/floor/engine( locate(src.x, src.y, src.z) )
-
- E.dir = old_dir
- E.icon_state = "engine"
-
-/turf/simulated/Entered(atom/A, atom/OL)
- if (istype(A,/mob/living/carbon))
- var/mob/living/carbon/M = A
- if(M.lying) return
- if(istype(M, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = M
- if(istype(H.shoes, /obj/item/clothing/shoes/clown_shoes))
- if(H.m_intent == "run")
- if(H.footstep >= 2)
- H.footstep = 0
- else
- H.footstep++
- if(H.footstep == 0)
- playsound(src, "clownstep", 50, 1) // this will get annoying very fast.
- else
- playsound(src, "clownstep", 20, 1)
-
- switch (src.wet)
- if(1)
- if(istype(M, /mob/living/carbon/human)) // Added check since monkeys don't have shoes
- if ((M.m_intent == "run") && !(istype(M:shoes, /obj/item/clothing/shoes) && M:shoes.flags&NOSLIP))
- M.stop_pulling()
- step(M, M.dir)
- M << "\blue You slipped on the wet floor!"
- playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3)
- M.Stun(8)
- M.Weaken(5)
- else
- M.inertia_dir = 0
- return
- else if(!istype(M, /mob/living/carbon/slime))
- if (M.m_intent == "run")
- M.stop_pulling()
- step(M, M.dir)
- M << "\blue You slipped on the wet floor!"
- playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3)
- M.Stun(8)
- M.Weaken(5)
- else
- M.inertia_dir = 0
- return
-
- if(2) //lube
- if(!istype(M, /mob/living/carbon/slime))
- M.stop_pulling()
- step(M, M.dir)
- spawn(1) step(M, M.dir)
- spawn(2) step(M, M.dir)
- spawn(3) step(M, M.dir)
- spawn(4) step(M, M.dir)
- M.take_organ_damage(2) // Was 5 -- TLE
- M << "\blue You slipped on the floor!"
- playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3)
- M.Weaken(10)
-
- ..()
-
-/turf/proc/ReplaceWithSpace()
- var/old_dir = dir
- var/turf/space/S = new /turf/space( locate(src.x, src.y, src.z) )
- S.dir = old_dir
- return S
-
-/turf/proc/ReplaceWithLattice()
- var/old_dir = dir
- var/turf/space/S = new /turf/space( locate(src.x, src.y, src.z) )
- S.dir = old_dir
- new /obj/structure/lattice( locate(src.x, src.y, src.z) )
- return S
-
-/turf/proc/ReplaceWithWall()
- var/old_icon = icon_state
- var/turf/simulated/wall/S = new /turf/simulated/wall( locate(src.x, src.y, src.z) )
- S.icon_old = old_icon
- S.opacity = 0
- S.sd_NewOpacity(1)
- return S
-
-/turf/proc/ReplaceWithRWall()
- var/old_icon = icon_state
- var/turf/simulated/wall/r_wall/S = new /turf/simulated/wall/r_wall( locate(src.x, src.y, src.z) )
- S.icon_old = old_icon
- S.opacity = 0
- S.sd_NewOpacity(1)
- return S
-
-/turf/simulated/wall/New()
- ..()
-
-/turf/simulated/wall/proc/dismantle_wall(devastated=0, explode=0)
- if(istype(src,/turf/simulated/wall/r_wall))
- if(!devastated)
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
- new /obj/structure/girder/reinforced(src)
- new /obj/item/stack/sheet/plasteel( src )
- else
- new /obj/item/stack/sheet/metal( src )
- new /obj/item/stack/sheet/metal( src )
- new /obj/item/stack/sheet/plasteel( src )
- else if(istype(src,/turf/simulated/wall/cult))
- if(!devastated)
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
- new /obj/effect/decal/remains/human(src)
- else
- new /obj/effect/decal/remains/human(src)
-
- else
- if(!devastated)
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
- new /obj/structure/girder(src)
- new /obj/item/stack/sheet/metal( src )
- new /obj/item/stack/sheet/metal( src )
- else
- new /obj/item/stack/sheet/metal( src )
- new /obj/item/stack/sheet/metal( src )
- new /obj/item/stack/sheet/metal( src )
-
- ReplaceWithPlating(explode)
-
-/turf/simulated/wall/examine()
- set src in oview(1)
-
- usr << "It looks like a regular wall."
- return
-
-/turf/simulated/wall/ex_act(severity)
- switch(severity)
- if(1.0)
- //SN src = null
- src.ReplaceWithSpace()
- del(src)
- return
- if(2.0)
- if (prob(50))
- dismantle_wall(0,1)
- else
- dismantle_wall(1,1)
- if(3.0)
- var/proba
- if (istype(src, /turf/simulated/wall/r_wall))
- proba = 15
- else
- proba = 40
- if (prob(proba))
- dismantle_wall(0,1)
- else
- return
-
-/turf/simulated/wall/blob_act()
- if(prob(50))
- dismantle_wall()
-
-/turf/simulated/wall/attack_paw(mob/user as mob)
- if ((user.mutations & HULK))
- if (prob(40))
- usr << text("\blue You smash through the wall.")
- dismantle_wall(1)
- return
- else
- usr << text("\blue You punch the wall.")
- return
-
- return src.attack_hand(user)
-
-
-/turf/simulated/wall/attack_animal(mob/living/simple_animal/M as mob)
- if(M.wall_smash)
- if (istype(src, /turf/simulated/wall/r_wall))
- M << text("\blue This wall is far too strong for you to destroy.")
- return
- else
- if (prob(40))
- M << text("\blue You smash through the wall.")
- dismantle_wall(1)
- return
- else
- M << text("\blue You smash against the wall.")
- return
-
- M << "\blue You push the wall but nothing happens!"
- return
-
-/turf/simulated/wall/attack_hand(mob/user as mob)
- if ((user.mutations & HULK))
- if (prob(40))
- usr << text("\blue You smash through the wall.")
- dismantle_wall(1)
- return
- else
- usr << text("\blue You punch the wall.")
- return
-
- user << "\blue You push the wall but nothing happens!"
- playsound(src.loc, 'sound/weapons/Genhit.ogg', 25, 1)
- src.add_fingerprint(user)
- return
-
-/turf/simulated/wall/attackby(obj/item/weapon/W as obj, mob/user as mob)
-
- if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
- usr << "\red You don't have the dexterity to do this!"
- return
-
- if (istype(W, /obj/item/weapon/weldingtool) && W:welding)
- var/turf/T = get_turf(user)
- if (!( istype(T, /turf) ))
- return
-
- if (thermite)
- var/obj/effect/overlay/O = new/obj/effect/overlay( src )
- O.name = "Thermite"
- O.desc = "Looks hot."
- O.icon = 'icons/effects/fire.dmi'
- O.icon_state = "2"
- O.anchored = 1
- O.density = 1
- O.layer = 5
- var/turf/simulated/floor/F = ReplaceWithPlating()
- F.burn_tile()
- F.icon_state = "wall_thermite"
- user << "\red The thermite melts the wall."
- spawn(100) del(O)
- F.sd_LumReset()
- return
-
- if (W:remove_fuel(0,user))
- W:welding = 2
- user << "\blue Now disassembling the outer wall plating."
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
- sleep(100)
- if (W && istype(src, /turf/simulated/wall))
- if ((get_turf(user) == T && user.equipped() == W))
- user << "\blue You disassembled the outer wall plating."
- dismantle_wall()
- W:welding = 1
- else
- user << "\blue You need more welding fuel to complete this task."
- return
-
- else if (istype(W, /obj/item/weapon/pickaxe/plasmacutter))
- var/turf/T = user.loc
- if (!( istype(T, /turf) ))
- return
-
- if (thermite)
- var/obj/effect/overlay/O = new/obj/effect/overlay( src )
- O.name = "Thermite"
- O.desc = "Looks hot."
- O.icon = 'icons/effects/fire.dmi'
- O.icon_state = "2"
- O.anchored = 1
- O.density = 1
- O.layer = 5
- var/turf/simulated/floor/F = ReplaceWithPlating()
- F.burn_tile()
- F.icon_state = "wall_thermite"
- user << "\red The thermite melts the wall."
- spawn(100) del(O)
- F.sd_LumReset()
- return
-
- else
- user << "\blue Now disassembling the outer wall plating."
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
- sleep(60)
- if (W && istype(src, /turf/simulated/wall))
- if ((get_turf(user) == T && user.equipped() == W))
- user << "\blue You disassembled the outer wall plating."
- dismantle_wall()
- for(var/mob/O in viewers(user, 5))
- O.show_message(text("\blue The wall was sliced apart by []!", user), 1, text("\red You hear metal being sliced apart."), 2)
- return
-
- else if(istype(W, /obj/item/weapon/pickaxe/diamonddrill))
- var/turf/T = user.loc
- user << "\blue Now drilling through wall."
- sleep(60)
- if (W && istype(src, /turf/simulated/wall))
- if ((user.loc == T && user.equipped() == W))
- dismantle_wall(1)
- for(var/mob/O in viewers(user, 5))
- O.show_message(text("\blue The wall was drilled apart by []!", user), 1, text("\red You hear metal being drilled appart."), 2)
- return
-
- else if(istype(W, /obj/item/weapon/melee/energy/blade))
- var/turf/T = user.loc
- user << "\blue Now slicing through wall."
- W:spark_system.start()
- playsound(src.loc, "sparks", 50, 1)
- sleep(70)
- if (W && istype(src, /turf/simulated/wall))
- if ((user.loc == T && user.equipped() == W))
- W:spark_system.start()
- playsound(src.loc, "sparks", 50, 1)
- playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1)
- dismantle_wall(1)
- for(var/mob/O in viewers(user, 5))
- O.show_message(text("\blue The wall was sliced apart by []!", user), 1, text("\red You hear metal being sliced and sparks flying."), 2)
- return
-
- else if(istype(W,/obj/item/apc_frame))
- var/obj/item/apc_frame/AH = W
- AH.try_build(src)
- else if(istype(W,/obj/item/weapon/contraband/poster))
- var/obj/item/weapon/contraband/poster/P = W
- if(P.resulting_poster)
- var/check = 0
- var/stuff_on_wall = 0
- for( var/obj/O in src.contents) //Let's see if it already has a poster on it or too much stuff
- if(istype(O,/obj/effect/decal/poster))
- check = 1
- break
- stuff_on_wall++
- if(stuff_on_wall==3)
- check = 1
- break
-
- if(check)
- user << "The wall is far too cluttered to place a poster!"
- return
-
- user << "You start placing the poster on the wall..." //Looks like it's uncluttered enough. Place the poster.
-
- P.resulting_poster.loc = src
- var/temp = P.resulting_poster.icon_state
- var/temp_loc = user.loc
- P.resulting_poster.icon_state = "poster_being_set"
- playsound(P.resulting_poster.loc, 'sound/items/poster_being_created.ogg', 100, 1)
- sleep(24)
-
- if(user.loc == temp_loc)//Let's check if he still is there
- user << "You place the poster!"
- P.resulting_poster.icon_state = temp
- src.contents += P.resulting_poster
- del(P)
- else
- user << "You stop placing the poster."
- P.resulting_poster.loc = P
- P.resulting_poster.icon_state = temp
- else
- return attack_hand(user)
- return
-
-
-/turf/simulated/wall/r_wall/attackby(obj/item/W as obj, mob/user as mob)
-
- if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
- usr << "\red You don't have the dexterity to do this!"
- return
-
- if(!istype(src, /turf/simulated/wall/r_wall))
- return // this may seem stupid and redundant but apparently floors can call this attackby() proc, it was spamming shit up. -- Doohl
-
-
- if (istype(W, /obj/item/weapon/weldingtool) && W:welding)
- W:eyecheck(user)
- var/turf/T = user.loc
- if (!( istype(T, /turf) ))
- return
-
- if (thermite)
- var/obj/effect/overlay/O = new/obj/effect/overlay( src )
- O.name = "Thermite"
- O.desc = "Looks hot."
- O.icon = 'icons/effects/fire.dmi'
- O.icon_state = "2"
- O.anchored = 1
- O.density = 1
- O.layer = 5
- var/turf/simulated/floor/F = ReplaceWithPlating()
- F.burn_tile()
- F.icon_state = "wall_thermite"
- user << "\red The thermite melts the wall."
- spawn(100) del(O)
- F.sd_LumReset()
- return
-
- if (src.d_state == 2)
- W:welding = 2
- user << "\blue Slicing metal cover."
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
- sleep(60)
- if ((user.loc == T && user.equipped() == W))
- src.d_state = 3
- user << "\blue You removed the metal cover."
- W:welding = 1
-
- else if (src.d_state == 5)
- W:welding = 2
- user << "\blue Removing support rods."
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
- sleep(100)
- if ((user.loc == T && user.equipped() == W))
- src.d_state = 6
- new /obj/item/stack/rods( src )
- user << "\blue You removed the support rods."
- W:welding = 1
-
- else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter))
- var/turf/T = user.loc
- if (!( istype(T, /turf) ))
- return
-
- if (thermite)
- var/obj/effect/overlay/O = new/obj/effect/overlay( src )
- O.name = "Thermite"
- O.desc = "Looks hot."
- O.icon = 'icons/effects/fire.dmi'
- O.icon_state = "2"
- O.anchored = 1
- O.density = 1
- O.layer = 5
- var/turf/simulated/floor/F = ReplaceWithPlating()
- F.burn_tile()
- F.icon_state = "wall_thermite"
- user << "\red The thermite melts the wall."
- spawn(100) del(O)
- F.sd_LumReset()
- return
-
- if (src.d_state == 2)
- user << "\blue Slicing metal cover."
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
- sleep(40)
- if ((user.loc == T && user.equipped() == W))
- src.d_state = 3
- user << "\blue You removed the metal cover."
-
- else if (src.d_state == 5)
- user << "\blue Removing support rods."
- playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
- sleep(70)
- if ((user.loc == T && user.equipped() == W))
- src.d_state = 6
- new /obj/item/stack/rods( src )
- user << "\blue You removed the support rods."
-
- else if(istype(W, /obj/item/weapon/melee/energy/blade))
- user << "\blue This wall is too thick to slice through. You will need to find a different path."
- return
-
- else if (istype(W, /obj/item/weapon/wrench))
- if (src.d_state == 4)
- var/turf/T = user.loc
- user << "\blue Detaching support rods."
- playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
- sleep(40)
- if ((user.loc == T && user.equipped() == W))
- src.d_state = 5
- user << "\blue You detach the support rods."
-
- else if (istype(W, /obj/item/weapon/wirecutters))
- if (src.d_state == 0)
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
- src.d_state = 1
- new /obj/item/stack/rods( src )
-
- else if (istype(W, /obj/item/weapon/screwdriver))
- if (src.d_state == 1)
- var/turf/T = user.loc
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1)
- user << "\blue Removing support lines."
- sleep(40)
- if ((user.loc == T && user.equipped() == W))
- src.d_state = 2
- user << "\blue You removed the support lines."
-
- else if (istype(W, /obj/item/weapon/crowbar))
-
- if (src.d_state == 3)
- var/turf/T = user.loc
- user << "\blue Prying cover off."
- playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
- sleep(100)
- if ((user.loc == T && user.equipped() == W))
- src.d_state = 4
- user << "\blue You removed the cover."
-
- else if (src.d_state == 6)
- var/turf/T = user.loc
- user << "\blue Prying outer sheath off."
- playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
- sleep(100)
- if(src)
- if ((user.loc == T && user.equipped() == W))
- user << "\blue You removed the outer sheath."
- dismantle_wall()
- return
-
- else if (istype(W, /obj/item/weapon/pickaxe/diamonddrill))
- var/turf/T = user.loc
- user << "\blue You begin to drill though, this will take some time."
- sleep(200)
- if(src)
- if ((user.loc == T && user.equipped() == W))
- user << "\blue Your drill tears though the reinforced plating."
- dismantle_wall()
- return
-
- else if ((istype(W, /obj/item/stack/sheet/metal)) && (src.d_state))
- var/turf/T = user.loc
- user << "\blue Repairing wall."
- sleep(100)
- if ((user.loc == T && user.equipped() == W))
- src.d_state = 0
- src.icon_state = initial(src.icon_state)
- user << "\blue You repaired the wall."
- if (W:amount > 1)
- W:amount--
- else
- del(W)
-
- else if(istype(W,/obj/item/weapon/contraband/poster))
- var/obj/item/weapon/contraband/poster/P = W
- if(P.resulting_poster)
- var/check = 0
- var/stuff_on_wall = 0
- for( var/obj/O in src.contents) //Let's see if it already has a poster on it or too much stuff
- if(istype(O,/obj/effect/decal/poster))
- check = 1
- break
- stuff_on_wall++
- if(stuff_on_wall==3)
- check = 1
- break
-
- if(check)
- user << "The wall is far too cluttered to place a poster!"
- return
-
- user << "You start placing the poster on the wall..." //Looks like it's uncluttered enough. Place the poster.
-
- P.resulting_poster.loc = src
- var/temp = P.resulting_poster.icon_state
- var/temp_loc = user.loc
- P.resulting_poster.icon_state = "poster_being_set"
- playsound(P.resulting_poster.loc, 'sound/items/poster_being_created.ogg', 100, 1)
- sleep(24)
-
- if(user.loc == temp_loc)//Let's check if he still is there
- user << "You place the poster!"
- P.resulting_poster.icon_state = temp
- src.contents += P.resulting_poster
- del(P)
- else
- user << "You stop placing the poster."
- P.resulting_poster.loc = P
- P.resulting_poster.icon_state = temp
- return
-
- if(istype(W,/obj/item/apc_frame))
- var/obj/item/apc_frame/AH = W
- AH.try_build(src)
- return
-
- if(src.d_state > 0)
- src.icon_state = "r_wall-[d_state]"
-
- else
- return attack_hand(user)
- return
-
-/turf/simulated/wall/meteorhit(obj/M as obj)
- if (prob(15))
- dismantle_wall()
- else if(prob(70))
- ReplaceWithPlating()
- else
- ReplaceWithLattice()
- return 0
-
-
-//This is so damaged or burnt tiles or platings don't get remembered as the default tile
-var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","damaged4",
- "damaged5","panelscorched","floorscorched1","floorscorched2","platingdmg1","platingdmg2",
- "platingdmg3","plating","light_on","light_on_flicker1","light_on_flicker2",
- "light_on_clicker3","light_on_clicker4","light_on_clicker5","light_broken",
- "light_on_broken","light_off","wall_thermite","grass1","grass2","grass3","grass4",
- "asteroid","asteroid_dug",
- "asteroid0","asteroid1","asteroid2","asteroid3","asteroid4",
- "asteroid5","asteroid6","asteroid7","asteroid8",
- "burning","oldburning","light-on-r","light-on-y","light-on-g","light-on-b")
-
-var/list/plating_icons = list("plating","platingdmg1","platingdmg2","platingdmg3","asteroid","asteroid_dug")
-
-/turf/simulated/floor
-
- //Note to coders, the 'intact' var can no longer be used to determine if the floor is a plating or not.
- //Use the is_plating(), is_plasteel_floor() and is_light_floor() procs instead. --Errorage
- name = "floor"
- icon = 'icons/turf/floors.dmi'
- icon_state = "floor"
- var/icon_regular_floor = "floor" //used to remember what icon the tile should have by default
- var/icon_plating = "plating"
- thermal_conductivity = 0.040
- heat_capacity = 10000
- var/broken = 0
- var/burnt = 0
- var/obj/item/stack/tile/floor_tile = new/obj/item/stack/tile/plasteel
-
- airless
- icon_state = "floor"
- name = "airless floor"
- oxygen = 0.01
- nitrogen = 0.01
- temperature = TCMB
-
- New()
- ..()
- name = "floor"
-
- light
- name = "Light floor"
- luminosity = 5
- icon_state = "light_on"
- floor_tile = new/obj/item/stack/tile/light
-
- New()
- floor_tile.New() //I guess New() isn't run on objects spawned without the definition of a turf to house them, ah well.
- var/n = name //just in case commands rename it in the ..() call
- ..()
- spawn(4)
- update_icon()
- name = n
-
- grass
- name = "Grass patch"
- icon_state = "grass1"
- floor_tile = new/obj/item/stack/tile/grass
-
- New()
- floor_tile.New() //I guess New() isn't run on objects spawned without the definition of a turf to house them, ah well.
- icon_state = "grass[pick("1","2","3","4")]"
- ..()
- spawn(4)
- update_icon()
- for(var/direction in cardinal)
- if(istype(get_step(src,direction),/turf/simulated/floor))
- var/turf/simulated/floor/FF = get_step(src,direction)
- FF.update_icon() //so siding get updated properly
-
-/turf/simulated/floor/vault
- icon_state = "rockvault"
-
- New(location,type)
- ..()
- icon_state = "[type]vault"
-
-/turf/simulated/wall/vault
- icon_state = "rockvault"
-
- New(location,type)
- ..()
- icon_state = "[type]vault"
-
-/turf/simulated/floor/engine
- name = "reinforced floor"
- icon_state = "engine"
- thermal_conductivity = 0.025
- heat_capacity = 325000
-
-/turf/simulated/floor/engine/cult
- name = "engraved floor"
- icon_state = "cult"
-
-
-/turf/simulated/floor/engine/n20
- New()
- ..()
- var/datum/gas_mixture/adding = new
- var/datum/gas/sleeping_agent/trace_gas = new
-
- trace_gas.moles = 2000
- adding.trace_gases += trace_gas
- adding.temperature = T20C
-
- assume_air(adding)
-
-/turf/simulated/floor/engine/vacuum
- name = "vacuum floor"
- icon_state = "engine"
- oxygen = 0
- nitrogen = 0.001
- temperature = TCMB
-
-/turf/simulated/floor/plating
- name = "plating"
- icon_state = "plating"
- floor_tile = null
- intact = 0
-
-/turf/simulated/floor/plating/airless
- icon_state = "plating"
- name = "airless plating"
- oxygen = 0.01
- nitrogen = 0.01
- temperature = TCMB
-
- New()
- ..()
- name = "plating"
-
-/turf/simulated/floor/grid
- icon = 'icons/turf/floors.dmi'
- icon_state = "circuit"
-
-/turf/simulated/floor/New()
- ..()
- if(icon_state in icons_to_ignore_at_floor_init) //so damaged/burned tiles or plating icons aren't saved as the default
- icon_regular_floor = "floor"
- else
- icon_regular_floor = icon_state
-
-//turf/simulated/floor/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
-// if ((istype(mover, /obj/machinery/vehicle) && !(src.burnt)))
-// if (!( locate(/obj/machinery/mass_driver, src) ))
-// return 0
-// return ..()
-
-/turf/simulated/floor/ex_act(severity)
- //set src in oview(1)
- switch(severity)
- if(1.0)
- src.ReplaceWithSpace()
- if(2.0)
- switch(pick(1,2;75,3))
- if (1)
- src.ReplaceWithLattice()
- if(prob(33)) new /obj/item/stack/sheet/metal(src)
- if(2)
- src.ReplaceWithSpace()
- if(3)
- if(prob(80))
- src.break_tile_to_plating()
- else
- src.break_tile()
- src.hotspot_expose(1000,CELL_VOLUME)
- if(prob(33)) new /obj/item/stack/sheet/metal(src)
- if(3.0)
- if (prob(50))
- src.break_tile()
- src.hotspot_expose(1000,CELL_VOLUME)
- return
-
-/turf/simulated/floor/blob_act()
- return
-
-turf/simulated/floor/proc/update_icon()
- if(is_plasteel_floor())
- if(!broken && !burnt)
- icon_state = icon_regular_floor
- if(is_plating())
- if(!broken && !burnt)
- icon_state = icon_plating //Because asteroids are 'platings' too.
- if(is_light_floor())
- var/obj/item/stack/tile/light/T = floor_tile
- if(T.on)
- switch(T.state)
- if(0)
- icon_state = "light_on"
- sd_SetLuminosity(5)
- if(1)
- var/num = pick("1","2","3","4")
- icon_state = "light_on_flicker[num]"
- sd_SetLuminosity(5)
- if(2)
- icon_state = "light_on_broken"
- sd_SetLuminosity(5)
- if(3)
- icon_state = "light_off"
- sd_SetLuminosity(0)
- else
- sd_SetLuminosity(0)
- icon_state = "light_off"
- if(is_grass_floor())
- if(!broken && !burnt)
- if(!(icon_state in list("grass1","grass2","grass3","grass4")))
- icon_state = "grass[pick("1","2","3","4")]"
- spawn(1)
- if(istype(src,/turf/simulated/floor)) //Was throwing runtime errors due to a chance of it changing to space halfway through.
- if(air)
- update_visuals(air)
-
-turf/simulated/floor/return_siding_icon_state()
- ..()
- if(is_grass_floor())
- var/dir_sum = 0
- for(var/direction in cardinal)
- var/turf/T = get_step(src,direction)
- if(!(T.is_grass_floor()))
- dir_sum += direction
- if(dir_sum)
- return "wood_siding[dir_sum]"
- else
- return 0
-
-
-/turf/simulated/floor/attack_paw(mob/user as mob)
- return src.attack_hand(user)
-
-/turf/simulated/floor/attack_hand(mob/user as mob)
- if (is_light_floor())
- var/obj/item/stack/tile/light/T = floor_tile
- T.on = !T.on
- update_icon()
- if ((!( user.canmove ) || user.restrained() || !( user.pulling )))
- return
- if (user.pulling.anchored)
- return
- if ((user.pulling.loc != user.loc && get_dist(user, user.pulling) > 1))
- return
- if (ismob(user.pulling))
- var/mob/M = user.pulling
- var/mob/t = M.pulling
- M.stop_pulling()
- step(user.pulling, get_dir(user.pulling.loc, src))
- M.start_pulling(t)
- else
- step(user.pulling, get_dir(user.pulling.loc, src))
- return
-
-/turf/simulated/floor/engine/attackby(obj/item/weapon/C as obj, mob/user as mob)
- if(!C)
- return
- if(!user)
- return
- if(istype(C, /obj/item/weapon/wrench))
- user << "\blue Removing rods..."
- playsound(src.loc, 'sound/items/Ratchet.ogg', 80, 1)
- if(do_after(user, 30))
- new /obj/item/stack/rods(src, 2)
- ReplaceWithFloor()
- var/turf/simulated/floor/F = src
- F.make_plating()
- return
-
-/turf/simulated/floor/proc/gets_drilled()
- return
-
-/turf/simulated/floor/proc/break_tile_to_plating()
- if(!is_plating())
- make_plating()
- break_tile()
-
-/turf/simulated/floor/is_plasteel_floor()
- if(istype(floor_tile,/obj/item/stack/tile/plasteel))
- return 1
- else
- return 0
-
-/turf/simulated/floor/is_light_floor()
- if(istype(floor_tile,/obj/item/stack/tile/light))
- return 1
- else
- return 0
-
-/turf/simulated/floor/is_grass_floor()
- if(istype(floor_tile,/obj/item/stack/tile/grass))
- return 1
- else
- return 0
-
-/turf/simulated/floor/is_plating()
- if(!floor_tile)
- return 1
- return 0
-
-/turf/simulated/floor/proc/break_tile()
- if(istype(src,/turf/simulated/floor/engine)) return
- if(istype(src,/turf/simulated/floor/mech_bay_recharge_floor))
- src.ReplaceWithPlating()
- if(broken) return
- if(is_plasteel_floor())
- src.icon_state = "damaged[pick(1,2,3,4,5)]"
- broken = 1
- else if(is_plasteel_floor())
- src.icon_state = "light_broken"
- broken = 1
- else if(is_plating())
- src.icon_state = "platingdmg[pick(1,2,3)]"
- broken = 1
- else if(is_grass_floor())
- src.icon_state = "sand[pick("1","2","3")]"
- broken = 1
-
-/turf/simulated/floor/proc/burn_tile()
- if(istype(src,/turf/simulated/floor/engine)) return
- if(broken || burnt) return
- if(is_plasteel_floor())
- src.icon_state = "damaged[pick(1,2,3,4,5)]"
- burnt = 1
- else if(is_plasteel_floor())
- src.icon_state = "floorscorched[pick(1,2)]"
- burnt = 1
- else if(is_plating())
- src.icon_state = "panelscorched"
- burnt = 1
- else if(is_grass_floor())
- src.icon_state = "sand[pick("1","2","3")]"
- burnt = 1
-
-//This proc will delete the floor_tile and the update_iocn() proc will then change the icon_state of the turf
-//This proc auto corrects the grass tiles' siding.
-/turf/simulated/floor/proc/make_plating()
- if(istype(src,/turf/simulated/floor/engine)) return
-
- if(is_grass_floor())
- for(var/direction in cardinal)
- if(istype(get_step(src,direction),/turf/simulated/floor))
- var/turf/simulated/floor/FF = get_step(src,direction)
- FF.update_icon() //so siding get updated properly
-
- if(!floor_tile) return
- del(floor_tile)
- icon_plating = "plating"
- sd_SetLuminosity(0)
- floor_tile = null
- intact = 0
- broken = 0
- burnt = 0
-
- update_icon()
- levelupdate()
-
-//This proc will make the turf a plasteel floor tile. The expected argument is the tile to make the turf with
-//If none is given it will make a new object. dropping or unequipping must be handled before or after calling
-//this proc.
-/turf/simulated/floor/proc/make_plasteel_floor(var/obj/item/stack/tile/plasteel/T = null)
- broken = 0
- burnt = 0
- intact = 1
- sd_SetLuminosity(0)
- if(T)
- if(istype(T,/obj/item/stack/tile/plasteel))
- floor_tile = T
- if (icon_regular_floor)
- icon_state = icon_regular_floor
- else
- icon_state = "floor"
- icon_regular_floor = icon_state
- update_icon()
- levelupdate()
- return
- //if you gave a valid parameter, it won't get thisf ar.
- floor_tile = new/obj/item/stack/tile/plasteel
- icon_state = "floor"
- icon_regular_floor = icon_state
-
- update_icon()
- levelupdate()
-
-//This proc will make the turf a light floor tile. The expected argument is the tile to make the turf with
-//If none is given it will make a new object. dropping or unequipping must be handled before or after calling
-//this proc.
-/turf/simulated/floor/proc/make_light_floor(var/obj/item/stack/tile/light/T = null)
- broken = 0
- burnt = 0
- intact = 1
- if(T)
- if(istype(T,/obj/item/stack/tile/light))
- floor_tile = T
- update_icon()
- levelupdate()
- return
- //if you gave a valid parameter, it won't get thisf ar.
- floor_tile = new/obj/item/stack/tile/light
-
- update_icon()
- levelupdate()
-
-//This proc will make a turf into a grass patch. Fun eh? Insert the grass tile to be used as the argument
-//If no argument is given a new one will be made.
-/turf/simulated/floor/proc/make_grass_floor(var/obj/item/stack/tile/grass/T = null)
- broken = 0
- burnt = 0
- intact = 1
- if(T)
- if(istype(T,/obj/item/stack/tile/grass))
- floor_tile = T
- update_icon()
- levelupdate()
- return
- //if you gave a valid parameter, it won't get thisf ar.
- floor_tile = new/obj/item/stack/tile/grass
-
- update_icon()
- levelupdate()
-
-/turf/simulated/floor/attackby(obj/item/C as obj, mob/user as mob)
-
- if(!C || !user)
- return 0
-
- if(istype(C,/obj/item/weapon/light/bulb)) //only for light tiles
- if(is_light_floor())
- var/obj/item/stack/tile/light/T = floor_tile
- if(T.state)
- user.u_equip(C)
- del(C)
- T.state = C //fixing it by bashing it with a light bulb, fun eh?
- update_icon()
- user << "\blue You replace the light bulb."
- else
- user << "\blue The lightbulb seems fine, no need to replace it."
-
- if(istype(C, /obj/item/weapon/crowbar) && (!(is_plating())))
- if(broken || burnt)
- user << "\red You remove the broken plating."
- else
- user << "\red You remove the [floor_tile.name]."
- new floor_tile.type(src)
-
- make_plating()
- playsound(src.loc, 'sound/items/Crowbar.ogg', 80, 1)
-
- return
-
- if(istype(C, /obj/item/stack/rods))
- var/obj/item/stack/rods/R = C
- if (is_plating())
- if (R.amount >= 2)
- user << "\blue Reinforcing the floor..."
- if(do_after(user, 30) && R && R.amount >= 2 && is_plating())
- ReplaceWithEngineFloor()
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 80, 1)
- R.use(2)
- return
- else
- user << "\red You need more rods."
- else
- user << "\red You must remove the plating first."
- return
-
- if(istype(C, /obj/item/stack/tile))
- if(is_plating())
- if(!broken && !burnt)
- var/obj/item/stack/tile/T = C
- floor_tile = new T.type
- intact = 1
- if(istype(T,/obj/item/stack/tile/light))
- var/obj/item/stack/tile/light/L = T
- var/obj/item/stack/tile/light/F = floor_tile
- F.state = L.state
- F.on = L.on
- if(istype(T,/obj/item/stack/tile/grass))
- for(var/direction in cardinal)
- if(istype(get_step(src,direction),/turf/simulated/floor))
- var/turf/simulated/floor/FF = get_step(src,direction)
- FF.update_icon() //so siding gets updated properly
- T.use(1)
- update_icon()
- levelupdate()
- playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1)
- else
- user << "\blue This section is too damaged to support a tile. Use a welder to fix the damage."
-
-
- if(istype(C, /obj/item/stack/cable_coil))
- if(is_plating())
- var/obj/item/stack/cable_coil/coil = C
- coil.turf_place(src, user)
- else
- user << "\red You must remove the plating first."
-
- if(istype(C, /obj/item/weapon/shovel))
- if(is_grass_floor())
- new /obj/item/weapon/ore/glass(src)
- new /obj/item/weapon/ore/glass(src) //Make some sand if you shovel grass
- user << "\blue You shovel the grass."
- make_plating()
- else
- user << "\red You cannot shovel this."
-
- if(istype(C, /obj/item/weapon/weldingtool))
- var/obj/item/weapon/weldingtool/welder = C
- if(welder.welding && (is_plating()))
- if(broken || burnt)
- if(welder.remove_fuel(0,user))
- user << "\red You fix some dents on the broken plating."
- playsound(src.loc, 'sound/items/Welder.ogg', 80, 1)
- icon_state = "plating"
- burnt = 0
- broken = 0
- else
- user << "\blue You need more welding fuel to complete this task."
-
-/turf/unsimulated/floor/attack_paw(user as mob)
- return src.attack_hand(user)
-
-/turf/unsimulated/floor/attack_hand(var/mob/user as mob)
- if ((!( user.canmove ) || user.restrained() || !( user.pulling )))
- return
- if (user.pulling.anchored)
- return
- if ((user.pulling.loc != user.loc && get_dist(user, user.pulling) > 1))
- return
- if (ismob(user.pulling))
- var/mob/M = user.pulling
- var/mob/t = M.pulling
- M.stop_pulling()
- step(user.pulling, get_dir(user.pulling.loc, src))
- M.start_pulling(t)
- else
- step(user.pulling, get_dir(user.pulling.loc, src))
- return
-
-// imported from space.dm
-
-/turf/space/attack_paw(mob/user as mob)
- return src.attack_hand(user)
-
-/turf/space/attack_hand(mob/user as mob)
- if ((user.restrained() || !( user.pulling )))
- return
- if (user.pulling.anchored)
- return
- if ((user.pulling.loc != user.loc && get_dist(user, user.pulling) > 1))
- return
- if (ismob(user.pulling))
- var/mob/M = user.pulling
- var/atom/movable/t = M.pulling
- M.stop_pulling()
- step(user.pulling, get_dir(user.pulling.loc, src))
- M.start_pulling(t)
- else
- step(user.pulling, get_dir(user.pulling.loc, src))
- return
-
-/turf/space/attackby(obj/item/C as obj, mob/user as mob)
-
- if (istype(C, /obj/item/stack/rods))
- var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
- if(L)
- return
- var/obj/item/stack/rods/R = C
- user << "\blue Constructing support lattice ..."
- playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1)
- ReplaceWithLattice()
- R.use(1)
- return
-
- if (istype(C, /obj/item/stack/tile/plasteel))
- var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
- if(L)
- var/obj/item/stack/tile/plasteel/S = C
- del(L)
- playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1)
- S.build(src)
- S.use(1)
- return
- else
- user << "\red The plating is going to need some support."
- return
-
-
-// Ported from unstable r355
-
-/turf/space/Entered(atom/movable/A as mob|obj)
- ..()
- if ((!(A) || src != A.loc || istype(null, /obj/effect/beam))) return
-
- inertial_drift(A)
-
- if(ticker && ticker.mode)
-
- // Okay, so let's make it so that people can travel z levels but not nuke disks!
- // if(ticker.mode.name == "nuclear emergency") return
-
- if(ticker.mode.name == "extended"||ticker.mode.name == "sandbox")
- Sandbox_Spacemove(A)
-
- else
- if (src.x <= 2 || A.x >= (world.maxx - 1) || src.y <= 2 || A.y >= (world.maxy - 1))
- if(istype(A, /obj/effect/meteor)||istype(A, /obj/effect/space_dust))
- del(A)
- return
-
- if(istype(A, /obj/item/weapon/disk/nuclear)) // Don't let nuke disks travel Z levels ... And moving this shit down here so it only fires when they're actually trying to change z-level.
- return
-
- if(!isemptylist(A.search_contents_for(/obj/item/weapon/disk/nuclear)))
- if(istype(A, /mob/living))
- var/mob/living/MM = A
- if(MM.client)
- MM << "\red Something you are carrying is preventing you from leaving. Don't play stupid; you know exactly what it is."
- return
-
-
-
- var/move_to_z_str = pickweight(accessable_z_levels)
-
- var/move_to_z = text2num(move_to_z_str)
-
- if(!move_to_z)
- return
-
-
-
- A.z = move_to_z
-
-
- if(src.x <= 2)
- A.x = world.maxx - 2
-
- else if (A.x >= (world.maxx - 1))
- A.x = 3
-
- else if (src.y <= 2)
- A.y = world.maxy - 2
-
- else if (A.y >= (world.maxy - 1))
- A.y = 3
-
- spawn (0)
- if ((A && A.loc))
- A.loc.Entered(A)
-
-// if(istype(A, /obj/structure/closet/coffin))
-// coffinhandler.Add(A)
-
-/turf/space/proc/Sandbox_Spacemove(atom/movable/A as mob|obj)
- var/cur_x
- var/cur_y
- var/next_x
- var/next_y
- var/target_z
- var/list/y_arr
-
- if(src.x <= 1)
- if(istype(A, /obj/effect/meteor)||istype(A, /obj/effect/space_dust))
- del(A)
- return
-
- var/list/cur_pos = src.get_global_map_pos()
- if(!cur_pos) return
- cur_x = cur_pos["x"]
- cur_y = cur_pos["y"]
- next_x = (--cur_x||global_map.len)
- y_arr = global_map[next_x]
- target_z = y_arr[cur_y]
-/*
- //debug
- world << "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]"
- world << "Target Z = [target_z]"
- world << "Next X = [next_x]"
- //debug
-*/
- if(target_z)
- A.z = target_z
- A.x = world.maxx - 2
- spawn (0)
- if ((A && A.loc))
- A.loc.Entered(A)
- else if (src.x >= world.maxx)
- if(istype(A, /obj/effect/meteor))
- del(A)
- return
-
- var/list/cur_pos = src.get_global_map_pos()
- if(!cur_pos) return
- cur_x = cur_pos["x"]
- cur_y = cur_pos["y"]
- next_x = (++cur_x > global_map.len ? 1 : cur_x)
- y_arr = global_map[next_x]
- target_z = y_arr[cur_y]
-/*
- //debug
- world << "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]"
- world << "Target Z = [target_z]"
- world << "Next X = [next_x]"
- //debug
-*/
- if(target_z)
- A.z = target_z
- A.x = 3
- spawn (0)
- if ((A && A.loc))
- A.loc.Entered(A)
- else if (src.y <= 1)
- if(istype(A, /obj/effect/meteor))
- del(A)
- return
- var/list/cur_pos = src.get_global_map_pos()
- if(!cur_pos) return
- cur_x = cur_pos["x"]
- cur_y = cur_pos["y"]
- y_arr = global_map[cur_x]
- next_y = (--cur_y||y_arr.len)
- target_z = y_arr[next_y]
-/*
- //debug
- world << "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]"
- world << "Next Y = [next_y]"
- world << "Target Z = [target_z]"
- //debug
-*/
- if(target_z)
- A.z = target_z
- A.y = world.maxy - 2
- spawn (0)
- if ((A && A.loc))
- A.loc.Entered(A)
-
- else if (src.y >= world.maxy)
- if(istype(A, /obj/effect/meteor)||istype(A, /obj/effect/space_dust))
- del(A)
- return
- var/list/cur_pos = src.get_global_map_pos()
- if(!cur_pos) return
- cur_x = cur_pos["x"]
- cur_y = cur_pos["y"]
- y_arr = global_map[cur_x]
- next_y = (++cur_y > y_arr.len ? 1 : cur_y)
- target_z = y_arr[next_y]
-/*
- //debug
- world << "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]"
- world << "Next Y = [next_y]"
- world << "Target Z = [target_z]"
- //debug
-*/
- if(target_z)
- A.z = target_z
- A.y = 3
- spawn (0)
- if ((A && A.loc))
- A.loc.Entered(A)
- return
-
-/obj/effect/vaultspawner
- var/maxX = 6
- var/maxY = 6
- var/minX = 2
- var/minY = 2
-
-/obj/effect/vaultspawner/New(turf/location as turf,lX = minX,uX = maxX,lY = minY,uY = maxY,var/type = null)
- if(!type)
- type = pick("sandstone","rock","alien")
-
- var/lowBoundX = location.x
- var/lowBoundY = location.y
-
- var/hiBoundX = location.x + rand(lX,uX)
- var/hiBoundY = location.y + rand(lY,uY)
-
- var/z = location.z
-
- for(var/i = lowBoundX,i<=hiBoundX,i++)
- for(var/j = lowBoundY,j<=hiBoundY,j++)
- if(i == lowBoundX || i == hiBoundX || j == lowBoundY || j == hiBoundY)
- new /turf/simulated/wall/vault(locate(i,j,z),type)
- else
- new /turf/simulated/floor/vault(locate(i,j,z),type)
-
- del(src)
-
-/turf/proc/kill_creatures(mob/U = null)//Will kill people/creatures and damage mechs./N
-//Useful to batch-add creatures to the list.
- for(var/mob/living/M in src)
- if(M==U) continue//Will not harm U. Since null != M, can be excluded to kill everyone.
- spawn(0)
- M.gib()
- for(var/obj/mecha/M in src)//Mecha are not gibbed but are damaged.
- spawn(0)
- M.take_damage(100, "brute")
- for(var/obj/effect/critter/M in src)
- spawn(0)
- M.Die()
-
-/turf/proc/Bless()
- if(flags & NOJAUNT)
- return
- flags |= NOJAUNT
+/*
+/obj/vehicle/airtight
+ //inner atmos
+ var/use_internal_tank = 0
+ var/internal_tank_valve = ONE_ATMOSPHERE
+ var/obj/machinery/portable_atmospherics/canister/internal_tank
+ var/datum/gas_mixture/cabin_air
+ var/obj/machinery/atmospherics/portables_connector/connected_port = null
+
+ 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
+
+
+/obj/vehicle/airtight/New()
+ ..()
+ src.add_airtank()
+ src.add_cabin()
+ src.add_airtight_iterators()
+
+
+
+
+//######################################### Helpers for airtight vehicles #########################################
+
+/obj/vehicle/airtight/proc/add_cabin()
+ cabin_air = new
+ cabin_air.temperature = T20C
+ cabin_air.volume = 200
+ cabin_air.oxygen = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
+ cabin_air.nitrogen = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
+ return cabin_air
+
+/obj/vehicle/airtight/proc/add_airtank()
+ internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src)
+ return internal_tank
+
+/obj/vehicle/airtight/proc/add_airtight_iterators()
+ pr_int_temp_processor = new /datum/global_iterator/vehicle_preserve_temp(list(src))
+ pr_give_air = new /datum/global_iterator/vehicle_tank_give_air(list(src))
+
+
+//######################################### Specific datums for airtight vehicles #################################
+
+
+/datum/global_iterator/vehicle_preserve_temp //normalizing cabin air temperature to 20 degrees celsium
+ delay = 20
+
+ process(var/obj/vehicle/airtight/V)
+ if(V.cabin_air && V.cabin_air.return_volume() > 0)
+ var/delta = V.cabin_air.temperature - T20C
+ V.cabin_air.temperature -= max(-10, min(10, round(delta/4,0.1)))
+ return
+
+
+/datum/global_iterator/vehicle_tank_give_air
+ delay = 15
+
+ process(var/obj/vehicle/airtight/V)
+ if(V.internal_tank)
+ var/datum/gas_mixture/tank_air = V.internal_tank.return_air()
+ var/datum/gas_mixture/cabin_air = V.cabin_air
+
+ var/release_pressure = V.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 = V.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
+ del(removed)
+ else
+ return stop()
+ return
+
+
+//######################################### Atmospherics for vehicles #############################################
+
+
+/obj/vehicle/proc/get_turf_air()
+ var/turf/T = get_turf(src)
+ if(T)
+ . = T.return_air()
+ return
+
+/obj/vehicle/airtight/remove_air(amount)
+ if(use_internal_tank)
+ return cabin_air.remove(amount)
+ else
+ var/turf/T = get_turf(src)
+ if(T)
+ return T.remove_air(amount)
+ return
+
+/obj/vehicle/airtight/return_air()
+ if(use_internal_tank)
+ return cabin_air
+ return get_turf_air()
+
+/obj/vehicle/airtight/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
+
+
+/obj/vehicle/airtight/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
+
+/obj/vehicle/airtight/proc/connect(obj/machinery/atmospherics/portables_connector/new_port)
+ //Make sure not already connected to something else
+ if(connected_port || !new_port || new_port.connected_device)
+ return 0
+
+ //Make sure are close enough for a valid connection
+ if(new_port.loc != src.loc)
+ return 0
+
+ //Perform the connection
+ connected_port = new_port
+ connected_port.connected_device = src
+
+ //Actually enforce the air sharing
+ var/datum/pipe_network/network = connected_port.return_network(src)
+ if(network && !(internal_tank.return_air() in network.gases))
+ network.gases += internal_tank.return_air()
+ network.update = 1
+ log_message("Vehicle airtank connected to external port.")
+ return 1
+
+/obj/vehicle/airtight/proc/disconnect()
+ if(!connected_port)
+ return 0
+
+ var/datum/pipe_network/network = connected_port.return_network(src)
+ if(network)
+ network.gases -= internal_tank.return_air()
+
+ connected_port.connected_device = null
+ connected_port = null
+ src.log_message("Vehicle airtank disconnected from external port.")
+ return 1
+
+
+
+
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+
+
+
+/obj/vehicle
+ name = "Vehicle"
+ icon = 'icons/vehicles/vehicles.dmi'
+ density = 1
+ anchored = 1
+ unacidable = 1 //To avoid the pilot-deleting shit that came with mechas
+ layer = MOB_LAYER
+ //var/can_move = 1
+ var/mob/living/carbon/occupant = null
+ //var/step_in = 10 //make a step in step_in/10 sec.
+ //var/dir_in = 2//What direction will the mech face when entered/powered on? Defaults to South.
+ //var/step_energy_drain = 10
+ var/health = 300 //health is health
+ //var/deflect_chance = 10 //chance to deflect the incoming projectiles, hits, or lesser the effect of ex_act.
+ //the values in this list show how much damage will pass through, not how much will be absorbed.
+ var/list/damage_absorption = list("brute"=0.8,"fire"=1.2,"bullet"=0.9,"laser"=1,"energy"=1,"bomb"=1)
+ var/obj/item/weapon/cell/cell //Our power source
+ var/state = 0
+ var/list/log = new
+ var/last_message = 0
+ var/add_req_access = 1
+ var/maint_access = 1
+ //var/dna //dna-locking the mech
+ var/list/proc_res = list() //stores proc owners, like proc_res["functionname"] = owner reference
+ var/datum/effect/effect/system/spark_spread/spark_system = new
+ var/lights = 0
+ var/lights_power = 6
+
+ //inner atmos //These go in airtight.dm, not all vehicles are space-faring -Agouri
+ //var/use_internal_tank = 0
+ //var/internal_tank_valve = ONE_ATMOSPHERE
+ //var/obj/machinery/portable_atmospherics/canister/internal_tank
+ //var/datum/gas_mixture/cabin_air
+ //var/obj/machinery/atmospherics/portables_connector/connected_port = null
+
+ var/obj/item/device/radio/radio = null
+
+ var/max_temperature = 2500
+ //var/internal_damage_threshold = 50 //health percentage below which internal damage is possible
+ var/internal_damage = 0 //contains bitflags
+
+ 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 //In airtight.dm you go -Agouri
+ var/datum/global_iterator/pr_inertial_movement //controls intertial movement in spesss
+
+ //var/datum/global_iterator/pr_give_air //moves air from tank to cabin //Y-you too -Agouri
+
+ var/datum/global_iterator/pr_internal_damage //processes internal damage
+
+
+ var/wreckage
+
+ var/list/equipment = new
+ var/obj/selected
+ //var/max_equip = 3
+
+ var/datum/events/events
+
+
+
+/obj/vehicle/New()
+ ..()
+ events = new
+ icon_state += "-unmanned"
+ add_radio()
+ //add_cabin() //No cabin for non-airtights
+
+ spark_system.set_up(2, 0, src)
+ spark_system.attach(src)
+ add_cell()
+ add_iterators()
+ removeVerb(/obj/mecha/verb/disconnect_from_port)
+ removeVerb(/atom/movable/verb/pull)
+ log_message("[src.name]'s functions initialised. Work protocols active - Entering IDLE mode.")
+ loc.Entered(src)
+ return
+
+
+//################ Helpers ###########################################################
+
+
+/obj/vehicle/proc/removeVerb(verb_path)
+ verbs -= verb_path
+
+/obj/vehicle/proc/addVerb(verb_path)
+ verbs += verb_path
+
+/*/obj/vehicle/proc/add_airtank() //In airtight.dm -Agouri
+ internal_tank = new /obj/machinery/portable_atmospherics/canister/air(src)
+ return internal_tank*/
+
+/obj/vehicle/proc/add_cell(var/obj/item/weapon/cell/C=null)
+ if(C)
+ C.forceMove(src)
+ cell = C
+ return
+ cell = new(src)
+ cell.charge = 15000
+ cell.maxcharge = 15000
+
+/*/obj/vehicle/proc/add_cabin() //In airtight.dm -Agouri
+ cabin_air = new
+ cabin_air.temperature = T20C
+ cabin_air.volume = 200
+ cabin_air.oxygen = O2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
+ cabin_air.nitrogen = N2STANDARD*cabin_air.volume/(R_IDEAL_GAS_EQUATION*cabin_air.temperature)
+ return cabin_air*/
+
+/obj/vehicle/proc/add_radio()
+ radio = new(src)
+ radio.name = "[src] radio"
+ radio.icon = icon
+ radio.icon_state = icon_state
+ radio.subspace_transmission = 1
+
+/obj/vehicle/proc/add_iterators()
+ pr_inertial_movement = new /datum/global_iterator/vehicle_intertial_movement(null,0)
+ //pr_internal_damage = new /datum/global_iterator/vehicle_internal_damage(list(src),0)
+ //pr_int_temp_processor = new /datum/global_iterator/vehicle_preserve_temp(list(src)) //In airtight.dm's add_airtight_iterators -Agouri
+ //pr_give_air = new /datum/global_iterator/vehicle_tank_give_air(list(src) //Same here -Agouri
+
+/obj/vehicle/proc/check_for_support()
+ if(locate(/obj/structure/grille, orange(1, src)) || locate(/obj/structure/lattice, orange(1, src)) || locate(/turf/simulated, orange(1, src)) || locate(/turf/unsimulated, orange(1, src)))
+ return 1
+ else
+ return 0
+
+//################ Logs and messages ############################################
+
+
+/obj/vehicle/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
+
+
+
+//################ Global Iterator Datums ######################################
+
+
+/datum/global_iterator/vehicle_intertial_movement //inertial movement in space
+ delay = 7
+
+ process(var/obj/vehicle/V as obj, direction)
+ if(direction)
+ if(!step(V, direction)||V.check_for_support())
+ src.stop()
+ else
+ src.stop()
+ return
+
+
+/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
+ del(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)
+ return
+
+
+*/
+
+
+
+
+
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+
+
+
+
+/*/turf/DblClick()
+ if(istype(usr, /mob/living/silicon/ai))
+ return move_camera_by_click()
+ if(usr.stat || usr.restrained() || usr.lying)
+ return ..()
+
+ if(usr.hand && istype(usr.l_hand, /obj/item/weapon/flamethrower))
+ var/turflist = getline(usr,src)
+ var/obj/item/weapon/flamethrower/F = usr.l_hand
+ F.flame_turf(turflist)
+ else if(!usr.hand && istype(usr.r_hand, /obj/item/weapon/flamethrower))
+ var/turflist = getline(usr,src)
+ var/obj/item/weapon/flamethrower/F = usr.r_hand
+ F.flame_turf(turflist)
+
+ return ..()
+
+/turf/New()
+ ..()
+ for(var/atom/movable/AM as mob|obj in src)
+ spawn( 0 )
+ src.Entered(AM)
+ return
+ return
+
+/turf/ex_act(severity)
+ return 0
+
+
+/turf/bullet_act(var/obj/item/projectile/Proj)
+ if(istype(Proj ,/obj/item/projectile/beam/pulse))
+ src.ex_act(2)
+ ..()
+ return 0
+
+/turf/bullet_act(var/obj/item/projectile/Proj)
+ if(istype(Proj ,/obj/item/projectile/bullet/gyro))
+ explosion(src, -1, 0, 2)
+ ..()
+ return 0
+
+/turf/Enter(atom/movable/mover as mob|obj, atom/forget as mob|obj|turf|area)
+ if (!mover || !isturf(mover.loc))
+ return 1
+
+
+ //First, check objects to block exit that are not on the border
+ for(var/obj/obstacle in mover.loc)
+ if((obstacle.flags & ~ON_BORDER) && (mover != obstacle) && (forget != obstacle))
+ if(!obstacle.CheckExit(mover, src))
+ mover.Bump(obstacle, 1)
+ return 0
+
+ //Now, check objects to block exit that are on the border
+ for(var/obj/border_obstacle in mover.loc)
+ if((border_obstacle.flags & ON_BORDER) && (mover != border_obstacle) && (forget != border_obstacle))
+ if(!border_obstacle.CheckExit(mover, src))
+ mover.Bump(border_obstacle, 1)
+ return 0
+
+ //Next, check objects to block entry that are on the border
+ for(var/obj/border_obstacle in src)
+ if(border_obstacle.flags & ON_BORDER)
+ if(!border_obstacle.CanPass(mover, mover.loc, 1, 0) && (forget != border_obstacle))
+ mover.Bump(border_obstacle, 1)
+ return 0
+
+ //Then, check the turf itself
+ if (!src.CanPass(mover, src))
+ mover.Bump(src, 1)
+ return 0
+
+ //Finally, check objects/mobs to block entry that are not on the border
+ for(var/atom/movable/obstacle in src)
+ if(obstacle.flags & ~ON_BORDER)
+ if(!obstacle.CanPass(mover, mover.loc, 1, 0) && (forget != obstacle))
+ mover.Bump(obstacle, 1)
+ return 0
+ return 1 //Nothing found to block so return success!
+
+
+/turf/Entered(atom/movable/M as mob|obj)
+ var/loopsanity = 100
+ if(ismob(M))
+ if(!M:lastarea)
+ M:lastarea = get_area(M.loc)
+ if(M:lastarea.has_gravity == 0)
+ inertial_drift(M)
+
+ /*
+ if(M.flags & NOGRAV)
+ inertial_drift(M)
+ */
+
+
+
+ else if(!istype(src, /turf/space))
+ M:inertia_dir = 0
+ ..()
+ var/objects = 0
+ for(var/atom/A as mob|obj|turf|area in src)
+ if(objects > loopsanity) break
+ objects++
+ spawn( 0 )
+ if ((A && M))
+ A.HasEntered(M, 1)
+ return
+ objects = 0
+ for(var/atom/A as mob|obj|turf|area in range(1))
+ if(objects > loopsanity) break
+ objects++
+ spawn( 0 )
+ if ((A && M))
+ A.HasProximity(M, 1)
+ return
+ return
+
+/turf/proc/inertial_drift(atom/movable/A as mob|obj)
+ if(!(A.last_move)) return
+ if((istype(A, /mob/) && src.x > 2 && src.x < (world.maxx - 1) && src.y > 2 && src.y < (world.maxy-1)))
+ var/mob/M = A
+ if(M.Process_Spacemove(1))
+ M.inertia_dir = 0
+ return
+ spawn(5)
+ if((M && !(M.anchored) && (M.loc == src)))
+ if(M.inertia_dir)
+ step(M, M.inertia_dir)
+ return
+ M.inertia_dir = M.last_move
+ step(M, M.inertia_dir)
+ return
+
+/turf/proc/levelupdate()
+ for(var/obj/O in src)
+ if(O.level == 1)
+ O.hide(src.intact)
+
+// override for space turfs, since they should never hide anything
+/turf/space/levelupdate()
+ for(var/obj/O in src)
+ if(O.level == 1)
+ O.hide(0)
+
+// Removes all signs of lattice on the pos of the turf -Donkieyo
+/turf/proc/RemoveLattice()
+ var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
+ if(L)
+ del L
+
+/turf/proc/ReplaceWithFloor(explode=0)
+ var/prior_icon = icon_old
+ var/old_dir = dir
+
+ var/turf/simulated/floor/W = new /turf/simulated/floor( locate(src.x, src.y, src.z) )
+
+ W.RemoveLattice()
+ W.dir = old_dir
+ if(prior_icon) W.icon_state = prior_icon
+ else W.icon_state = "floor"
+
+ if (!explode)
+ W.opacity = 1
+ W.sd_SetOpacity(0)
+ //This is probably gonna make lighting go a bit wonky in bombed areas, but sd_SetOpacity was the primary reason bombs have been so laggy. --NEO
+ W.levelupdate()
+ return W
+
+/turf/proc/ReplaceWithPlating()
+ var/prior_icon = icon_old
+ var/old_dir = dir
+
+ var/turf/simulated/floor/plating/W = new /turf/simulated/floor/plating( locate(src.x, src.y, src.z) )
+
+ W.RemoveLattice()
+ W.dir = old_dir
+ if(prior_icon) W.icon_state = prior_icon
+ else W.icon_state = "plating"
+ W.opacity = 1
+ W.sd_SetOpacity(0)
+ W.levelupdate()
+ return W
+
+/turf/proc/ReplaceWithEngineFloor()
+ var/old_dir = dir
+
+ var/turf/simulated/floor/engine/E = new /turf/simulated/floor/engine( locate(src.x, src.y, src.z) )
+
+ E.dir = old_dir
+ E.icon_state = "engine"
+
+/turf/simulated/Entered(atom/A, atom/OL)
+ if (istype(A,/mob/living/carbon))
+ var/mob/living/carbon/M = A
+ if(M.lying) return
+ if(istype(M, /mob/living/carbon/human))
+ var/mob/living/carbon/human/H = M
+ if(istype(H.shoes, /obj/item/clothing/shoes/clown_shoes))
+ if(H.m_intent == "run")
+ if(H.footstep >= 2)
+ H.footstep = 0
+ else
+ H.footstep++
+ if(H.footstep == 0)
+ playsound(src, "clownstep", 50, 1) // this will get annoying very fast.
+ else
+ playsound(src, "clownstep", 20, 1)
+
+ switch (src.wet)
+ if(1)
+ if(istype(M, /mob/living/carbon/human)) // Added check since monkeys don't have shoes
+ if ((M.m_intent == "run") && !(istype(M:shoes, /obj/item/clothing/shoes) && M:shoes.flags&NOSLIP))
+ M.stop_pulling()
+ step(M, M.dir)
+ M << "\blue You slipped on the wet floor!"
+ playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3)
+ M.Stun(8)
+ M.Weaken(5)
+ else
+ M.inertia_dir = 0
+ return
+ else if(!istype(M, /mob/living/carbon/slime))
+ if (M.m_intent == "run")
+ M.stop_pulling()
+ step(M, M.dir)
+ M << "\blue You slipped on the wet floor!"
+ playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3)
+ M.Stun(8)
+ M.Weaken(5)
+ else
+ M.inertia_dir = 0
+ return
+
+ if(2) //lube
+ if(!istype(M, /mob/living/carbon/slime))
+ M.stop_pulling()
+ step(M, M.dir)
+ spawn(1) step(M, M.dir)
+ spawn(2) step(M, M.dir)
+ spawn(3) step(M, M.dir)
+ spawn(4) step(M, M.dir)
+ M.take_organ_damage(2) // Was 5 -- TLE
+ M << "\blue You slipped on the floor!"
+ playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3)
+ M.Weaken(10)
+
+ ..()
+
+/turf/proc/ReplaceWithSpace()
+ var/old_dir = dir
+ var/turf/space/S = new /turf/space( locate(src.x, src.y, src.z) )
+ S.dir = old_dir
+ return S
+
+/turf/proc/ReplaceWithLattice()
+ var/old_dir = dir
+ var/turf/space/S = new /turf/space( locate(src.x, src.y, src.z) )
+ S.dir = old_dir
+ new /obj/structure/lattice( locate(src.x, src.y, src.z) )
+ return S
+
+/turf/proc/ReplaceWithWall()
+ var/old_icon = icon_state
+ var/turf/simulated/wall/S = new /turf/simulated/wall( locate(src.x, src.y, src.z) )
+ S.icon_old = old_icon
+ S.opacity = 0
+ S.sd_NewOpacity(1)
+ return S
+
+/turf/proc/ReplaceWithRWall()
+ var/old_icon = icon_state
+ var/turf/simulated/wall/r_wall/S = new /turf/simulated/wall/r_wall( locate(src.x, src.y, src.z) )
+ S.icon_old = old_icon
+ S.opacity = 0
+ S.sd_NewOpacity(1)
+ return S
+
+/turf/simulated/wall/New()
+ ..()
+
+/turf/simulated/wall/proc/dismantle_wall(devastated=0, explode=0)
+ if(istype(src,/turf/simulated/wall/r_wall))
+ if(!devastated)
+ playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
+ new /obj/structure/girder/reinforced(src)
+ new /obj/item/stack/sheet/plasteel( src )
+ else
+ new /obj/item/stack/sheet/metal( src )
+ new /obj/item/stack/sheet/metal( src )
+ new /obj/item/stack/sheet/plasteel( src )
+ else if(istype(src,/turf/simulated/wall/cult))
+ if(!devastated)
+ playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
+ new /obj/effect/decal/remains/human(src)
+ else
+ new /obj/effect/decal/remains/human(src)
+
+ else
+ if(!devastated)
+ playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
+ new /obj/structure/girder(src)
+ new /obj/item/stack/sheet/metal( src )
+ new /obj/item/stack/sheet/metal( src )
+ else
+ new /obj/item/stack/sheet/metal( src )
+ new /obj/item/stack/sheet/metal( src )
+ new /obj/item/stack/sheet/metal( src )
+
+ ReplaceWithPlating(explode)
+
+/turf/simulated/wall/examine()
+ set src in oview(1)
+
+ usr << "It looks like a regular wall."
+ return
+
+/turf/simulated/wall/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ //SN src = null
+ src.ReplaceWithSpace()
+ del(src)
+ return
+ if(2.0)
+ if (prob(50))
+ dismantle_wall(0,1)
+ else
+ dismantle_wall(1,1)
+ if(3.0)
+ var/proba
+ if (istype(src, /turf/simulated/wall/r_wall))
+ proba = 15
+ else
+ proba = 40
+ if (prob(proba))
+ dismantle_wall(0,1)
+ else
+ return
+
+/turf/simulated/wall/blob_act()
+ if(prob(50))
+ dismantle_wall()
+
+/turf/simulated/wall/attack_paw(mob/user as mob)
+ if ((user.mutations & HULK))
+ if (prob(40))
+ usr << text("\blue You smash through the wall.")
+ dismantle_wall(1)
+ return
+ else
+ usr << text("\blue You punch the wall.")
+ return
+
+ return src.attack_hand(user)
+
+
+/turf/simulated/wall/attack_animal(mob/living/simple_animal/M as mob)
+ if(M.wall_smash)
+ if (istype(src, /turf/simulated/wall/r_wall))
+ M << text("\blue This wall is far too strong for you to destroy.")
+ return
+ else
+ if (prob(40))
+ M << text("\blue You smash through the wall.")
+ dismantle_wall(1)
+ return
+ else
+ M << text("\blue You smash against the wall.")
+ return
+
+ M << "\blue You push the wall but nothing happens!"
+ return
+
+/turf/simulated/wall/attack_hand(mob/user as mob)
+ if ((user.mutations & HULK))
+ if (prob(40))
+ usr << text("\blue You smash through the wall.")
+ dismantle_wall(1)
+ return
+ else
+ usr << text("\blue You punch the wall.")
+ return
+
+ user << "\blue You push the wall but nothing happens!"
+ playsound(src.loc, 'sound/weapons/Genhit.ogg', 25, 1)
+ src.add_fingerprint(user)
+ return
+
+/turf/simulated/wall/attackby(obj/item/weapon/W as obj, mob/user as mob)
+
+ if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
+ usr << "\red You don't have the dexterity to do this!"
+ return
+
+ if (istype(W, /obj/item/weapon/weldingtool) && W:welding)
+ var/turf/T = get_turf(user)
+ if (!( istype(T, /turf) ))
+ return
+
+ if (thermite)
+ var/obj/effect/overlay/O = new/obj/effect/overlay( src )
+ O.name = "Thermite"
+ O.desc = "Looks hot."
+ O.icon = 'icons/effects/fire.dmi'
+ O.icon_state = "2"
+ O.anchored = 1
+ O.density = 1
+ O.layer = 5
+ var/turf/simulated/floor/F = ReplaceWithPlating()
+ F.burn_tile()
+ F.icon_state = "wall_thermite"
+ user << "\red The thermite melts the wall."
+ spawn(100) del(O)
+ F.sd_LumReset()
+ return
+
+ if (W:remove_fuel(0,user))
+ W:welding = 2
+ user << "\blue Now disassembling the outer wall plating."
+ playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
+ sleep(100)
+ if (W && istype(src, /turf/simulated/wall))
+ if ((get_turf(user) == T && user.equipped() == W))
+ user << "\blue You disassembled the outer wall plating."
+ dismantle_wall()
+ W:welding = 1
+ else
+ user << "\blue You need more welding fuel to complete this task."
+ return
+
+ else if (istype(W, /obj/item/weapon/pickaxe/plasmacutter))
+ var/turf/T = user.loc
+ if (!( istype(T, /turf) ))
+ return
+
+ if (thermite)
+ var/obj/effect/overlay/O = new/obj/effect/overlay( src )
+ O.name = "Thermite"
+ O.desc = "Looks hot."
+ O.icon = 'icons/effects/fire.dmi'
+ O.icon_state = "2"
+ O.anchored = 1
+ O.density = 1
+ O.layer = 5
+ var/turf/simulated/floor/F = ReplaceWithPlating()
+ F.burn_tile()
+ F.icon_state = "wall_thermite"
+ user << "\red The thermite melts the wall."
+ spawn(100) del(O)
+ F.sd_LumReset()
+ return
+
+ else
+ user << "\blue Now disassembling the outer wall plating."
+ playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
+ sleep(60)
+ if (W && istype(src, /turf/simulated/wall))
+ if ((get_turf(user) == T && user.equipped() == W))
+ user << "\blue You disassembled the outer wall plating."
+ dismantle_wall()
+ for(var/mob/O in viewers(user, 5))
+ O.show_message(text("\blue The wall was sliced apart by []!", user), 1, text("\red You hear metal being sliced apart."), 2)
+ return
+
+ else if(istype(W, /obj/item/weapon/pickaxe/diamonddrill))
+ var/turf/T = user.loc
+ user << "\blue Now drilling through wall."
+ sleep(60)
+ if (W && istype(src, /turf/simulated/wall))
+ if ((user.loc == T && user.equipped() == W))
+ dismantle_wall(1)
+ for(var/mob/O in viewers(user, 5))
+ O.show_message(text("\blue The wall was drilled apart by []!", user), 1, text("\red You hear metal being drilled appart."), 2)
+ return
+
+ else if(istype(W, /obj/item/weapon/melee/energy/blade))
+ var/turf/T = user.loc
+ user << "\blue Now slicing through wall."
+ W:spark_system.start()
+ playsound(src.loc, "sparks", 50, 1)
+ sleep(70)
+ if (W && istype(src, /turf/simulated/wall))
+ if ((user.loc == T && user.equipped() == W))
+ W:spark_system.start()
+ playsound(src.loc, "sparks", 50, 1)
+ playsound(src.loc, 'sound/weapons/blade1.ogg', 50, 1)
+ dismantle_wall(1)
+ for(var/mob/O in viewers(user, 5))
+ O.show_message(text("\blue The wall was sliced apart by []!", user), 1, text("\red You hear metal being sliced and sparks flying."), 2)
+ return
+
+ else if(istype(W,/obj/item/apc_frame))
+ var/obj/item/apc_frame/AH = W
+ AH.try_build(src)
+ else if(istype(W,/obj/item/weapon/contraband/poster))
+ var/obj/item/weapon/contraband/poster/P = W
+ if(P.resulting_poster)
+ var/check = 0
+ var/stuff_on_wall = 0
+ for( var/obj/O in src.contents) //Let's see if it already has a poster on it or too much stuff
+ if(istype(O,/obj/effect/decal/poster))
+ check = 1
+ break
+ stuff_on_wall++
+ if(stuff_on_wall==3)
+ check = 1
+ break
+
+ if(check)
+ user << "The wall is far too cluttered to place a poster!"
+ return
+
+ user << "You start placing the poster on the wall..." //Looks like it's uncluttered enough. Place the poster.
+
+ P.resulting_poster.loc = src
+ var/temp = P.resulting_poster.icon_state
+ var/temp_loc = user.loc
+ P.resulting_poster.icon_state = "poster_being_set"
+ playsound(P.resulting_poster.loc, 'sound/items/poster_being_created.ogg', 100, 1)
+ sleep(24)
+
+ if(user.loc == temp_loc)//Let's check if he still is there
+ user << "You place the poster!"
+ P.resulting_poster.icon_state = temp
+ src.contents += P.resulting_poster
+ del(P)
+ else
+ user << "You stop placing the poster."
+ P.resulting_poster.loc = P
+ P.resulting_poster.icon_state = temp
+ else
+ return attack_hand(user)
+ return
+
+
+/turf/simulated/wall/r_wall/attackby(obj/item/W as obj, mob/user as mob)
+
+ if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
+ usr << "\red You don't have the dexterity to do this!"
+ return
+
+ if(!istype(src, /turf/simulated/wall/r_wall))
+ return // this may seem stupid and redundant but apparently floors can call this attackby() proc, it was spamming shit up. -- Doohl
+
+
+ if (istype(W, /obj/item/weapon/weldingtool) && W:welding)
+ W:eyecheck(user)
+ var/turf/T = user.loc
+ if (!( istype(T, /turf) ))
+ return
+
+ if (thermite)
+ var/obj/effect/overlay/O = new/obj/effect/overlay( src )
+ O.name = "Thermite"
+ O.desc = "Looks hot."
+ O.icon = 'icons/effects/fire.dmi'
+ O.icon_state = "2"
+ O.anchored = 1
+ O.density = 1
+ O.layer = 5
+ var/turf/simulated/floor/F = ReplaceWithPlating()
+ F.burn_tile()
+ F.icon_state = "wall_thermite"
+ user << "\red The thermite melts the wall."
+ spawn(100) del(O)
+ F.sd_LumReset()
+ return
+
+ if (src.d_state == 2)
+ W:welding = 2
+ user << "\blue Slicing metal cover."
+ playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
+ sleep(60)
+ if ((user.loc == T && user.equipped() == W))
+ src.d_state = 3
+ user << "\blue You removed the metal cover."
+ W:welding = 1
+
+ else if (src.d_state == 5)
+ W:welding = 2
+ user << "\blue Removing support rods."
+ playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
+ sleep(100)
+ if ((user.loc == T && user.equipped() == W))
+ src.d_state = 6
+ new /obj/item/stack/rods( src )
+ user << "\blue You removed the support rods."
+ W:welding = 1
+
+ else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter))
+ var/turf/T = user.loc
+ if (!( istype(T, /turf) ))
+ return
+
+ if (thermite)
+ var/obj/effect/overlay/O = new/obj/effect/overlay( src )
+ O.name = "Thermite"
+ O.desc = "Looks hot."
+ O.icon = 'icons/effects/fire.dmi'
+ O.icon_state = "2"
+ O.anchored = 1
+ O.density = 1
+ O.layer = 5
+ var/turf/simulated/floor/F = ReplaceWithPlating()
+ F.burn_tile()
+ F.icon_state = "wall_thermite"
+ user << "\red The thermite melts the wall."
+ spawn(100) del(O)
+ F.sd_LumReset()
+ return
+
+ if (src.d_state == 2)
+ user << "\blue Slicing metal cover."
+ playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
+ sleep(40)
+ if ((user.loc == T && user.equipped() == W))
+ src.d_state = 3
+ user << "\blue You removed the metal cover."
+
+ else if (src.d_state == 5)
+ user << "\blue Removing support rods."
+ playsound(src.loc, 'sound/items/Welder.ogg', 100, 1)
+ sleep(70)
+ if ((user.loc == T && user.equipped() == W))
+ src.d_state = 6
+ new /obj/item/stack/rods( src )
+ user << "\blue You removed the support rods."
+
+ else if(istype(W, /obj/item/weapon/melee/energy/blade))
+ user << "\blue This wall is too thick to slice through. You will need to find a different path."
+ return
+
+ else if (istype(W, /obj/item/weapon/wrench))
+ if (src.d_state == 4)
+ var/turf/T = user.loc
+ user << "\blue Detaching support rods."
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
+ sleep(40)
+ if ((user.loc == T && user.equipped() == W))
+ src.d_state = 5
+ user << "\blue You detach the support rods."
+
+ else if (istype(W, /obj/item/weapon/wirecutters))
+ if (src.d_state == 0)
+ playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
+ src.d_state = 1
+ new /obj/item/stack/rods( src )
+
+ else if (istype(W, /obj/item/weapon/screwdriver))
+ if (src.d_state == 1)
+ var/turf/T = user.loc
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1)
+ user << "\blue Removing support lines."
+ sleep(40)
+ if ((user.loc == T && user.equipped() == W))
+ src.d_state = 2
+ user << "\blue You removed the support lines."
+
+ else if (istype(W, /obj/item/weapon/crowbar))
+
+ if (src.d_state == 3)
+ var/turf/T = user.loc
+ user << "\blue Prying cover off."
+ playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
+ sleep(100)
+ if ((user.loc == T && user.equipped() == W))
+ src.d_state = 4
+ user << "\blue You removed the cover."
+
+ else if (src.d_state == 6)
+ var/turf/T = user.loc
+ user << "\blue Prying outer sheath off."
+ playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
+ sleep(100)
+ if(src)
+ if ((user.loc == T && user.equipped() == W))
+ user << "\blue You removed the outer sheath."
+ dismantle_wall()
+ return
+
+ else if (istype(W, /obj/item/weapon/pickaxe/diamonddrill))
+ var/turf/T = user.loc
+ user << "\blue You begin to drill though, this will take some time."
+ sleep(200)
+ if(src)
+ if ((user.loc == T && user.equipped() == W))
+ user << "\blue Your drill tears though the reinforced plating."
+ dismantle_wall()
+ return
+
+ else if ((istype(W, /obj/item/stack/sheet/metal)) && (src.d_state))
+ var/turf/T = user.loc
+ user << "\blue Repairing wall."
+ sleep(100)
+ if ((user.loc == T && user.equipped() == W))
+ src.d_state = 0
+ src.icon_state = initial(src.icon_state)
+ user << "\blue You repaired the wall."
+ if (W:amount > 1)
+ W:amount--
+ else
+ del(W)
+
+ else if(istype(W,/obj/item/weapon/contraband/poster))
+ var/obj/item/weapon/contraband/poster/P = W
+ if(P.resulting_poster)
+ var/check = 0
+ var/stuff_on_wall = 0
+ for( var/obj/O in src.contents) //Let's see if it already has a poster on it or too much stuff
+ if(istype(O,/obj/effect/decal/poster))
+ check = 1
+ break
+ stuff_on_wall++
+ if(stuff_on_wall==3)
+ check = 1
+ break
+
+ if(check)
+ user << "The wall is far too cluttered to place a poster!"
+ return
+
+ user << "You start placing the poster on the wall..." //Looks like it's uncluttered enough. Place the poster.
+
+ P.resulting_poster.loc = src
+ var/temp = P.resulting_poster.icon_state
+ var/temp_loc = user.loc
+ P.resulting_poster.icon_state = "poster_being_set"
+ playsound(P.resulting_poster.loc, 'sound/items/poster_being_created.ogg', 100, 1)
+ sleep(24)
+
+ if(user.loc == temp_loc)//Let's check if he still is there
+ user << "You place the poster!"
+ P.resulting_poster.icon_state = temp
+ src.contents += P.resulting_poster
+ del(P)
+ else
+ user << "You stop placing the poster."
+ P.resulting_poster.loc = P
+ P.resulting_poster.icon_state = temp
+ return
+
+ if(istype(W,/obj/item/apc_frame))
+ var/obj/item/apc_frame/AH = W
+ AH.try_build(src)
+ return
+
+ if(src.d_state > 0)
+ src.icon_state = "r_wall-[d_state]"
+
+ else
+ return attack_hand(user)
+ return
+
+/turf/simulated/wall/meteorhit(obj/M as obj)
+ if (prob(15))
+ dismantle_wall()
+ else if(prob(70))
+ ReplaceWithPlating()
+ else
+ ReplaceWithLattice()
+ return 0
+
+
+//This is so damaged or burnt tiles or platings don't get remembered as the default tile
+var/list/icons_to_ignore_at_floor_init = list("damaged1","damaged2","damaged3","damaged4",
+ "damaged5","panelscorched","floorscorched1","floorscorched2","platingdmg1","platingdmg2",
+ "platingdmg3","plating","light_on","light_on_flicker1","light_on_flicker2",
+ "light_on_clicker3","light_on_clicker4","light_on_clicker5","light_broken",
+ "light_on_broken","light_off","wall_thermite","grass1","grass2","grass3","grass4",
+ "asteroid","asteroid_dug",
+ "asteroid0","asteroid1","asteroid2","asteroid3","asteroid4",
+ "asteroid5","asteroid6","asteroid7","asteroid8",
+ "burning","oldburning","light-on-r","light-on-y","light-on-g","light-on-b")
+
+var/list/plating_icons = list("plating","platingdmg1","platingdmg2","platingdmg3","asteroid","asteroid_dug")
+
+/turf/simulated/floor
+
+ //Note to coders, the 'intact' var can no longer be used to determine if the floor is a plating or not.
+ //Use the is_plating(), is_plasteel_floor() and is_light_floor() procs instead. --Errorage
+ name = "floor"
+ icon = 'icons/turf/floors.dmi'
+ icon_state = "floor"
+ var/icon_regular_floor = "floor" //used to remember what icon the tile should have by default
+ var/icon_plating = "plating"
+ thermal_conductivity = 0.040
+ heat_capacity = 10000
+ var/broken = 0
+ var/burnt = 0
+ var/obj/item/stack/tile/floor_tile = new/obj/item/stack/tile/plasteel
+
+ airless
+ icon_state = "floor"
+ name = "airless floor"
+ oxygen = 0.01
+ nitrogen = 0.01
+ temperature = TCMB
+
+ New()
+ ..()
+ name = "floor"
+
+ light
+ name = "Light floor"
+ luminosity = 5
+ icon_state = "light_on"
+ floor_tile = new/obj/item/stack/tile/light
+
+ New()
+ floor_tile.New() //I guess New() isn't run on objects spawned without the definition of a turf to house them, ah well.
+ var/n = name //just in case commands rename it in the ..() call
+ ..()
+ spawn(4)
+ update_icon()
+ name = n
+
+ grass
+ name = "Grass patch"
+ icon_state = "grass1"
+ floor_tile = new/obj/item/stack/tile/grass
+
+ New()
+ floor_tile.New() //I guess New() isn't run on objects spawned without the definition of a turf to house them, ah well.
+ icon_state = "grass[pick("1","2","3","4")]"
+ ..()
+ spawn(4)
+ update_icon()
+ for(var/direction in cardinal)
+ if(istype(get_step(src,direction),/turf/simulated/floor))
+ var/turf/simulated/floor/FF = get_step(src,direction)
+ FF.update_icon() //so siding get updated properly
+
+/turf/simulated/floor/vault
+ icon_state = "rockvault"
+
+ New(location,type)
+ ..()
+ icon_state = "[type]vault"
+
+/turf/simulated/wall/vault
+ icon_state = "rockvault"
+
+ New(location,type)
+ ..()
+ icon_state = "[type]vault"
+
+/turf/simulated/floor/engine
+ name = "reinforced floor"
+ icon_state = "engine"
+ thermal_conductivity = 0.025
+ heat_capacity = 325000
+
+/turf/simulated/floor/engine/cult
+ name = "engraved floor"
+ icon_state = "cult"
+
+
+/turf/simulated/floor/engine/n20
+ New()
+ ..()
+ var/datum/gas_mixture/adding = new
+ var/datum/gas/sleeping_agent/trace_gas = new
+
+ trace_gas.moles = 2000
+ adding.trace_gases += trace_gas
+ adding.temperature = T20C
+
+ assume_air(adding)
+
+/turf/simulated/floor/engine/vacuum
+ name = "vacuum floor"
+ icon_state = "engine"
+ oxygen = 0
+ nitrogen = 0.001
+ temperature = TCMB
+
+/turf/simulated/floor/plating
+ name = "plating"
+ icon_state = "plating"
+ floor_tile = null
+ intact = 0
+
+/turf/simulated/floor/plating/airless
+ icon_state = "plating"
+ name = "airless plating"
+ oxygen = 0.01
+ nitrogen = 0.01
+ temperature = TCMB
+
+ New()
+ ..()
+ name = "plating"
+
+/turf/simulated/floor/grid
+ icon = 'icons/turf/floors.dmi'
+ icon_state = "circuit"
+
+/turf/simulated/floor/New()
+ ..()
+ if(icon_state in icons_to_ignore_at_floor_init) //so damaged/burned tiles or plating icons aren't saved as the default
+ icon_regular_floor = "floor"
+ else
+ icon_regular_floor = icon_state
+
+//turf/simulated/floor/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
+// if ((istype(mover, /obj/machinery/vehicle) && !(src.burnt)))
+// if (!( locate(/obj/machinery/mass_driver, src) ))
+// return 0
+// return ..()
+
+/turf/simulated/floor/ex_act(severity)
+ //set src in oview(1)
+ switch(severity)
+ if(1.0)
+ src.ReplaceWithSpace()
+ if(2.0)
+ switch(pick(1,2;75,3))
+ if (1)
+ src.ReplaceWithLattice()
+ if(prob(33)) new /obj/item/stack/sheet/metal(src)
+ if(2)
+ src.ReplaceWithSpace()
+ if(3)
+ if(prob(80))
+ src.break_tile_to_plating()
+ else
+ src.break_tile()
+ src.hotspot_expose(1000,CELL_VOLUME)
+ if(prob(33)) new /obj/item/stack/sheet/metal(src)
+ if(3.0)
+ if (prob(50))
+ src.break_tile()
+ src.hotspot_expose(1000,CELL_VOLUME)
+ return
+
+/turf/simulated/floor/blob_act()
+ return
+
+turf/simulated/floor/proc/update_icon()
+ if(is_plasteel_floor())
+ if(!broken && !burnt)
+ icon_state = icon_regular_floor
+ if(is_plating())
+ if(!broken && !burnt)
+ icon_state = icon_plating //Because asteroids are 'platings' too.
+ if(is_light_floor())
+ var/obj/item/stack/tile/light/T = floor_tile
+ if(T.on)
+ switch(T.state)
+ if(0)
+ icon_state = "light_on"
+ sd_SetLuminosity(5)
+ if(1)
+ var/num = pick("1","2","3","4")
+ icon_state = "light_on_flicker[num]"
+ sd_SetLuminosity(5)
+ if(2)
+ icon_state = "light_on_broken"
+ sd_SetLuminosity(5)
+ if(3)
+ icon_state = "light_off"
+ sd_SetLuminosity(0)
+ else
+ sd_SetLuminosity(0)
+ icon_state = "light_off"
+ if(is_grass_floor())
+ if(!broken && !burnt)
+ if(!(icon_state in list("grass1","grass2","grass3","grass4")))
+ icon_state = "grass[pick("1","2","3","4")]"
+ spawn(1)
+ if(istype(src,/turf/simulated/floor)) //Was throwing runtime errors due to a chance of it changing to space halfway through.
+ if(air)
+ update_visuals(air)
+
+turf/simulated/floor/return_siding_icon_state()
+ ..()
+ if(is_grass_floor())
+ var/dir_sum = 0
+ for(var/direction in cardinal)
+ var/turf/T = get_step(src,direction)
+ if(!(T.is_grass_floor()))
+ dir_sum += direction
+ if(dir_sum)
+ return "wood_siding[dir_sum]"
+ else
+ return 0
+
+
+/turf/simulated/floor/attack_paw(mob/user as mob)
+ return src.attack_hand(user)
+
+/turf/simulated/floor/attack_hand(mob/user as mob)
+ if (is_light_floor())
+ var/obj/item/stack/tile/light/T = floor_tile
+ T.on = !T.on
+ update_icon()
+ if ((!( user.canmove ) || user.restrained() || !( user.pulling )))
+ return
+ if (user.pulling.anchored)
+ return
+ if ((user.pulling.loc != user.loc && get_dist(user, user.pulling) > 1))
+ return
+ if (ismob(user.pulling))
+ var/mob/M = user.pulling
+ var/mob/t = M.pulling
+ M.stop_pulling()
+ step(user.pulling, get_dir(user.pulling.loc, src))
+ M.start_pulling(t)
+ else
+ step(user.pulling, get_dir(user.pulling.loc, src))
+ return
+
+/turf/simulated/floor/engine/attackby(obj/item/weapon/C as obj, mob/user as mob)
+ if(!C)
+ return
+ if(!user)
+ return
+ if(istype(C, /obj/item/weapon/wrench))
+ user << "\blue Removing rods..."
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 80, 1)
+ if(do_after(user, 30))
+ new /obj/item/stack/rods(src, 2)
+ ReplaceWithFloor()
+ var/turf/simulated/floor/F = src
+ F.make_plating()
+ return
+
+/turf/simulated/floor/proc/gets_drilled()
+ return
+
+/turf/simulated/floor/proc/break_tile_to_plating()
+ if(!is_plating())
+ make_plating()
+ break_tile()
+
+/turf/simulated/floor/is_plasteel_floor()
+ if(istype(floor_tile,/obj/item/stack/tile/plasteel))
+ return 1
+ else
+ return 0
+
+/turf/simulated/floor/is_light_floor()
+ if(istype(floor_tile,/obj/item/stack/tile/light))
+ return 1
+ else
+ return 0
+
+/turf/simulated/floor/is_grass_floor()
+ if(istype(floor_tile,/obj/item/stack/tile/grass))
+ return 1
+ else
+ return 0
+
+/turf/simulated/floor/is_plating()
+ if(!floor_tile)
+ return 1
+ return 0
+
+/turf/simulated/floor/proc/break_tile()
+ if(istype(src,/turf/simulated/floor/engine)) return
+ if(istype(src,/turf/simulated/floor/mech_bay_recharge_floor))
+ src.ReplaceWithPlating()
+ if(broken) return
+ if(is_plasteel_floor())
+ src.icon_state = "damaged[pick(1,2,3,4,5)]"
+ broken = 1
+ else if(is_plasteel_floor())
+ src.icon_state = "light_broken"
+ broken = 1
+ else if(is_plating())
+ src.icon_state = "platingdmg[pick(1,2,3)]"
+ broken = 1
+ else if(is_grass_floor())
+ src.icon_state = "sand[pick("1","2","3")]"
+ broken = 1
+
+/turf/simulated/floor/proc/burn_tile()
+ if(istype(src,/turf/simulated/floor/engine)) return
+ if(broken || burnt) return
+ if(is_plasteel_floor())
+ src.icon_state = "damaged[pick(1,2,3,4,5)]"
+ burnt = 1
+ else if(is_plasteel_floor())
+ src.icon_state = "floorscorched[pick(1,2)]"
+ burnt = 1
+ else if(is_plating())
+ src.icon_state = "panelscorched"
+ burnt = 1
+ else if(is_grass_floor())
+ src.icon_state = "sand[pick("1","2","3")]"
+ burnt = 1
+
+//This proc will delete the floor_tile and the update_iocn() proc will then change the icon_state of the turf
+//This proc auto corrects the grass tiles' siding.
+/turf/simulated/floor/proc/make_plating()
+ if(istype(src,/turf/simulated/floor/engine)) return
+
+ if(is_grass_floor())
+ for(var/direction in cardinal)
+ if(istype(get_step(src,direction),/turf/simulated/floor))
+ var/turf/simulated/floor/FF = get_step(src,direction)
+ FF.update_icon() //so siding get updated properly
+
+ if(!floor_tile) return
+ del(floor_tile)
+ icon_plating = "plating"
+ sd_SetLuminosity(0)
+ floor_tile = null
+ intact = 0
+ broken = 0
+ burnt = 0
+
+ update_icon()
+ levelupdate()
+
+//This proc will make the turf a plasteel floor tile. The expected argument is the tile to make the turf with
+//If none is given it will make a new object. dropping or unequipping must be handled before or after calling
+//this proc.
+/turf/simulated/floor/proc/make_plasteel_floor(var/obj/item/stack/tile/plasteel/T = null)
+ broken = 0
+ burnt = 0
+ intact = 1
+ sd_SetLuminosity(0)
+ if(T)
+ if(istype(T,/obj/item/stack/tile/plasteel))
+ floor_tile = T
+ if (icon_regular_floor)
+ icon_state = icon_regular_floor
+ else
+ icon_state = "floor"
+ icon_regular_floor = icon_state
+ update_icon()
+ levelupdate()
+ return
+ //if you gave a valid parameter, it won't get thisf ar.
+ floor_tile = new/obj/item/stack/tile/plasteel
+ icon_state = "floor"
+ icon_regular_floor = icon_state
+
+ update_icon()
+ levelupdate()
+
+//This proc will make the turf a light floor tile. The expected argument is the tile to make the turf with
+//If none is given it will make a new object. dropping or unequipping must be handled before or after calling
+//this proc.
+/turf/simulated/floor/proc/make_light_floor(var/obj/item/stack/tile/light/T = null)
+ broken = 0
+ burnt = 0
+ intact = 1
+ if(T)
+ if(istype(T,/obj/item/stack/tile/light))
+ floor_tile = T
+ update_icon()
+ levelupdate()
+ return
+ //if you gave a valid parameter, it won't get thisf ar.
+ floor_tile = new/obj/item/stack/tile/light
+
+ update_icon()
+ levelupdate()
+
+//This proc will make a turf into a grass patch. Fun eh? Insert the grass tile to be used as the argument
+//If no argument is given a new one will be made.
+/turf/simulated/floor/proc/make_grass_floor(var/obj/item/stack/tile/grass/T = null)
+ broken = 0
+ burnt = 0
+ intact = 1
+ if(T)
+ if(istype(T,/obj/item/stack/tile/grass))
+ floor_tile = T
+ update_icon()
+ levelupdate()
+ return
+ //if you gave a valid parameter, it won't get thisf ar.
+ floor_tile = new/obj/item/stack/tile/grass
+
+ update_icon()
+ levelupdate()
+
+/turf/simulated/floor/attackby(obj/item/C as obj, mob/user as mob)
+
+ if(!C || !user)
+ return 0
+
+ if(istype(C,/obj/item/weapon/light/bulb)) //only for light tiles
+ if(is_light_floor())
+ var/obj/item/stack/tile/light/T = floor_tile
+ if(T.state)
+ user.u_equip(C)
+ del(C)
+ T.state = C //fixing it by bashing it with a light bulb, fun eh?
+ update_icon()
+ user << "\blue You replace the light bulb."
+ else
+ user << "\blue The lightbulb seems fine, no need to replace it."
+
+ if(istype(C, /obj/item/weapon/crowbar) && (!(is_plating())))
+ if(broken || burnt)
+ user << "\red You remove the broken plating."
+ else
+ user << "\red You remove the [floor_tile.name]."
+ new floor_tile.type(src)
+
+ make_plating()
+ playsound(src.loc, 'sound/items/Crowbar.ogg', 80, 1)
+
+ return
+
+ if(istype(C, /obj/item/stack/rods))
+ var/obj/item/stack/rods/R = C
+ if (is_plating())
+ if (R.amount >= 2)
+ user << "\blue Reinforcing the floor..."
+ if(do_after(user, 30) && R && R.amount >= 2 && is_plating())
+ ReplaceWithEngineFloor()
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 80, 1)
+ R.use(2)
+ return
+ else
+ user << "\red You need more rods."
+ else
+ user << "\red You must remove the plating first."
+ return
+
+ if(istype(C, /obj/item/stack/tile))
+ if(is_plating())
+ if(!broken && !burnt)
+ var/obj/item/stack/tile/T = C
+ floor_tile = new T.type
+ intact = 1
+ if(istype(T,/obj/item/stack/tile/light))
+ var/obj/item/stack/tile/light/L = T
+ var/obj/item/stack/tile/light/F = floor_tile
+ F.state = L.state
+ F.on = L.on
+ if(istype(T,/obj/item/stack/tile/grass))
+ for(var/direction in cardinal)
+ if(istype(get_step(src,direction),/turf/simulated/floor))
+ var/turf/simulated/floor/FF = get_step(src,direction)
+ FF.update_icon() //so siding gets updated properly
+ T.use(1)
+ update_icon()
+ levelupdate()
+ playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1)
+ else
+ user << "\blue This section is too damaged to support a tile. Use a welder to fix the damage."
+
+
+ if(istype(C, /obj/item/stack/cable_coil))
+ if(is_plating())
+ var/obj/item/stack/cable_coil/coil = C
+ coil.turf_place(src, user)
+ else
+ user << "\red You must remove the plating first."
+
+ if(istype(C, /obj/item/weapon/shovel))
+ if(is_grass_floor())
+ new /obj/item/weapon/ore/glass(src)
+ new /obj/item/weapon/ore/glass(src) //Make some sand if you shovel grass
+ user << "\blue You shovel the grass."
+ make_plating()
+ else
+ user << "\red You cannot shovel this."
+
+ if(istype(C, /obj/item/weapon/weldingtool))
+ var/obj/item/weapon/weldingtool/welder = C
+ if(welder.welding && (is_plating()))
+ if(broken || burnt)
+ if(welder.remove_fuel(0,user))
+ user << "\red You fix some dents on the broken plating."
+ playsound(src.loc, 'sound/items/Welder.ogg', 80, 1)
+ icon_state = "plating"
+ burnt = 0
+ broken = 0
+ else
+ user << "\blue You need more welding fuel to complete this task."
+
+/turf/unsimulated/floor/attack_paw(user as mob)
+ return src.attack_hand(user)
+
+/turf/unsimulated/floor/attack_hand(var/mob/user as mob)
+ if ((!( user.canmove ) || user.restrained() || !( user.pulling )))
+ return
+ if (user.pulling.anchored)
+ return
+ if ((user.pulling.loc != user.loc && get_dist(user, user.pulling) > 1))
+ return
+ if (ismob(user.pulling))
+ var/mob/M = user.pulling
+ var/mob/t = M.pulling
+ M.stop_pulling()
+ step(user.pulling, get_dir(user.pulling.loc, src))
+ M.start_pulling(t)
+ else
+ step(user.pulling, get_dir(user.pulling.loc, src))
+ return
+
+// imported from space.dm
+
+/turf/space/attack_paw(mob/user as mob)
+ return src.attack_hand(user)
+
+/turf/space/attack_hand(mob/user as mob)
+ if ((user.restrained() || !( user.pulling )))
+ return
+ if (user.pulling.anchored)
+ return
+ if ((user.pulling.loc != user.loc && get_dist(user, user.pulling) > 1))
+ return
+ if (ismob(user.pulling))
+ var/mob/M = user.pulling
+ var/atom/movable/t = M.pulling
+ M.stop_pulling()
+ step(user.pulling, get_dir(user.pulling.loc, src))
+ M.start_pulling(t)
+ else
+ step(user.pulling, get_dir(user.pulling.loc, src))
+ return
+
+/turf/space/attackby(obj/item/C as obj, mob/user as mob)
+
+ if (istype(C, /obj/item/stack/rods))
+ var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
+ if(L)
+ return
+ var/obj/item/stack/rods/R = C
+ user << "\blue Constructing support lattice ..."
+ playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1)
+ ReplaceWithLattice()
+ R.use(1)
+ return
+
+ if (istype(C, /obj/item/stack/tile/plasteel))
+ var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
+ if(L)
+ var/obj/item/stack/tile/plasteel/S = C
+ del(L)
+ playsound(src.loc, 'sound/weapons/Genhit.ogg', 50, 1)
+ S.build(src)
+ S.use(1)
+ return
+ else
+ user << "\red The plating is going to need some support."
+ return
+
+
+// Ported from unstable r355
+
+/turf/space/Entered(atom/movable/A as mob|obj)
+ ..()
+ if ((!(A) || src != A.loc || istype(null, /obj/effect/beam))) return
+
+ inertial_drift(A)
+
+ if(ticker && ticker.mode)
+
+ // Okay, so let's make it so that people can travel z levels but not nuke disks!
+ // if(ticker.mode.name == "nuclear emergency") return
+
+ if(ticker.mode.name == "extended"||ticker.mode.name == "sandbox")
+ Sandbox_Spacemove(A)
+
+ else
+ if (src.x <= 2 || A.x >= (world.maxx - 1) || src.y <= 2 || A.y >= (world.maxy - 1))
+ if(istype(A, /obj/effect/meteor)||istype(A, /obj/effect/space_dust))
+ del(A)
+ return
+
+ if(istype(A, /obj/item/weapon/disk/nuclear)) // Don't let nuke disks travel Z levels ... And moving this shit down here so it only fires when they're actually trying to change z-level.
+ return
+
+ if(!isemptylist(A.search_contents_for(/obj/item/weapon/disk/nuclear)))
+ if(istype(A, /mob/living))
+ var/mob/living/MM = A
+ if(MM.client)
+ MM << "\red Something you are carrying is preventing you from leaving. Don't play stupid; you know exactly what it is."
+ return
+
+
+
+ var/move_to_z_str = pickweight(accessable_z_levels)
+
+ var/move_to_z = text2num(move_to_z_str)
+
+ if(!move_to_z)
+ return
+
+
+
+ A.z = move_to_z
+
+
+ if(src.x <= 2)
+ A.x = world.maxx - 2
+
+ else if (A.x >= (world.maxx - 1))
+ A.x = 3
+
+ else if (src.y <= 2)
+ A.y = world.maxy - 2
+
+ else if (A.y >= (world.maxy - 1))
+ A.y = 3
+
+ spawn (0)
+ if ((A && A.loc))
+ A.loc.Entered(A)
+
+// if(istype(A, /obj/structure/closet/coffin))
+// coffinhandler.Add(A)
+
+/turf/space/proc/Sandbox_Spacemove(atom/movable/A as mob|obj)
+ var/cur_x
+ var/cur_y
+ var/next_x
+ var/next_y
+ var/target_z
+ var/list/y_arr
+
+ if(src.x <= 1)
+ if(istype(A, /obj/effect/meteor)||istype(A, /obj/effect/space_dust))
+ del(A)
+ return
+
+ var/list/cur_pos = src.get_global_map_pos()
+ if(!cur_pos) return
+ cur_x = cur_pos["x"]
+ cur_y = cur_pos["y"]
+ next_x = (--cur_x||global_map.len)
+ y_arr = global_map[next_x]
+ target_z = y_arr[cur_y]
+/*
+ //debug
+ world << "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]"
+ world << "Target Z = [target_z]"
+ world << "Next X = [next_x]"
+ //debug
+*/
+ if(target_z)
+ A.z = target_z
+ A.x = world.maxx - 2
+ spawn (0)
+ if ((A && A.loc))
+ A.loc.Entered(A)
+ else if (src.x >= world.maxx)
+ if(istype(A, /obj/effect/meteor))
+ del(A)
+ return
+
+ var/list/cur_pos = src.get_global_map_pos()
+ if(!cur_pos) return
+ cur_x = cur_pos["x"]
+ cur_y = cur_pos["y"]
+ next_x = (++cur_x > global_map.len ? 1 : cur_x)
+ y_arr = global_map[next_x]
+ target_z = y_arr[cur_y]
+/*
+ //debug
+ world << "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]"
+ world << "Target Z = [target_z]"
+ world << "Next X = [next_x]"
+ //debug
+*/
+ if(target_z)
+ A.z = target_z
+ A.x = 3
+ spawn (0)
+ if ((A && A.loc))
+ A.loc.Entered(A)
+ else if (src.y <= 1)
+ if(istype(A, /obj/effect/meteor))
+ del(A)
+ return
+ var/list/cur_pos = src.get_global_map_pos()
+ if(!cur_pos) return
+ cur_x = cur_pos["x"]
+ cur_y = cur_pos["y"]
+ y_arr = global_map[cur_x]
+ next_y = (--cur_y||y_arr.len)
+ target_z = y_arr[next_y]
+/*
+ //debug
+ world << "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]"
+ world << "Next Y = [next_y]"
+ world << "Target Z = [target_z]"
+ //debug
+*/
+ if(target_z)
+ A.z = target_z
+ A.y = world.maxy - 2
+ spawn (0)
+ if ((A && A.loc))
+ A.loc.Entered(A)
+
+ else if (src.y >= world.maxy)
+ if(istype(A, /obj/effect/meteor)||istype(A, /obj/effect/space_dust))
+ del(A)
+ return
+ var/list/cur_pos = src.get_global_map_pos()
+ if(!cur_pos) return
+ cur_x = cur_pos["x"]
+ cur_y = cur_pos["y"]
+ y_arr = global_map[cur_x]
+ next_y = (++cur_y > y_arr.len ? 1 : cur_y)
+ target_z = y_arr[next_y]
+/*
+ //debug
+ world << "Src.z = [src.z] in global map X = [cur_x], Y = [cur_y]"
+ world << "Next Y = [next_y]"
+ world << "Target Z = [target_z]"
+ //debug
+*/
+ if(target_z)
+ A.z = target_z
+ A.y = 3
+ spawn (0)
+ if ((A && A.loc))
+ A.loc.Entered(A)
+ return
+
+/obj/effect/vaultspawner
+ var/maxX = 6
+ var/maxY = 6
+ var/minX = 2
+ var/minY = 2
+
+/obj/effect/vaultspawner/New(turf/location as turf,lX = minX,uX = maxX,lY = minY,uY = maxY,var/type = null)
+ if(!type)
+ type = pick("sandstone","rock","alien")
+
+ var/lowBoundX = location.x
+ var/lowBoundY = location.y
+
+ var/hiBoundX = location.x + rand(lX,uX)
+ var/hiBoundY = location.y + rand(lY,uY)
+
+ var/z = location.z
+
+ for(var/i = lowBoundX,i<=hiBoundX,i++)
+ for(var/j = lowBoundY,j<=hiBoundY,j++)
+ if(i == lowBoundX || i == hiBoundX || j == lowBoundY || j == hiBoundY)
+ new /turf/simulated/wall/vault(locate(i,j,z),type)
+ else
+ new /turf/simulated/floor/vault(locate(i,j,z),type)
+
+ del(src)
+
+/turf/proc/kill_creatures(mob/U = null)//Will kill people/creatures and damage mechs./N
+//Useful to batch-add creatures to the list.
+ for(var/mob/living/M in src)
+ if(M==U) continue//Will not harm U. Since null != M, can be excluded to kill everyone.
+ spawn(0)
+ M.gib()
+ for(var/obj/mecha/M in src)//Mecha are not gibbed but are damaged.
+ spawn(0)
+ M.take_damage(100, "brute")
+ for(var/obj/effect/critter/M in src)
+ spawn(0)
+ M.Die()
+
+/turf/proc/Bless()
+ if(flags & NOJAUNT)
+ return
+ flags |= NOJAUNT
overlays += image('icons/effects/water.dmi',src,"holywater")*/
\ No newline at end of file
diff --git a/code/unused/cable_heavyduty.dm b/code/unused/cable_heavyduty.dm
index 911fe50b43c..36bd4f93eb7 100644
--- a/code/unused/cable_heavyduty.dm
+++ b/code/unused/cable_heavyduty.dm
@@ -1,28 +1,28 @@
-/obj/item/stack/cable_coil/heavyduty
- name = "heavy cable coil"
- icon = 'icons/obj/power.dmi'
- icon_state = "wire"
-
-/obj/structure/cable/heavyduty
- icon = 'icons/obj/power_cond_heavy.dmi'
- name = "large power cable"
- desc = "This cable is tough. It cannot be cut with simple hand tools."
- layer = 2.39 //Just below pipes, which are at 2.4
-
-/obj/structure/cable/heavyduty/attackby(obj/item/W, mob/user)
-
- var/turf/T = src.loc
- if(T.intact)
- return
-
- if(istype(W, /obj/item/weapon/wirecutters))
- usr << "\blue These cables are too tough to be cut with those [W.name]."
- return
- else if(istype(W, /obj/item/stack/cable_coil))
- usr << "\blue You will need heavier cables to connect to these."
- return
- else
- ..()
-
-/obj/structure/cable/heavyduty/cableColor(var/colorC)
+/obj/item/stack/cable_coil/heavyduty
+ name = "heavy cable coil"
+ icon = 'icons/obj/power.dmi'
+ icon_state = "wire"
+
+/obj/structure/cable/heavyduty
+ icon = 'icons/obj/power_cond_heavy.dmi'
+ name = "large power cable"
+ desc = "This cable is tough. It cannot be cut with simple hand tools."
+ layer = 2.39 //Just below pipes, which are at 2.4
+
+/obj/structure/cable/heavyduty/attackby(obj/item/W, mob/user)
+
+ var/turf/T = src.loc
+ if(T.intact)
+ return
+
+ if(istype(W, /obj/item/weapon/wirecutters))
+ usr << "\blue These cables are too tough to be cut with those [W.name]."
+ return
+ else if(istype(W, /obj/item/stack/cable_coil))
+ usr << "\blue You will need heavier cables to connect to these."
+ return
+ else
+ ..()
+
+/obj/structure/cable/heavyduty/cableColor(var/colorC)
return
\ No newline at end of file
diff --git a/code/unused/computer2/buildandrepair.dm b/code/unused/computer2/buildandrepair.dm
index 69e7b5fb822..2fde1740b77 100644
--- a/code/unused/computer2/buildandrepair.dm
+++ b/code/unused/computer2/buildandrepair.dm
@@ -1,150 +1,150 @@
-//Motherboard is just used in assembly/disassembly, doesn't exist in the actual computer object.
-/obj/item/weapon/motherboard
- name = "Computer mainboard"
- desc = "A computer motherboard."
- icon = 'icons/obj/module.dmi'
- icon_state = "mainboard"
- item_state = "electronic"
- w_class = 3
- var/created_name = null //If defined, result computer will have this name.
-
-/obj/computer2frame
- density = 1
- anchored = 0
- name = "Computer-frame"
- icon = 'icons/obj/stock_parts.dmi'
- icon_state = "0"
- var/state = 0
- var/obj/item/weapon/motherboard/mainboard = null
- var/obj/item/weapon/disk/data/fixed_disk/hd = null
- var/list/peripherals = list()
- var/created_icon_state = "aiupload"
-
-/obj/computer2frame/attackby(obj/item/P as obj, mob/user as mob)
- switch(state)
- if(0)
- if(istype(P, /obj/item/weapon/wrench))
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- if(do_after(user, 20))
- user << "\blue You wrench the frame into place."
- src.anchored = 1
- src.state = 1
- if(istype(P, /obj/item/weapon/weldingtool))
- playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
- if(do_after(user, 20))
- user << "\blue You deconstruct the frame."
- new /obj/item/stack/sheet/metal( src.loc, 5 )
- del(src)
- if(1)
- if(istype(P, /obj/item/weapon/wrench))
- playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
- if(do_after(user, 20))
- user << "\blue You unfasten the frame."
- src.anchored = 0
- src.state = 0
- if(istype(P, /obj/item/weapon/motherboard) && !mainboard)
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
- user << "\blue You place the mainboard inside the frame."
- src.icon_state = "1"
- src.mainboard = P
- user.drop_item()
- P.loc = src
- if(istype(P, /obj/item/weapon/screwdriver) && mainboard)
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
- user << "\blue You screw the mainboard into place."
- src.state = 2
- src.icon_state = "2"
- if(istype(P, /obj/item/weapon/crowbar) && mainboard)
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
- user << "\blue You remove the mainboard."
- src.state = 1
- src.icon_state = "0"
- mainboard.loc = src.loc
- src.mainboard = null
- if(2)
- if(istype(P, /obj/item/weapon/screwdriver) && mainboard && (!peripherals.len))
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
- user << "\blue You unfasten the mainboard."
- src.state = 1
- src.icon_state = "1"
-
- if(istype(P, /obj/item/weapon/peripheral))
- if(src.peripherals.len < 3)
- user.drop_item()
- src.peripherals.Add(P)
- P.loc = src
- user << "\blue You add [P] to the frame."
- else
- user << "\red There is no more room for peripheral cards."
-
- if(istype(P, /obj/item/weapon/crowbar) && src.peripherals.len)
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
- user << "\blue You remove the peripheral boards."
- for(var/obj/item/weapon/peripheral/W in src.peripherals)
- W.loc = src.loc
- src.peripherals.Remove(W)
-
- if(istype(P, /obj/item/stack/cable_coil))
- if(P:amount >= 5)
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
- if(do_after(user, 20))
- P:amount -= 5
- if(!P:amount) del(P)
- user << "\blue You add cables to the frame."
- src.state = 3
- src.icon_state = "3"
- if(3)
- if(istype(P, /obj/item/weapon/wirecutters))
- playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
- user << "\blue You remove the cables."
- src.state = 2
- src.icon_state = "2"
- var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( src.loc )
- A.amount = 5
- if(src.hd)
- src.hd.loc = src.loc
- src.hd = null
-
- if(istype(P, /obj/item/weapon/disk/data/fixed_disk) && !src.hd)
- user.drop_item()
- src.hd = P
- P.loc = src
- user << "\blue You connect the drive to the cabling."
-
- if(istype(P, /obj/item/weapon/crowbar) && src.hd)
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
- user << "\blue You remove the hard drive."
- src.hd.loc = src.loc
- src.hd = null
-
- if(istype(P, /obj/item/stack/sheet/glass))
- if(P:amount >= 2)
- playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
- if(do_after(user, 20))
- P:use(2)
- user << "\blue You put in the glass panel."
- src.state = 4
- src.icon_state = "4"
- if(4)
- if(istype(P, /obj/item/weapon/crowbar))
- playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
- user << "\blue You remove the glass panel."
- src.state = 3
- src.icon_state = "3"
- new /obj/item/stack/sheet/glass( src.loc, 2 )
- if(istype(P, /obj/item/weapon/screwdriver))
- playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
- user << "\blue You connect the monitor."
- var/obj/machinery/computer2/C= new /obj/machinery/computer2( src.loc )
- C.setup_drive_size = 0
- C.icon_state = src.created_icon_state
- if(mainboard.created_name) C.name = mainboard.created_name
- del(mainboard)
- if(hd)
- C.hd = hd
- hd.loc = C
- for(var/obj/item/weapon/peripheral/W in src.peripherals)
- W.loc = C
- W.host = C
- C.peripherals.Add(W)
+//Motherboard is just used in assembly/disassembly, doesn't exist in the actual computer object.
+/obj/item/weapon/motherboard
+ name = "Computer mainboard"
+ desc = "A computer motherboard."
+ icon = 'icons/obj/module.dmi'
+ icon_state = "mainboard"
+ item_state = "electronic"
+ w_class = 3
+ var/created_name = null //If defined, result computer will have this name.
+
+/obj/computer2frame
+ density = 1
+ anchored = 0
+ name = "Computer-frame"
+ icon = 'icons/obj/stock_parts.dmi'
+ icon_state = "0"
+ var/state = 0
+ var/obj/item/weapon/motherboard/mainboard = null
+ var/obj/item/weapon/disk/data/fixed_disk/hd = null
+ var/list/peripherals = list()
+ var/created_icon_state = "aiupload"
+
+/obj/computer2frame/attackby(obj/item/P as obj, mob/user as mob)
+ switch(state)
+ if(0)
+ if(istype(P, /obj/item/weapon/wrench))
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ if(do_after(user, 20))
+ user << "\blue You wrench the frame into place."
+ src.anchored = 1
+ src.state = 1
+ if(istype(P, /obj/item/weapon/weldingtool))
+ playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
+ if(do_after(user, 20))
+ user << "\blue You deconstruct the frame."
+ new /obj/item/stack/sheet/metal( src.loc, 5 )
+ del(src)
+ if(1)
+ if(istype(P, /obj/item/weapon/wrench))
+ playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
+ if(do_after(user, 20))
+ user << "\blue You unfasten the frame."
+ src.anchored = 0
+ src.state = 0
+ if(istype(P, /obj/item/weapon/motherboard) && !mainboard)
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ user << "\blue You place the mainboard inside the frame."
+ src.icon_state = "1"
+ src.mainboard = P
+ user.drop_item()
+ P.loc = src
+ if(istype(P, /obj/item/weapon/screwdriver) && mainboard)
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ user << "\blue You screw the mainboard into place."
+ src.state = 2
+ src.icon_state = "2"
+ if(istype(P, /obj/item/weapon/crowbar) && mainboard)
+ playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ user << "\blue You remove the mainboard."
+ src.state = 1
+ src.icon_state = "0"
+ mainboard.loc = src.loc
+ src.mainboard = null
+ if(2)
+ if(istype(P, /obj/item/weapon/screwdriver) && mainboard && (!peripherals.len))
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ user << "\blue You unfasten the mainboard."
+ src.state = 1
+ src.icon_state = "1"
+
+ if(istype(P, /obj/item/weapon/peripheral))
+ if(src.peripherals.len < 3)
+ user.drop_item()
+ src.peripherals.Add(P)
+ P.loc = src
+ user << "\blue You add [P] to the frame."
+ else
+ user << "\red There is no more room for peripheral cards."
+
+ if(istype(P, /obj/item/weapon/crowbar) && src.peripherals.len)
+ playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ user << "\blue You remove the peripheral boards."
+ for(var/obj/item/weapon/peripheral/W in src.peripherals)
+ W.loc = src.loc
+ src.peripherals.Remove(W)
+
+ if(istype(P, /obj/item/stack/cable_coil))
+ if(P:amount >= 5)
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ if(do_after(user, 20))
+ P:amount -= 5
+ if(!P:amount) del(P)
+ user << "\blue You add cables to the frame."
+ src.state = 3
+ src.icon_state = "3"
+ if(3)
+ if(istype(P, /obj/item/weapon/wirecutters))
+ playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
+ user << "\blue You remove the cables."
+ src.state = 2
+ src.icon_state = "2"
+ var/obj/item/stack/cable_coil/A = new /obj/item/stack/cable_coil( src.loc )
+ A.amount = 5
+ if(src.hd)
+ src.hd.loc = src.loc
+ src.hd = null
+
+ if(istype(P, /obj/item/weapon/disk/data/fixed_disk) && !src.hd)
+ user.drop_item()
+ src.hd = P
+ P.loc = src
+ user << "\blue You connect the drive to the cabling."
+
+ if(istype(P, /obj/item/weapon/crowbar) && src.hd)
+ playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ user << "\blue You remove the hard drive."
+ src.hd.loc = src.loc
+ src.hd = null
+
+ if(istype(P, /obj/item/stack/sheet/glass))
+ if(P:amount >= 2)
+ playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
+ if(do_after(user, 20))
+ P:use(2)
+ user << "\blue You put in the glass panel."
+ src.state = 4
+ src.icon_state = "4"
+ if(4)
+ if(istype(P, /obj/item/weapon/crowbar))
+ playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
+ user << "\blue You remove the glass panel."
+ src.state = 3
+ src.icon_state = "3"
+ new /obj/item/stack/sheet/glass( src.loc, 2 )
+ if(istype(P, /obj/item/weapon/screwdriver))
+ playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
+ user << "\blue You connect the monitor."
+ var/obj/machinery/computer2/C= new /obj/machinery/computer2( src.loc )
+ C.setup_drive_size = 0
+ C.icon_state = src.created_icon_state
+ if(mainboard.created_name) C.name = mainboard.created_name
+ del(mainboard)
+ if(hd)
+ C.hd = hd
+ hd.loc = C
+ for(var/obj/item/weapon/peripheral/W in src.peripherals)
+ W.loc = C
+ W.host = C
+ C.peripherals.Add(W)
del(src)
\ No newline at end of file
diff --git a/code/unused/conveyor.dm b/code/unused/conveyor.dm
index ad4337b696c..0756be124f6 100644
--- a/code/unused/conveyor.dm
+++ b/code/unused/conveyor.dm
@@ -1,384 +1,384 @@
-// converyor belt
-
-// moves items/mobs/movables in set direction every ptick
-
-
-/obj/machinery/conveyor
- icon = 'icons/obj/recycling.dmi'
- icon_state = "conveyor0"
- name = "conveyor belt"
- desc = "A conveyor belt."
- anchored = 1
- var/operating = 0 // 1 if running forward, -1 if backwards, 0 if off
- var/operable = 1 // true if can operate (no broken segments in this belt run)
- var/basedir // this is the default (forward) direction, set by the map dir
- // note dir var can vary when the direction changes
-
- var/list/affecting // the list of all items that will be moved this ptick
- var/id = "" // the control ID - must match controller ID
- // following two only used if a diverter is present
- var/divert = 0 // if non-zero, direction to divert items
- var/divdir = 0 // if diverting, will be conveyer dir needed to divert (otherwise dense)
-
-
-
- // create a conveyor
-
-/obj/machinery/conveyor/New()
- ..()
- basedir = dir
- setdir()
-
- // set the dir and target turf depending on the operating direction
-
-/obj/machinery/conveyor/proc/setdir()
- if(operating == -1)
- dir = turn(basedir,180)
- else
- dir = basedir
- update()
-
-
- // update the icon depending on the operating condition
-
-/obj/machinery/conveyor/proc/update()
- if(stat & BROKEN)
- icon_state = "conveyor-b"
- operating = 0
- return
- if(!operable)
- operating = 0
- icon_state = "conveyor[(operating != 0) && !(stat & NOPOWER)]"
-
-
- // machine process
- // move items to the target location
-/obj/machinery/conveyor/process()
- if(stat & (BROKEN | NOPOWER))
- return
- if(!operating)
- return
- use_power(100)
-
- var/movedir = dir // base movement dir
- if(divert && dir==divdir) // update if diverter present
- movedir = divert
-
-
- affecting = loc.contents - src // moved items will be all in loc
- spawn(1) // slight delay to prevent infinite propagation due to map order
- var/items_moved = 0
- for(var/atom/movable/A in affecting)
- if(!A.anchored)
- if(isturf(A.loc)) // this is to prevent an ugly bug that forces a player to drop what they're holding if they recently pick it up from the conveyer belt
- if(ismob(A))
- var/mob/M = A
- if(M.buckled == src)
- var/obj/machinery/conveyor/C = locate() in get_step(src, dir)
- M.buckled = null
- step(M,dir)
- if(C)
- M.buckled = C
- else
- new/obj/item/stack/cable_coil/cut(M.loc)
- else
- step(M,movedir)
- else
- step(A,movedir)
- items_moved++
- if(items_moved >= 10)
- break
-
-// attack with item, place item on conveyor
-
-/obj/machinery/conveyor/attackby(var/obj/item/I, mob/user)
- if(istype(I, /obj/item/weapon/grab)) // special handling if grabbing a mob
- var/obj/item/weapon/grab/G = I
- G.affecting.Move(src.loc)
- del(G)
- return
- else if(istype(I, /obj/item/stack/cable_coil)) // if cable, see if a mob is present
- var/mob/M = locate() in src.loc
- if(M)
- if (M == user)
- src.visible_message("\blue [M] ties \himself to the conveyor.")
- // note don't check for lying if self-tying
- else
- if(M.lying)
- user.visible_message("\blue [M] has been tied to the conveyor by [user].", "\blue You tie [M] to the converyor!")
- else
- user << "\blue [M] must be lying down to be tied to the converyor!"
- return
- M.buckled = src
- src.add_fingerprint(user)
- I:use(1)
- M.lying = 1
- return
-
- // else if no mob in loc, then allow coil to be placed
-
- else if(istype(I, /obj/item/weapon/wirecutters))
- var/mob/M = locate() in src.loc
- if(M && M.buckled == src)
- M.buckled = null
- src.add_fingerprint(user)
- if (M == user)
- src.visible_message("\blue [M] cuts \himself free from the conveyor.")
- else
- src.visible_message("\blue [M] had been cut free from the conveyor by [user].")
- return
-
- if(isrobot(user))
- return
-
- // otherwise drop and place on conveyor
- user.drop_item()
- if(I && I.loc) I.loc = src.loc
- return
-
-// attack with hand, move pulled object onto conveyor
-
-/obj/machinery/conveyor/attack_hand(mob/user as mob)
- user.Move_Pulled(src)
-
-
-// make the conveyor broken
-// also propagate inoperability to any connected conveyor with the same ID
-/obj/machinery/conveyor/proc/broken()
- stat |= BROKEN
- update()
-
- var/obj/machinery/conveyor/C = locate() in get_step(src, basedir)
- if(C)
- C.set_operable(basedir, id, 0)
-
- C = locate() in get_step(src, turn(basedir,180))
- if(C)
- C.set_operable(turn(basedir,180), id, 0)
-
-
-//set the operable var if ID matches, propagating in the given direction
-
-/obj/machinery/conveyor/proc/set_operable(stepdir, match_id, op)
-
- if(id != match_id)
- return
- operable = op
-
- update()
- var/obj/machinery/conveyor/C = locate() in get_step(src, stepdir)
- if(C)
- C.set_operable(stepdir, id, op)
-
-/*
-/obj/machinery/conveyor/verb/destroy()
- set src in view()
- src.broken()
-*/
-
-/obj/machinery/conveyor/power_change()
- ..()
- update()
-
-
-// converyor diverter
-// extendable arm that can be switched so items on the conveyer are diverted sideways
-// situate in same turf as conveyor
-// only works if belts is running proper direction
-//
-//
-/obj/machinery/diverter
- icon = 'icons/obj/recycling.dmi'
- icon_state = "diverter0"
- name = "diverter"
- desc = "A diverter arm for a conveyor belt."
- anchored = 1
- layer = FLY_LAYER
- var/obj/machinery/conveyor/conv // the conveyor this diverter works on
- var/deployed = 0 // true if diverter arm is extended
- var/operating = 0 // true if arm is extending/contracting
- var/divert_to // the dir that diverted items will be moved
- var/divert_from // the dir items must be moving to divert
-
-
-// create a diverter
-// set up divert_to and divert_from directions depending on dir state
-/obj/machinery/diverter/New()
-
- ..()
-
- switch(dir)
- if(NORTH)
- divert_to = WEST // stuff will be moved to the west
- divert_from = NORTH // if entering from the north
- if(SOUTH)
- divert_to = EAST
- divert_from = NORTH
- if(EAST)
- divert_to = EAST
- divert_from = SOUTH
- if(WEST)
- divert_to = WEST
- divert_from = SOUTH
- if(NORTHEAST)
- divert_to = NORTH
- divert_from = EAST
- if(NORTHWEST)
- divert_to = NORTH
- divert_from = WEST
- if(SOUTHEAST)
- divert_to = SOUTH
- divert_from = EAST
- if(SOUTHWEST)
- divert_to = SOUTH
- divert_from = WEST
- spawn(2)
- // wait for map load then find the conveyor in this turf
- conv = locate() in src.loc
- if(conv) // divert_from dir must match possible conveyor movement
- if(conv.basedir != divert_from && conv.basedir != turn(divert_from,180) )
- del(src) // if no dir match, then delete self
- set_divert()
- update()
-
-// update the icon state depending on whether the diverter is extended
-/obj/machinery/diverter/proc/update()
- icon_state = "diverter[deployed]"
-
-// call to set the diversion vars of underlying conveyor
-/obj/machinery/diverter/proc/set_divert()
- if(conv)
- if(deployed)
- conv.divert = divert_to
- conv.divdir = divert_from
- else
- conv.divert= 0
-
-
-// *** TESTING click to toggle
-/obj/machinery/diverter/Click()
- toggle()
-
-
-// toggle between arm deployed and not deployed, showing animation
-//
-/obj/machinery/diverter/proc/toggle()
- if( stat & (NOPOWER|BROKEN))
- return
-
- if(operating)
- return
-
- use_power(50)
- operating = 1
- if(deployed)
- flick("diverter10",src)
- icon_state = "diverter0"
- sleep(10)
- deployed = 0
- else
- flick("diverter01",src)
- icon_state = "diverter1"
- sleep(10)
- deployed = 1
- operating = 0
- update()
- set_divert()
-
-// don't allow movement into the 'backwards' direction if deployed
-/obj/machinery/diverter/CanPass(atom/movable/O, var/turf/target)
- var/direct = get_dir(O, target)
- if(direct == divert_to) // prevent movement through body of diverter
- return 0
- if(!deployed)
- return 1
- return(direct != turn(divert_from,180))
-
-// don't allow movement through the arm if deployed
-/obj/machinery/diverter/CheckExit(atom/movable/O, var/turf/target)
- var/direct = get_dir(O, target)
- if(direct == turn(divert_to,180)) // prevent movement through body of diverter
- return 0
- if(!deployed)
- return 1
- return(direct != divert_from)
-
-
-
-
-
-// the conveyor control switch
-//
-//
-
-/obj/machinery/conveyor_switch
-
- name = "conveyor switch"
- desc = "A conveyor control switch."
- icon = 'icons/obj/recycling.dmi'
- icon_state = "switch-off"
- var/position = 0 // 0 off, -1 reverse, 1 forward
- var/last_pos = -1 // last direction setting
- var/operated = 1 // true if just operated
-
- var/id = "" // must match conveyor IDs to control them
-
- var/list/conveyors // the list of converyors that are controlled by this switch
- anchored = 1
-
-
-
-/obj/machinery/conveyor_switch/New()
- ..()
- update()
-
- spawn(5) // allow map load
- conveyors = list()
- for(var/obj/machinery/conveyor/C in world)
- if(C.id == id)
- conveyors += C
-
-// update the icon depending on the position
-
-/obj/machinery/conveyor_switch/proc/update()
- if(position<0)
- icon_state = "switch-rev"
- else if(position>0)
- icon_state = "switch-fwd"
- else
- icon_state = "switch-off"
-
-
-// timed process
-// if the switch changed, update the linked conveyors
-
-/obj/machinery/conveyor_switch/process()
- if(!operated)
- return
- operated = 0
-
- for(var/obj/machinery/conveyor/C in conveyors)
- C.operating = position
- C.setdir()
-
-// attack with hand, switch position
-/obj/machinery/conveyor_switch/attack_hand(mob/user)
- if(position == 0)
- if(last_pos < 0)
- position = 1
- last_pos = 0
- else
- position = -1
- last_pos = 0
- else
- last_pos = position
- position = 0
-
- operated = 1
- update()
-
- // find any switches with same id as this one, and set their positions to match us
- for(var/obj/machinery/conveyor_switch/S in world)
- if(S.id == src.id)
- S.position = position
- S.update()
+// converyor belt
+
+// moves items/mobs/movables in set direction every ptick
+
+
+/obj/machinery/conveyor
+ icon = 'icons/obj/recycling.dmi'
+ icon_state = "conveyor0"
+ name = "conveyor belt"
+ desc = "A conveyor belt."
+ anchored = 1
+ var/operating = 0 // 1 if running forward, -1 if backwards, 0 if off
+ var/operable = 1 // true if can operate (no broken segments in this belt run)
+ var/basedir // this is the default (forward) direction, set by the map dir
+ // note dir var can vary when the direction changes
+
+ var/list/affecting // the list of all items that will be moved this ptick
+ var/id = "" // the control ID - must match controller ID
+ // following two only used if a diverter is present
+ var/divert = 0 // if non-zero, direction to divert items
+ var/divdir = 0 // if diverting, will be conveyer dir needed to divert (otherwise dense)
+
+
+
+ // create a conveyor
+
+/obj/machinery/conveyor/New()
+ ..()
+ basedir = dir
+ setdir()
+
+ // set the dir and target turf depending on the operating direction
+
+/obj/machinery/conveyor/proc/setdir()
+ if(operating == -1)
+ dir = turn(basedir,180)
+ else
+ dir = basedir
+ update()
+
+
+ // update the icon depending on the operating condition
+
+/obj/machinery/conveyor/proc/update()
+ if(stat & BROKEN)
+ icon_state = "conveyor-b"
+ operating = 0
+ return
+ if(!operable)
+ operating = 0
+ icon_state = "conveyor[(operating != 0) && !(stat & NOPOWER)]"
+
+
+ // machine process
+ // move items to the target location
+/obj/machinery/conveyor/process()
+ if(stat & (BROKEN | NOPOWER))
+ return
+ if(!operating)
+ return
+ use_power(100)
+
+ var/movedir = dir // base movement dir
+ if(divert && dir==divdir) // update if diverter present
+ movedir = divert
+
+
+ affecting = loc.contents - src // moved items will be all in loc
+ spawn(1) // slight delay to prevent infinite propagation due to map order
+ var/items_moved = 0
+ for(var/atom/movable/A in affecting)
+ if(!A.anchored)
+ if(isturf(A.loc)) // this is to prevent an ugly bug that forces a player to drop what they're holding if they recently pick it up from the conveyer belt
+ if(ismob(A))
+ var/mob/M = A
+ if(M.buckled == src)
+ var/obj/machinery/conveyor/C = locate() in get_step(src, dir)
+ M.buckled = null
+ step(M,dir)
+ if(C)
+ M.buckled = C
+ else
+ new/obj/item/stack/cable_coil/cut(M.loc)
+ else
+ step(M,movedir)
+ else
+ step(A,movedir)
+ items_moved++
+ if(items_moved >= 10)
+ break
+
+// attack with item, place item on conveyor
+
+/obj/machinery/conveyor/attackby(var/obj/item/I, mob/user)
+ if(istype(I, /obj/item/weapon/grab)) // special handling if grabbing a mob
+ var/obj/item/weapon/grab/G = I
+ G.affecting.Move(src.loc)
+ del(G)
+ return
+ else if(istype(I, /obj/item/stack/cable_coil)) // if cable, see if a mob is present
+ var/mob/M = locate() in src.loc
+ if(M)
+ if (M == user)
+ src.visible_message("\blue [M] ties \himself to the conveyor.")
+ // note don't check for lying if self-tying
+ else
+ if(M.lying)
+ user.visible_message("\blue [M] has been tied to the conveyor by [user].", "\blue You tie [M] to the converyor!")
+ else
+ user << "\blue [M] must be lying down to be tied to the converyor!"
+ return
+ M.buckled = src
+ src.add_fingerprint(user)
+ I:use(1)
+ M.lying = 1
+ return
+
+ // else if no mob in loc, then allow coil to be placed
+
+ else if(istype(I, /obj/item/weapon/wirecutters))
+ var/mob/M = locate() in src.loc
+ if(M && M.buckled == src)
+ M.buckled = null
+ src.add_fingerprint(user)
+ if (M == user)
+ src.visible_message("\blue [M] cuts \himself free from the conveyor.")
+ else
+ src.visible_message("\blue [M] had been cut free from the conveyor by [user].")
+ return
+
+ if(isrobot(user))
+ return
+
+ // otherwise drop and place on conveyor
+ user.drop_item()
+ if(I && I.loc) I.loc = src.loc
+ return
+
+// attack with hand, move pulled object onto conveyor
+
+/obj/machinery/conveyor/attack_hand(mob/user as mob)
+ user.Move_Pulled(src)
+
+
+// make the conveyor broken
+// also propagate inoperability to any connected conveyor with the same ID
+/obj/machinery/conveyor/proc/broken()
+ stat |= BROKEN
+ update()
+
+ var/obj/machinery/conveyor/C = locate() in get_step(src, basedir)
+ if(C)
+ C.set_operable(basedir, id, 0)
+
+ C = locate() in get_step(src, turn(basedir,180))
+ if(C)
+ C.set_operable(turn(basedir,180), id, 0)
+
+
+//set the operable var if ID matches, propagating in the given direction
+
+/obj/machinery/conveyor/proc/set_operable(stepdir, match_id, op)
+
+ if(id != match_id)
+ return
+ operable = op
+
+ update()
+ var/obj/machinery/conveyor/C = locate() in get_step(src, stepdir)
+ if(C)
+ C.set_operable(stepdir, id, op)
+
+/*
+/obj/machinery/conveyor/verb/destroy()
+ set src in view()
+ src.broken()
+*/
+
+/obj/machinery/conveyor/power_change()
+ ..()
+ update()
+
+
+// converyor diverter
+// extendable arm that can be switched so items on the conveyer are diverted sideways
+// situate in same turf as conveyor
+// only works if belts is running proper direction
+//
+//
+/obj/machinery/diverter
+ icon = 'icons/obj/recycling.dmi'
+ icon_state = "diverter0"
+ name = "diverter"
+ desc = "A diverter arm for a conveyor belt."
+ anchored = 1
+ layer = FLY_LAYER
+ var/obj/machinery/conveyor/conv // the conveyor this diverter works on
+ var/deployed = 0 // true if diverter arm is extended
+ var/operating = 0 // true if arm is extending/contracting
+ var/divert_to // the dir that diverted items will be moved
+ var/divert_from // the dir items must be moving to divert
+
+
+// create a diverter
+// set up divert_to and divert_from directions depending on dir state
+/obj/machinery/diverter/New()
+
+ ..()
+
+ switch(dir)
+ if(NORTH)
+ divert_to = WEST // stuff will be moved to the west
+ divert_from = NORTH // if entering from the north
+ if(SOUTH)
+ divert_to = EAST
+ divert_from = NORTH
+ if(EAST)
+ divert_to = EAST
+ divert_from = SOUTH
+ if(WEST)
+ divert_to = WEST
+ divert_from = SOUTH
+ if(NORTHEAST)
+ divert_to = NORTH
+ divert_from = EAST
+ if(NORTHWEST)
+ divert_to = NORTH
+ divert_from = WEST
+ if(SOUTHEAST)
+ divert_to = SOUTH
+ divert_from = EAST
+ if(SOUTHWEST)
+ divert_to = SOUTH
+ divert_from = WEST
+ spawn(2)
+ // wait for map load then find the conveyor in this turf
+ conv = locate() in src.loc
+ if(conv) // divert_from dir must match possible conveyor movement
+ if(conv.basedir != divert_from && conv.basedir != turn(divert_from,180) )
+ del(src) // if no dir match, then delete self
+ set_divert()
+ update()
+
+// update the icon state depending on whether the diverter is extended
+/obj/machinery/diverter/proc/update()
+ icon_state = "diverter[deployed]"
+
+// call to set the diversion vars of underlying conveyor
+/obj/machinery/diverter/proc/set_divert()
+ if(conv)
+ if(deployed)
+ conv.divert = divert_to
+ conv.divdir = divert_from
+ else
+ conv.divert= 0
+
+
+// *** TESTING click to toggle
+/obj/machinery/diverter/Click()
+ toggle()
+
+
+// toggle between arm deployed and not deployed, showing animation
+//
+/obj/machinery/diverter/proc/toggle()
+ if( stat & (NOPOWER|BROKEN))
+ return
+
+ if(operating)
+ return
+
+ use_power(50)
+ operating = 1
+ if(deployed)
+ flick("diverter10",src)
+ icon_state = "diverter0"
+ sleep(10)
+ deployed = 0
+ else
+ flick("diverter01",src)
+ icon_state = "diverter1"
+ sleep(10)
+ deployed = 1
+ operating = 0
+ update()
+ set_divert()
+
+// don't allow movement into the 'backwards' direction if deployed
+/obj/machinery/diverter/CanPass(atom/movable/O, var/turf/target)
+ var/direct = get_dir(O, target)
+ if(direct == divert_to) // prevent movement through body of diverter
+ return 0
+ if(!deployed)
+ return 1
+ return(direct != turn(divert_from,180))
+
+// don't allow movement through the arm if deployed
+/obj/machinery/diverter/CheckExit(atom/movable/O, var/turf/target)
+ var/direct = get_dir(O, target)
+ if(direct == turn(divert_to,180)) // prevent movement through body of diverter
+ return 0
+ if(!deployed)
+ return 1
+ return(direct != divert_from)
+
+
+
+
+
+// the conveyor control switch
+//
+//
+
+/obj/machinery/conveyor_switch
+
+ name = "conveyor switch"
+ desc = "A conveyor control switch."
+ icon = 'icons/obj/recycling.dmi'
+ icon_state = "switch-off"
+ var/position = 0 // 0 off, -1 reverse, 1 forward
+ var/last_pos = -1 // last direction setting
+ var/operated = 1 // true if just operated
+
+ var/id = "" // must match conveyor IDs to control them
+
+ var/list/conveyors // the list of converyors that are controlled by this switch
+ anchored = 1
+
+
+
+/obj/machinery/conveyor_switch/New()
+ ..()
+ update()
+
+ spawn(5) // allow map load
+ conveyors = list()
+ for(var/obj/machinery/conveyor/C in world)
+ if(C.id == id)
+ conveyors += C
+
+// update the icon depending on the position
+
+/obj/machinery/conveyor_switch/proc/update()
+ if(position<0)
+ icon_state = "switch-rev"
+ else if(position>0)
+ icon_state = "switch-fwd"
+ else
+ icon_state = "switch-off"
+
+
+// timed process
+// if the switch changed, update the linked conveyors
+
+/obj/machinery/conveyor_switch/process()
+ if(!operated)
+ return
+ operated = 0
+
+ for(var/obj/machinery/conveyor/C in conveyors)
+ C.operating = position
+ C.setdir()
+
+// attack with hand, switch position
+/obj/machinery/conveyor_switch/attack_hand(mob/user)
+ if(position == 0)
+ if(last_pos < 0)
+ position = 1
+ last_pos = 0
+ else
+ position = -1
+ last_pos = 0
+ else
+ last_pos = position
+ position = 0
+
+ operated = 1
+ update()
+
+ // find any switches with same id as this one, and set their positions to match us
+ for(var/obj/machinery/conveyor_switch/S in world)
+ if(S.id == src.id)
+ S.position = position
+ S.update()
diff --git a/code/unused/hivebot/hive_modules.dm b/code/unused/hivebot/hive_modules.dm
index c0ae3196ca9..abac6236910 100644
--- a/code/unused/hivebot/hive_modules.dm
+++ b/code/unused/hivebot/hive_modules.dm
@@ -1,57 +1,57 @@
-/obj/item/weapon/hive_module
- name = "hive robot module"
- icon = 'icons/obj/module.dmi'
- icon_state = "std_module"
- w_class = 2.0
- item_state = "electronic"
- flags = FPRINT|TABLEPASS | CONDUCT
- var/list/modules = list()
-
-/obj/item/weapon/hive_module/standard
- name = "give standard robot module"
-
-/obj/item/weapon/hive_module/engineering
- name = "HiveBot engineering robot module"
-
-/obj/item/weapon/hive_module/New()//Shit all the mods have
- src.modules += new /obj/item/device/flash(src)
-
-
-/obj/item/weapon/hive_module/standard/New()
- ..()
- src.modules += new /obj/item/weapon/melee/baton(src)
- src.modules += new /obj/item/weapon/extinguisher(src)
- //var/obj/item/weapon/gun/mp5/M = new /obj/item/weapon/gun/mp5(src)
- //M.weapon_lock = 0
- //src.modules += M
-
-
-/obj/item/weapon/hive_module/engineering/New()
-
- src.modules += new /obj/item/weapon/extinguisher(src)
- src.modules += new /obj/item/weapon/screwdriver(src)
- src.modules += new /obj/item/weapon/weldingtool(src)
- src.modules += new /obj/item/weapon/wrench(src)
- src.modules += new /obj/item/device/analyzer(src)
- src.modules += new /obj/item/device/flashlight(src)
-
- var/obj/item/weapon/rcd/R = new /obj/item/weapon/rcd(src)
- R.matter = 30
- src.modules += R
-
- src.modules += new /obj/item/device/t_scanner(src)
- src.modules += new /obj/item/weapon/crowbar(src)
- src.modules += new /obj/item/weapon/wirecutters(src)
- src.modules += new /obj/item/device/multitool(src)
-
- var/obj/item/stack/sheet/metal/M = new /obj/item/stack/sheet/metal(src)
- M.amount = 50
- src.modules += M
-
- var/obj/item/stack/sheet/rglass/G = new /obj/item/stack/sheet/rglass(src)
- G.amount = 50
- src.modules += G
-
- var/obj/item/stack/cable_coil/W = new /obj/item/stack/cable_coil(src)
- W.amount = 50
- src.modules += W
+/obj/item/weapon/hive_module
+ name = "hive robot module"
+ icon = 'icons/obj/module.dmi'
+ icon_state = "std_module"
+ w_class = 2.0
+ item_state = "electronic"
+ flags = FPRINT|TABLEPASS | CONDUCT
+ var/list/modules = list()
+
+/obj/item/weapon/hive_module/standard
+ name = "give standard robot module"
+
+/obj/item/weapon/hive_module/engineering
+ name = "HiveBot engineering robot module"
+
+/obj/item/weapon/hive_module/New()//Shit all the mods have
+ src.modules += new /obj/item/device/flash(src)
+
+
+/obj/item/weapon/hive_module/standard/New()
+ ..()
+ src.modules += new /obj/item/weapon/melee/baton(src)
+ src.modules += new /obj/item/weapon/extinguisher(src)
+ //var/obj/item/weapon/gun/mp5/M = new /obj/item/weapon/gun/mp5(src)
+ //M.weapon_lock = 0
+ //src.modules += M
+
+
+/obj/item/weapon/hive_module/engineering/New()
+
+ src.modules += new /obj/item/weapon/extinguisher(src)
+ src.modules += new /obj/item/weapon/screwdriver(src)
+ src.modules += new /obj/item/weapon/weldingtool(src)
+ src.modules += new /obj/item/weapon/wrench(src)
+ src.modules += new /obj/item/device/analyzer(src)
+ src.modules += new /obj/item/device/flashlight(src)
+
+ var/obj/item/weapon/rcd/R = new /obj/item/weapon/rcd(src)
+ R.matter = 30
+ src.modules += R
+
+ src.modules += new /obj/item/device/t_scanner(src)
+ src.modules += new /obj/item/weapon/crowbar(src)
+ src.modules += new /obj/item/weapon/wirecutters(src)
+ src.modules += new /obj/item/device/multitool(src)
+
+ var/obj/item/stack/sheet/metal/M = new /obj/item/stack/sheet/metal(src)
+ M.amount = 50
+ src.modules += M
+
+ var/obj/item/stack/sheet/rglass/G = new /obj/item/stack/sheet/rglass(src)
+ G.amount = 50
+ src.modules += G
+
+ var/obj/item/stack/cable_coil/W = new /obj/item/stack/cable_coil(src)
+ W.amount = 50
+ src.modules += W
diff --git a/code/unused/pipe_filter.dm b/code/unused/pipe_filter.dm
index 10f0673728a..f12b36be467 100644
--- a/code/unused/pipe_filter.dm
+++ b/code/unused/pipe_filter.dm
@@ -1,243 +1,243 @@
-// *** pipefilter
-
-/obj/machinery/pipefilter/New()
- ..()
- p_dir = (NORTH|SOUTH|EAST|WEST) ^ turn(dir, 180)
-
- src.gas = new /datum/gas_mixture/()
- src.ngas = new /datum/gas_mixture/()
-
- src.f_gas = new /datum/gas_mixture/()
- src.f_ngas = new /datum/gas_mixture/()
-
- gasflowlist += src
-
-/obj/machinery/pipefilter/buildnodes()
- var/turf/T = src.loc
-
- n1dir = turn(dir, 90)
- n2dir = turn(dir,-90)
-
- node1 = get_machine( level, T , n1dir ) // the main flow dir
- node2 = get_machine( level, T , n2dir )
- node3 = get_machine( level, T, dir ) // the ejector port
-
- if(node1) vnode1 = node1.getline()
- if(node2) vnode2 = node2.getline()
- if(node3) vnode3 = node3.getline()
-
-/obj/machinery/pipefilter/gas_flow()
- gas.copy_from(ngas)
- f_gas.copy_from(f_ngas)
-
-/obj/machinery/pipefilter/process()
-/* var/delta_gt
-
- if(vnode1)
- delta_gt = FLOWFRAC * ( vnode1.get_gas_val(src) - gas.total_moles() / capmult)
- calc_delta( src, gas, ngas, vnode1, delta_gt)
- else
- leak_to_turf(1)
- if(vnode2)
- delta_gt = FLOWFRAC * ( vnode2.get_gas_val(src) - gas.total_moles() / capmult)
- calc_delta( src, gas, ngas, vnode2, delta_gt)
- else
- leak_to_turf(2)
- if(vnode3)
- delta_gt = FLOWFRAC * ( vnode3.get_gas_val(src) - f_gas.total_moles() / capmult)
- calc_delta( src, f_gas, f_ngas, vnode3, delta_gt)
- else
- leak_to_turf(3)
-
- // transfer gas from ngas->f_ngas according to extraction rate, but only if we have power
- if(! (stat & NOPOWER) )
- use_power(min(src.f_per, 100),ENVIRON)
- var/datum/gas_mixture/ndelta = src.get_extract()
- ngas.sub_delta(ndelta)
- f_ngas.add_delta(ndelta)
- AutoUpdateAI(src)
- src.updateUsrDialog()*/ //TODO: FIX
-
-/obj/machinery/pipefilter/get_gas_val(from)
- return ((from == vnode3) ? f_gas.total_moles() : gas.total_moles())/capmult
-
-/obj/machinery/pipefilter/get_gas(from)
- return (from == vnode3) ? f_gas : gas
-
-/obj/machinery/pipefilter/proc/leak_to_turf(var/port)
- var/turf/T
-
- switch(port)
- if(1)
- T = get_step(src, n1dir)
- if(2)
- T = get_step(src, n2dir)
- if(3)
- T = get_step(src, dir)
- if(T.density)
- T = src.loc
- if(T.density)
- return
- flow_to_turf(f_gas, f_ngas, T)
- return
-
- if(T.density)
- T = src.loc
- if(T.density)
- return
-
- flow_to_turf(gas, ngas, T)
-
-/obj/machinery/pipefilter/proc/get_extract()
- /*
- var/datum/gas_mixture/ndelta = new()
- if (src.f_mask & GAS_O2)
- ndelta.oxygen = min(src.f_per, src.ngas.oxygen)
- if (src.f_mask & GAS_N2)
- ndelta.n2 = min(src.f_per, src.ngas.n2)
- if (src.f_mask & GAS_PL)
- ndelta.plasma = min(src.f_per, src.ngas.plasma)
- if (src.f_mask & GAS_CO2)
- ndelta.co2 = min(src.f_per, src.ngas.co2)
- if (src.f_mask & GAS_N2O)
- ndelta.sl_gas = min(src.f_per, src.ngas.sl_gas)
- return ndelta
- */ //TODO: FIX
-
-/obj/machinery/pipefilter/attackby(obj/item/weapon/W, mob/user as mob)
- if(istype(W, /obj/item/weapon/detective_scanner))
- return ..()
- if(istype(W, /obj/item/weapon/screwdriver))
- if(bypassed)
- user.show_message(text("\red Remove the foreign wires first!"), 1)
- return
- src.add_fingerprint(user)
- user.show_message(text("\red Now []securing the access system panel...", (src.locked) ? "un" : "re"), 1)
- sleep(30)
- locked =! locked
- user.show_message(text("\red Done!"),1)
- src.updateicon()
- return
- if(istype(W, /obj/item/stack/cable_coil) && !bypassed)
- if(src.locked)
- user.show_message(text("\red You must remove the panel first!"),1)
- return
- var/obj/item/stack/cable_coil/C = W
- if(C.use(4))
- user.show_message(text("\red You unravel some cable.."),1)
- else
- user.show_message(text("\red Not enough cable! (Requires four pieces)"),1)
- src.add_fingerprint(user)
- user.show_message(text("\red Now bypassing the access system... (This may take a while)"), 1)
- sleep(100)
- bypassed = 1
- src.updateicon()
- return
- if(istype(W, /obj/item/weapon/wirecutters) && bypassed)
- src.add_fingerprint(user)
- user.show_message(text("\red Now removing the bypass wires... (This may take a while)"), 1)
- sleep(50)
- bypassed = 0
- src.updateicon()
- return
- if(istype(W, /obj/item/weapon/card/emag) && (!emagged))
- emagged++
- src.add_fingerprint(user)
- for(var/mob/O in viewers(user, null))
- O.show_message(text("\red [] has shorted out the [] with an electromagnetic card!", user, src), 1)
- src.overlays += image('icons/obj/pipes2.dmi', "filter-spark")
- sleep(6)
- src.updateicon()
- return src.attack_hand(user)
- return src.attack_hand(user)
-
-// pipefilter interact/topic
-/obj/machinery/pipefilter/attack_paw(mob/user as mob)
- return src.attack_hand(user)
-
-/obj/machinery/pipefilter/attack_ai(mob/user as mob)
- return src.attack_hand(user)
-
-/obj/machinery/pipefilter/attack_hand(mob/user as mob)
-/* if(stat & NOPOWER)
- user << browse(null, "window=pipefilter")
- user.machine = null
- return
-
- var/list/gases = list("O2", "N2", "Plasma", "CO2", "N2O")
- user.machine = src
- var/dat = "Filter Release Rate:
\nM - - - - - [src.f_per] + + + + + M
\n"
- for (var/i = 1; i <= gases.len; i++)
- dat += "[gases[i]]: [(src.f_mask & 1 << (i - 1)) ? "Releasing" : "Passing"]
\n"
- if(gas.total_moles())
- var/totalgas = gas.total_moles()
- var/pressure = round(totalgas / gas.maximum * 100)
- var/nitrogen = gas.n2 / totalgas * 100
- var/oxygen = gas.oxygen / totalgas * 100
- var/plasma = gas.plasma / totalgas * 100
- var/co2 = gas.co2 / totalgas * 100
- var/no2 = gas.sl_gas / totalgas * 100
-
- dat += "
Gas Levels:
\nPressure: [pressure]%
\nNitrogen: [nitrogen]%
\nOxygen: [oxygen]%
\nPlasma: [plasma]%
\nCO2: [co2]%
\nN2O: [no2]%
\n"
- else
- dat += "
Gas Levels:
\nPressure: 0%
\nNitrogen: 0%
\nOxygen: 0%
\nPlasma: 0%
\nCO2: 0%
\nN2O: 0%
\n"
- dat += "
\nClose
\n"
-
- user << browse(dat, "window=pipefilter;size=300x365")*/ //TODO: FIX
- //onclose(user, "pipefilter")
-
-/obj/machinery/pipefilter/Topic(href, href_list)
- ..()
- if(usr.restrained() || usr.lying)
- return
- if ((((get_dist(src, usr) <= 1 || usr.telekinesis == 1) || istype(usr, /mob/living/silicon/ai)) && istype(src.loc, /turf)))
- usr.machine = src
- if (href_list["close"])
- usr << browse(null, "window=pipefilter;")
- usr.machine = null
- return
- if (src.allowed(usr) || src.emagged || src.bypassed)
- if (href_list["fp"])
- src.f_per = min(max(round(src.f_per + text2num(href_list["fp"])), 0), src.maxrate)
- else if (href_list["tg"])
- // toggle gas
- src.f_mask ^= text2num(href_list["tg"])
- src.updateicon()
- else
- usr.see("\red Access Denied ([src.name] operation restricted to authorized atmospheric technicians.)")
- AutoUpdateAI(src)
- src.updateUsrDialog()
- src.add_fingerprint(usr)
- else
- usr << browse(null, "window=pipefilter")
- usr.machine = null
- return
-
-/obj/machinery/pipefilter/power_change()
- if(powered(ENVIRON))
- stat &= ~NOPOWER
- else
- stat |= NOPOWER
- spawn(rand(1,15)) //so all the filters don't come on at once
- updateicon()
-
-/obj/machinery/pipefilter/proc/updateicon()
- src.overlays.Cut()
- if(stat & NOPOWER)
- icon_state = "filter-off"
- else
- icon_state = "filter"
- if(emagged) //only show if powered because presumeably its the interface that has been fried
- src.overlays += image('icons/obj/pipes2.dmi', "filter-emag")
- if (src.f_mask & (GAS_N2O|GAS_PL))
- src.overlays += image('icons/obj/pipes2.dmi', "filter-tox")
- if (src.f_mask & GAS_O2)
- src.overlays += image('icons/obj/pipes2.dmi', "filter-o2")
- if (src.f_mask & GAS_N2)
- src.overlays += image('icons/obj/pipes2.dmi', "filter-n2")
- if (src.f_mask & GAS_CO2)
- src.overlays += image('icons/obj/pipes2.dmi', "filter-co2")
- if(!locked)
- src.overlays += image('icons/obj/pipes2.dmi', "filter-open")
- if(bypassed) //should only be bypassed if unlocked
+// *** pipefilter
+
+/obj/machinery/pipefilter/New()
+ ..()
+ p_dir = (NORTH|SOUTH|EAST|WEST) ^ turn(dir, 180)
+
+ src.gas = new /datum/gas_mixture/()
+ src.ngas = new /datum/gas_mixture/()
+
+ src.f_gas = new /datum/gas_mixture/()
+ src.f_ngas = new /datum/gas_mixture/()
+
+ gasflowlist += src
+
+/obj/machinery/pipefilter/buildnodes()
+ var/turf/T = src.loc
+
+ n1dir = turn(dir, 90)
+ n2dir = turn(dir,-90)
+
+ node1 = get_machine( level, T , n1dir ) // the main flow dir
+ node2 = get_machine( level, T , n2dir )
+ node3 = get_machine( level, T, dir ) // the ejector port
+
+ if(node1) vnode1 = node1.getline()
+ if(node2) vnode2 = node2.getline()
+ if(node3) vnode3 = node3.getline()
+
+/obj/machinery/pipefilter/gas_flow()
+ gas.copy_from(ngas)
+ f_gas.copy_from(f_ngas)
+
+/obj/machinery/pipefilter/process()
+/* var/delta_gt
+
+ if(vnode1)
+ delta_gt = FLOWFRAC * ( vnode1.get_gas_val(src) - gas.total_moles() / capmult)
+ calc_delta( src, gas, ngas, vnode1, delta_gt)
+ else
+ leak_to_turf(1)
+ if(vnode2)
+ delta_gt = FLOWFRAC * ( vnode2.get_gas_val(src) - gas.total_moles() / capmult)
+ calc_delta( src, gas, ngas, vnode2, delta_gt)
+ else
+ leak_to_turf(2)
+ if(vnode3)
+ delta_gt = FLOWFRAC * ( vnode3.get_gas_val(src) - f_gas.total_moles() / capmult)
+ calc_delta( src, f_gas, f_ngas, vnode3, delta_gt)
+ else
+ leak_to_turf(3)
+
+ // transfer gas from ngas->f_ngas according to extraction rate, but only if we have power
+ if(! (stat & NOPOWER) )
+ use_power(min(src.f_per, 100),ENVIRON)
+ var/datum/gas_mixture/ndelta = src.get_extract()
+ ngas.sub_delta(ndelta)
+ f_ngas.add_delta(ndelta)
+ AutoUpdateAI(src)
+ src.updateUsrDialog()*/ //TODO: FIX
+
+/obj/machinery/pipefilter/get_gas_val(from)
+ return ((from == vnode3) ? f_gas.total_moles() : gas.total_moles())/capmult
+
+/obj/machinery/pipefilter/get_gas(from)
+ return (from == vnode3) ? f_gas : gas
+
+/obj/machinery/pipefilter/proc/leak_to_turf(var/port)
+ var/turf/T
+
+ switch(port)
+ if(1)
+ T = get_step(src, n1dir)
+ if(2)
+ T = get_step(src, n2dir)
+ if(3)
+ T = get_step(src, dir)
+ if(T.density)
+ T = src.loc
+ if(T.density)
+ return
+ flow_to_turf(f_gas, f_ngas, T)
+ return
+
+ if(T.density)
+ T = src.loc
+ if(T.density)
+ return
+
+ flow_to_turf(gas, ngas, T)
+
+/obj/machinery/pipefilter/proc/get_extract()
+ /*
+ var/datum/gas_mixture/ndelta = new()
+ if (src.f_mask & GAS_O2)
+ ndelta.oxygen = min(src.f_per, src.ngas.oxygen)
+ if (src.f_mask & GAS_N2)
+ ndelta.n2 = min(src.f_per, src.ngas.n2)
+ if (src.f_mask & GAS_PL)
+ ndelta.plasma = min(src.f_per, src.ngas.plasma)
+ if (src.f_mask & GAS_CO2)
+ ndelta.co2 = min(src.f_per, src.ngas.co2)
+ if (src.f_mask & GAS_N2O)
+ ndelta.sl_gas = min(src.f_per, src.ngas.sl_gas)
+ return ndelta
+ */ //TODO: FIX
+
+/obj/machinery/pipefilter/attackby(obj/item/weapon/W, mob/user as mob)
+ if(istype(W, /obj/item/weapon/detective_scanner))
+ return ..()
+ if(istype(W, /obj/item/weapon/screwdriver))
+ if(bypassed)
+ user.show_message(text("\red Remove the foreign wires first!"), 1)
+ return
+ src.add_fingerprint(user)
+ user.show_message(text("\red Now []securing the access system panel...", (src.locked) ? "un" : "re"), 1)
+ sleep(30)
+ locked =! locked
+ user.show_message(text("\red Done!"),1)
+ src.updateicon()
+ return
+ if(istype(W, /obj/item/stack/cable_coil) && !bypassed)
+ if(src.locked)
+ user.show_message(text("\red You must remove the panel first!"),1)
+ return
+ var/obj/item/stack/cable_coil/C = W
+ if(C.use(4))
+ user.show_message(text("\red You unravel some cable.."),1)
+ else
+ user.show_message(text("\red Not enough cable! (Requires four pieces)"),1)
+ src.add_fingerprint(user)
+ user.show_message(text("\red Now bypassing the access system... (This may take a while)"), 1)
+ sleep(100)
+ bypassed = 1
+ src.updateicon()
+ return
+ if(istype(W, /obj/item/weapon/wirecutters) && bypassed)
+ src.add_fingerprint(user)
+ user.show_message(text("\red Now removing the bypass wires... (This may take a while)"), 1)
+ sleep(50)
+ bypassed = 0
+ src.updateicon()
+ return
+ if(istype(W, /obj/item/weapon/card/emag) && (!emagged))
+ emagged++
+ src.add_fingerprint(user)
+ for(var/mob/O in viewers(user, null))
+ O.show_message(text("\red [] has shorted out the [] with an electromagnetic card!", user, src), 1)
+ src.overlays += image('icons/obj/pipes2.dmi', "filter-spark")
+ sleep(6)
+ src.updateicon()
+ return src.attack_hand(user)
+ return src.attack_hand(user)
+
+// pipefilter interact/topic
+/obj/machinery/pipefilter/attack_paw(mob/user as mob)
+ return src.attack_hand(user)
+
+/obj/machinery/pipefilter/attack_ai(mob/user as mob)
+ return src.attack_hand(user)
+
+/obj/machinery/pipefilter/attack_hand(mob/user as mob)
+/* if(stat & NOPOWER)
+ user << browse(null, "window=pipefilter")
+ user.machine = null
+ return
+
+ var/list/gases = list("O2", "N2", "Plasma", "CO2", "N2O")
+ user.machine = src
+ var/dat = "Filter Release Rate:
\nM - - - - - [src.f_per] + + + + + M
\n"
+ for (var/i = 1; i <= gases.len; i++)
+ dat += "[gases[i]]: [(src.f_mask & 1 << (i - 1)) ? "Releasing" : "Passing"]
\n"
+ if(gas.total_moles())
+ var/totalgas = gas.total_moles()
+ var/pressure = round(totalgas / gas.maximum * 100)
+ var/nitrogen = gas.n2 / totalgas * 100
+ var/oxygen = gas.oxygen / totalgas * 100
+ var/plasma = gas.plasma / totalgas * 100
+ var/co2 = gas.co2 / totalgas * 100
+ var/no2 = gas.sl_gas / totalgas * 100
+
+ dat += "
Gas Levels:
\nPressure: [pressure]%
\nNitrogen: [nitrogen]%
\nOxygen: [oxygen]%
\nPlasma: [plasma]%
\nCO2: [co2]%
\nN2O: [no2]%
\n"
+ else
+ dat += "
Gas Levels:
\nPressure: 0%
\nNitrogen: 0%
\nOxygen: 0%
\nPlasma: 0%
\nCO2: 0%
\nN2O: 0%
\n"
+ dat += "
\nClose
\n"
+
+ user << browse(dat, "window=pipefilter;size=300x365")*/ //TODO: FIX
+ //onclose(user, "pipefilter")
+
+/obj/machinery/pipefilter/Topic(href, href_list)
+ ..()
+ if(usr.restrained() || usr.lying)
+ return
+ if ((((get_dist(src, usr) <= 1 || usr.telekinesis == 1) || istype(usr, /mob/living/silicon/ai)) && istype(src.loc, /turf)))
+ usr.machine = src
+ if (href_list["close"])
+ usr << browse(null, "window=pipefilter;")
+ usr.machine = null
+ return
+ if (src.allowed(usr) || src.emagged || src.bypassed)
+ if (href_list["fp"])
+ src.f_per = min(max(round(src.f_per + text2num(href_list["fp"])), 0), src.maxrate)
+ else if (href_list["tg"])
+ // toggle gas
+ src.f_mask ^= text2num(href_list["tg"])
+ src.updateicon()
+ else
+ usr.see("\red Access Denied ([src.name] operation restricted to authorized atmospheric technicians.)")
+ AutoUpdateAI(src)
+ src.updateUsrDialog()
+ src.add_fingerprint(usr)
+ else
+ usr << browse(null, "window=pipefilter")
+ usr.machine = null
+ return
+
+/obj/machinery/pipefilter/power_change()
+ if(powered(ENVIRON))
+ stat &= ~NOPOWER
+ else
+ stat |= NOPOWER
+ spawn(rand(1,15)) //so all the filters don't come on at once
+ updateicon()
+
+/obj/machinery/pipefilter/proc/updateicon()
+ src.overlays.Cut()
+ if(stat & NOPOWER)
+ icon_state = "filter-off"
+ else
+ icon_state = "filter"
+ if(emagged) //only show if powered because presumeably its the interface that has been fried
+ src.overlays += image('icons/obj/pipes2.dmi', "filter-emag")
+ if (src.f_mask & (GAS_N2O|GAS_PL))
+ src.overlays += image('icons/obj/pipes2.dmi', "filter-tox")
+ if (src.f_mask & GAS_O2)
+ src.overlays += image('icons/obj/pipes2.dmi', "filter-o2")
+ if (src.f_mask & GAS_N2)
+ src.overlays += image('icons/obj/pipes2.dmi', "filter-n2")
+ if (src.f_mask & GAS_CO2)
+ src.overlays += image('icons/obj/pipes2.dmi', "filter-co2")
+ if(!locked)
+ src.overlays += image('icons/obj/pipes2.dmi', "filter-open")
+ if(bypassed) //should only be bypassed if unlocked
src.overlays += image('icons/obj/pipes2.dmi', "filter-bypass")
\ No newline at end of file
diff --git a/config/admins.txt b/config/admins.txt
index 68dfd02bd71..c8846e169f8 100644
--- a/config/admins.txt
+++ b/config/admins.txt
@@ -1,57 +1,57 @@
-###############################################################################################
-# Basically, ckey goes first. Rank goes after the "=" #
-# Case is not important for ckey. #
-# Case IS important for the rank. #
-# All punctuation (spaces etc) EXCEPT '-', '_' and '@' will be stripped from rank names. #
-# Ranks can be anything defined in admin_ranks.txt #
-# NOTE: if the rank-name cannot be found in admin_ranks.txt, they will not be adminned! ~Carn #
-# NOTE: syntax was changed to allow hyphenation of ranknames, since spaces are stripped. #
-###############################################################################################
-razharas = Game Master
-rolan7 = Game Master
-quarxink = Game Master
-adrix89 = Game Master
-tle = Game Master
-xsi = Game Master
-scaredofshadows = Game Master
-neofite = Game Master
-trubblebass = Game Master
-mport2004 = Game Master
-deuryn = Game Master
-agouri = Game Master
-errorage = Game Master
-superxpdude = Game Master
-petethegoat = Game Master
-korphaeron = Game Master
-nodrak = Game Master
-carnwennan = Game Master
-ikarrus = Game Master
-cheridan = Game Master
-giacomand = Game Master
-rockdtben = Game Master
-sieve = Game Master
-aranclanos = Game Master
-intigracy = Game Master
-dumpdavidson = Game Master
-kazeespada = Game Master
-malkevin = Game Master
-incoming = Game Master
-demas = Game Master
-fleure = Game Master
-ricotez = Game Master
-misterperson = Game Master
-crimsonvision = Game Master
-iamgoofball = Game Master
-zelacks = Game Master
-androidsfv = Game Master
-miggles = Game Master
-jordie0608 = Game Master
-s0ldi3rkr4s0 = Game Master
-ergovisavi = Game Master
-vistapowa = Game Master
-miauw62 = Game Master
-kazeespada = Game Master
-rumia29 = Game Master
-bobylein = Game Master
-sirbayer = Game Master
+###############################################################################################
+# Basically, ckey goes first. Rank goes after the "=" #
+# Case is not important for ckey. #
+# Case IS important for the rank. #
+# All punctuation (spaces etc) EXCEPT '-', '_' and '@' will be stripped from rank names. #
+# Ranks can be anything defined in admin_ranks.txt #
+# NOTE: if the rank-name cannot be found in admin_ranks.txt, they will not be adminned! ~Carn #
+# NOTE: syntax was changed to allow hyphenation of ranknames, since spaces are stripped. #
+###############################################################################################
+razharas = Game Master
+rolan7 = Game Master
+quarxink = Game Master
+adrix89 = Game Master
+tle = Game Master
+xsi = Game Master
+scaredofshadows = Game Master
+neofite = Game Master
+trubblebass = Game Master
+mport2004 = Game Master
+deuryn = Game Master
+agouri = Game Master
+errorage = Game Master
+superxpdude = Game Master
+petethegoat = Game Master
+korphaeron = Game Master
+nodrak = Game Master
+carnwennan = Game Master
+ikarrus = Game Master
+cheridan = Game Master
+giacomand = Game Master
+rockdtben = Game Master
+sieve = Game Master
+aranclanos = Game Master
+intigracy = Game Master
+dumpdavidson = Game Master
+kazeespada = Game Master
+malkevin = Game Master
+incoming = Game Master
+demas = Game Master
+fleure = Game Master
+ricotez = Game Master
+misterperson = Game Master
+crimsonvision = Game Master
+iamgoofball = Game Master
+zelacks = Game Master
+androidsfv = Game Master
+miggles = Game Master
+jordie0608 = Game Master
+s0ldi3rkr4s0 = Game Master
+ergovisavi = Game Master
+vistapowa = Game Master
+miauw62 = Game Master
+kazeespada = Game Master
+rumia29 = Game Master
+bobylein = Game Master
+sirbayer = Game Master
hornygranny = Game Master
diff --git a/html/changelog.html b/html/changelog.html
index efadaca5384..fe030564f28 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -52,7 +52,7 @@ should be listed in the changelog upon commit tho. Thanks. -->
-
+
3 February 2014
@@ -266,7 +266,7 @@ should be listed in the changelog upon commit tho. Thanks. -->
- A new training bomb has been added to the armoury, which will allow you to train your wire cutting skills to disarm real syndicate bombs.
-
+
12 January 2014
diff --git a/tgstation.dme b/tgstation.dme
index e187962032a..80be6634b91 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1,1216 +1,1216 @@
-// DM Environment file for tgstation.dme.
-// All manual changes should be made outside the BEGIN_ and END_ blocks.
- // New source code should be placed in .dm files: choose File/New --> Code File.
-// BEGIN_INTERNALS
-// END_INTERNALS
-
-// BEGIN_FILE_DIR
-#define FILE_DIR .
-// END_FILE_DIR
-
-// BEGIN_PREFERENCES
-#define DEBUG
-// END_PREFERENCES
-
-// BEGIN_INCLUDE
-#include "_maps\tgstation2.dm"
-#include "code\_compile_options.dm"
-#include "code\hub.dm"
-#include "code\world.dm"
-#include "code\__DEFINES\admin.dm"
-#include "code\__DEFINES\atmospherics.dm"
-#include "code\__DEFINES\clothing.dm"
-#include "code\__DEFINES\combat.dm"
-#include "code\__DEFINES\flags.dm"
-#include "code\__DEFINES\genetics.dm"
-#include "code\__DEFINES\machines.dm"
-#include "code\__DEFINES\math.dm"
-#include "code\__DEFINES\misc.dm"
-#include "code\__DEFINES\preferences.dm"
-#include "code\__DEFINES\sight.dm"
-#include "code\__DEFINES\stat.dm"
-#include "code\__HELPERS\files.dm"
-#include "code\__HELPERS\game.dm"
-#include "code\__HELPERS\global_lists.dm"
-#include "code\__HELPERS\icons.dm"
-#include "code\__HELPERS\lists.dm"
-#include "code\__HELPERS\logging.dm"
-#include "code\__HELPERS\maths.dm"
-#include "code\__HELPERS\matrices.dm"
-#include "code\__HELPERS\mobs.dm"
-#include "code\__HELPERS\names.dm"
-#include "code\__HELPERS\sanitize_values.dm"
-#include "code\__HELPERS\text.dm"
-#include "code\__HELPERS\time.dm"
-#include "code\__HELPERS\type2type.dm"
-#include "code\__HELPERS\unsorted.dm"
-#include "code\_globalvars\configuration.dm"
-#include "code\_globalvars\database.dm"
-#include "code\_globalvars\game_modes.dm"
-#include "code\_globalvars\genetics.dm"
-#include "code\_globalvars\logging.dm"
-#include "code\_globalvars\misc.dm"
-#include "code\_globalvars\station.dm"
-#include "code\_globalvars\unused.dm"
-#include "code\_globalvars\lists\flavor_misc.dm"
-#include "code\_globalvars\lists\mapping.dm"
-#include "code\_globalvars\lists\mobs.dm"
-#include "code\_globalvars\lists\names.dm"
-#include "code\_globalvars\lists\objects.dm"
-#include "code\_onclick\adjacent.dm"
-#include "code\_onclick\ai.dm"
-#include "code\_onclick\click.dm"
-#include "code\_onclick\cyborg.dm"
-#include "code\_onclick\drag_drop.dm"
-#include "code\_onclick\item_attack.dm"
-#include "code\_onclick\observer.dm"
-#include "code\_onclick\other_mobs.dm"
-#include "code\_onclick\overmind.dm"
-#include "code\_onclick\telekinesis.dm"
-#include "code\_onclick\hud\_defines.dm"
-#include "code\_onclick\hud\alien.dm"
-#include "code\_onclick\hud\alien_larva.dm"
-#include "code\_onclick\hud\hud.dm"
-#include "code\_onclick\hud\human.dm"
-#include "code\_onclick\hud\monkey.dm"
-#include "code\_onclick\hud\other_mobs.dm"
-#include "code\_onclick\hud\robot.dm"
-#include "code\_onclick\hud\screen_objects.dm"
-#include "code\ATMOSPHERICS\atmospherics.dm"
-#include "code\ATMOSPHERICS\datum_pipe_network.dm"
-#include "code\ATMOSPHERICS\datum_pipeline.dm"
-#include "code\ATMOSPHERICS\he_pipes.dm"
-#include "code\ATMOSPHERICS\pipes.dm"
-#include "code\ATMOSPHERICS\components\portables_connector.dm"
-#include "code\ATMOSPHERICS\components\valve.dm"
-#include "code\ATMOSPHERICS\components\binary_devices\binary_atmos_base.dm"
-#include "code\ATMOSPHERICS\components\binary_devices\circulator.dm"
-#include "code\ATMOSPHERICS\components\binary_devices\dp_vent_pump.dm"
-#include "code\ATMOSPHERICS\components\binary_devices\passive_gate.dm"
-#include "code\ATMOSPHERICS\components\binary_devices\pump.dm"
-#include "code\ATMOSPHERICS\components\binary_devices\volume_pump.dm"
-#include "code\ATMOSPHERICS\components\trinary_devices\filter.dm"
-#include "code\ATMOSPHERICS\components\trinary_devices\mixer.dm"
-#include "code\ATMOSPHERICS\components\trinary_devices\trinary_base.dm"
-#include "code\ATMOSPHERICS\components\unary\cold_sink.dm"
-#include "code\ATMOSPHERICS\components\unary\generator_input.dm"
-#include "code\ATMOSPHERICS\components\unary\heat_exchanger.dm"
-#include "code\ATMOSPHERICS\components\unary\heat_source.dm"
-#include "code\ATMOSPHERICS\components\unary\outlet_injector.dm"
-#include "code\ATMOSPHERICS\components\unary\oxygen_generator.dm"
-#include "code\ATMOSPHERICS\components\unary\unary_base.dm"
-#include "code\ATMOSPHERICS\components\unary\vent_pump.dm"
-#include "code\ATMOSPHERICS\components\unary\vent_scrubber.dm"
-#include "code\controllers\_DynamicAreaLighting_TG.dm"
-#include "code\controllers\configuration.dm"
-#include "code\controllers\failsafe.dm"
-#include "code\controllers\lighting_controller.dm"
-#include "code\controllers\master_controller.dm"
-#include "code\controllers\shuttle_controller.dm"
-#include "code\controllers\supply_shuttle.dm"
-#include "code\controllers\verbs.dm"
-#include "code\controllers\voting.dm"
-#include "code\datums\ai_laws.dm"
-#include "code\datums\browser.dm"
-#include "code\datums\computerfiles.dm"
-#include "code\datums\datacore.dm"
-#include "code\datums\datumvars.dm"
-#include "code\datums\disease.dm"
-#include "code\datums\mind.dm"
-#include "code\datums\mixed.dm"
-#include "code\datums\modules.dm"
-#include "code\datums\recipe.dm"
-#include "code\datums\spell.dm"
-#include "code\datums\sun.dm"
-#include "code\datums\supplypacks.dm"
-#include "code\datums\uplink_item.dm"
-#include "code\datums\diseases\appendicitis.dm"
-#include "code\datums\diseases\beesease.dm"
-#include "code\datums\diseases\brainrot.dm"
-#include "code\datums\diseases\cold.dm"
-#include "code\datums\diseases\cold9.dm"
-#include "code\datums\diseases\dna_spread.dm"
-#include "code\datums\diseases\fake_gbs.dm"
-#include "code\datums\diseases\flu.dm"
-#include "code\datums\diseases\fluspanish.dm"
-#include "code\datums\diseases\gbs.dm"
-#include "code\datums\diseases\jungle_fever.dm"
-#include "code\datums\diseases\magnitis.dm"
-#include "code\datums\diseases\pierrot_throat.dm"
-#include "code\datums\diseases\plasmatoid.dm"
-#include "code\datums\diseases\retrovirus.dm"
-#include "code\datums\diseases\rhumba_beat.dm"
-#include "code\datums\diseases\transformation.dm"
-#include "code\datums\diseases\wizarditis.dm"
-#include "code\datums\diseases\advance\advance.dm"
-#include "code\datums\diseases\advance\presets.dm"
-#include "code\datums\diseases\advance\symptoms\beard.dm"
-#include "code\datums\diseases\advance\symptoms\choking.dm"
-#include "code\datums\diseases\advance\symptoms\confusion.dm"
-#include "code\datums\diseases\advance\symptoms\cough.dm"
-#include "code\datums\diseases\advance\symptoms\damage_converter.dm"
-#include "code\datums\diseases\advance\symptoms\deafness.dm"
-#include "code\datums\diseases\advance\symptoms\dizzy.dm"
-#include "code\datums\diseases\advance\symptoms\fever.dm"
-#include "code\datums\diseases\advance\symptoms\flesh_eating.dm"
-#include "code\datums\diseases\advance\symptoms\hallucigen.dm"
-#include "code\datums\diseases\advance\symptoms\headache.dm"
-#include "code\datums\diseases\advance\symptoms\heal.dm"
-#include "code\datums\diseases\advance\symptoms\itching.dm"
-#include "code\datums\diseases\advance\symptoms\oxygen.dm"
-#include "code\datums\diseases\advance\symptoms\shedding.dm"
-#include "code\datums\diseases\advance\symptoms\shivering.dm"
-#include "code\datums\diseases\advance\symptoms\sneeze.dm"
-#include "code\datums\diseases\advance\symptoms\stimulant.dm"
-#include "code\datums\diseases\advance\symptoms\symptoms.dm"
-#include "code\datums\diseases\advance\symptoms\visionloss.dm"
-#include "code\datums\diseases\advance\symptoms\vitiligo.dm"
-#include "code\datums\diseases\advance\symptoms\voice_change.dm"
-#include "code\datums\diseases\advance\symptoms\vomit.dm"
-#include "code\datums\diseases\advance\symptoms\weight.dm"
-#include "code\datums\diseases\advance\symptoms\youth.dm"
-#include "code\datums\helper_datums\construction_datum.dm"
-#include "code\datums\helper_datums\events.dm"
-#include "code\datums\helper_datums\getrev.dm"
-#include "code\datums\helper_datums\global_iterator.dm"
-#include "code\datums\helper_datums\teleport.dm"
-#include "code\datums\helper_datums\topic_input.dm"
-#include "code\datums\spells\area_teleport.dm"
-#include "code\datums\spells\charge.dm"
-#include "code\datums\spells\conjure.dm"
-#include "code\datums\spells\construct_spells.dm"
-#include "code\datums\spells\dumbfire.dm"
-#include "code\datums\spells\emplosion.dm"
-#include "code\datums\spells\ethereal_jaunt.dm"
-#include "code\datums\spells\explosion.dm"
-#include "code\datums\spells\genetic.dm"
-#include "code\datums\spells\horsemask.dm"
-#include "code\datums\spells\inflict_handler.dm"
-#include "code\datums\spells\knock.dm"
-#include "code\datums\spells\mime.dm"
-#include "code\datums\spells\mind_transfer.dm"
-#include "code\datums\spells\projectile.dm"
-#include "code\datums\spells\trigger.dm"
-#include "code\datums\spells\turf_teleport.dm"
-#include "code\datums\spells\wizard.dm"
-#include "code\datums\wires\airlock.dm"
-#include "code\datums\wires\alarm.dm"
-#include "code\datums\wires\apc.dm"
-#include "code\datums\wires\camera.dm"
-#include "code\datums\wires\explosive.dm"
-#include "code\datums\wires\mulebot.dm"
-#include "code\datums\wires\particle_accelerator.dm"
-#include "code\datums\wires\radio.dm"
-#include "code\datums\wires\robot.dm"
-#include "code\datums\wires\syndicatebomb.dm"
-#include "code\datums\wires\taperecorder.dm"
-#include "code\datums\wires\vending.dm"
-#include "code\datums\wires\wires.dm"
-#include "code\defines\obj.dm"
-#include "code\defines\obj\weapon.dm"
-#include "code\defines\procs\AStar.dm"
-#include "code\defines\procs\captain_announce.dm"
-#include "code\defines\procs\command_alert.dm"
-#include "code\defines\procs\dbcore.dm"
-#include "code\defines\procs\statistics.dm"
-#include "code\FEA\FEA_gas_mixture.dm"
-#include "code\game\asteroid.dm"
-#include "code\game\atoms.dm"
-#include "code\game\atoms_movable.dm"
-#include "code\game\communications.dm"
-#include "code\game\dna.dm"
-#include "code\game\shuttle_engines.dm"
-#include "code\game\skincmd.dm"
-#include "code\game\smoothwall.dm"
-#include "code\game\sound.dm"
-#include "code\game\area\ai_monitored.dm"
-#include "code\game\area\areas.dm"
-#include "code\game\area\Space Station 13 areas.dm"
-#include "code\game\gamemodes\antag_spawner.dm"
-#include "code\game\gamemodes\events.dm"
-#include "code\game\gamemodes\factions.dm"
-#include "code\game\gamemodes\game_mode.dm"
-#include "code\game\gamemodes\gameticker.dm"
-#include "code\game\gamemodes\intercept_report.dm"
-#include "code\game\gamemodes\objective.dm"
-#include "code\game\gamemodes\objective_items.dm"
-#include "code\game\gamemodes\setupgame.dm"
-#include "code\game\gamemodes\blob\blob.dm"
-#include "code\game\gamemodes\blob\blob_finish.dm"
-#include "code\game\gamemodes\blob\blob_report.dm"
-#include "code\game\gamemodes\blob\overmind.dm"
-#include "code\game\gamemodes\blob\powers.dm"
-#include "code\game\gamemodes\blob\theblob.dm"
-#include "code\game\gamemodes\blob\blobs\core.dm"
-#include "code\game\gamemodes\blob\blobs\factory.dm"
-#include "code\game\gamemodes\blob\blobs\node.dm"
-#include "code\game\gamemodes\blob\blobs\resource.dm"
-#include "code\game\gamemodes\blob\blobs\shield.dm"
-#include "code\game\gamemodes\changeling\changeling.dm"
-#include "code\game\gamemodes\changeling\changeling_mutations.dm"
-#include "code\game\gamemodes\changeling\changeling_powers.dm"
-#include "code\game\gamemodes\changeling\modularchangling.dm"
-#include "code\game\gamemodes\changeling\traitor_chan.dm"
-#include "code\game\gamemodes\cult\cult.dm"
-#include "code\game\gamemodes\cult\cult_items.dm"
-#include "code\game\gamemodes\cult\cult_structures.dm"
-#include "code\game\gamemodes\cult\ritual.dm"
-#include "code\game\gamemodes\cult\runes.dm"
-#include "code\game\gamemodes\cult\talisman.dm"
-#include "code\game\gamemodes\extended\extended.dm"
-#include "code\game\gamemodes\malfunction\Malf_Modules.dm"
-#include "code\game\gamemodes\malfunction\malfunction.dm"
-#include "code\game\gamemodes\meteor\meteor.dm"
-#include "code\game\gamemodes\meteor\meteors.dm"
-#include "code\game\gamemodes\nuclear\nuclear.dm"
-#include "code\game\gamemodes\nuclear\nuclearbomb.dm"
-#include "code\game\gamemodes\nuclear\pinpointer.dm"
-#include "code\game\gamemodes\revolution\revolution.dm"
-#include "code\game\gamemodes\sandbox\airlock_maker.dm"
-#include "code\game\gamemodes\sandbox\h_sandbox.dm"
-#include "code\game\gamemodes\sandbox\sandbox.dm"
-#include "code\game\gamemodes\traitor\double_agents.dm"
-#include "code\game\gamemodes\traitor\traitor.dm"
-#include "code\game\gamemodes\wizard\artefact.dm"
-#include "code\game\gamemodes\wizard\rightandwrong.dm"
-#include "code\game\gamemodes\wizard\soulstone.dm"
-#include "code\game\gamemodes\wizard\spellbook.dm"
-#include "code\game\gamemodes\wizard\wizard.dm"
-#include "code\game\jobs\access.dm"
-#include "code\game\jobs\job_controller.dm"
-#include "code\game\jobs\jobprocs.dm"
-#include "code\game\jobs\jobs.dm"
-#include "code\game\jobs\whitelist.dm"
-#include "code\game\jobs\job\assistant.dm"
-#include "code\game\jobs\job\captain.dm"
-#include "code\game\jobs\job\civilian.dm"
-#include "code\game\jobs\job\civilian_chaplain.dm"
-#include "code\game\jobs\job\engineering.dm"
-#include "code\game\jobs\job\job.dm"
-#include "code\game\jobs\job\medical.dm"
-#include "code\game\jobs\job\science.dm"
-#include "code\game\jobs\job\security.dm"
-#include "code\game\jobs\job\silicon.dm"
-#include "code\game\machinery\ai_slipper.dm"
-#include "code\game\machinery\airlock_control.dm"
-#include "code\game\machinery\alarm.dm"
-#include "code\game\machinery\atmo_control.dm"
-#include "code\game\machinery\autolathe.dm"
-#include "code\game\machinery\Beacon.dm"
-#include "code\game\machinery\buttons.dm"
-#include "code\game\machinery\cell_charger.dm"
-#include "code\game\machinery\cloning.dm"
-#include "code\game\machinery\constructable_frame.dm"
-#include "code\game\machinery\cryo.dm"
-#include "code\game\machinery\deployable.dm"
-#include "code\game\machinery\door_control.dm"
-#include "code\game\machinery\doppler_array.dm"
-#include "code\game\machinery\drying_rack.dm"
-#include "code\game\machinery\flasher.dm"
-#include "code\game\machinery\Freezer.dm"
-#include "code\game\machinery\hologram.dm"
-#include "code\game\machinery\igniter.dm"
-#include "code\game\machinery\lightswitch.dm"
-#include "code\game\machinery\machinery.dm"
-#include "code\game\machinery\magnet.dm"
-#include "code\game\machinery\mass_driver.dm"
-#include "code\game\machinery\navbeacon.dm"
-#include "code\game\machinery\newscaster.dm"
-#include "code\game\machinery\overview.dm"
-#include "code\game\machinery\PDApainter.dm"
-#include "code\game\machinery\portable_turret.dm"
-#include "code\game\machinery\recharger.dm"
-#include "code\game\machinery\rechargestation.dm"
-#include "code\game\machinery\recycler.dm"
-#include "code\game\machinery\requests_console.dm"
-#include "code\game\machinery\robot_fabricator.dm"
-#include "code\game\machinery\shieldgen.dm"
-#include "code\game\machinery\Sleeper.dm"
-#include "code\game\machinery\spaceheater.dm"
-#include "code\game\machinery\status_display.dm"
-#include "code\game\machinery\suit_storage_unit.dm"
-#include "code\game\machinery\syndicatebeacon.dm"
-#include "code\game\machinery\syndicatebomb.dm"
-#include "code\game\machinery\teleporter.dm"
-#include "code\game\machinery\transformer.dm"
-#include "code\game\machinery\turrets.dm"
-#include "code\game\machinery\vending.dm"
-#include "code\game\machinery\washing_machine.dm"
-#include "code\game\machinery\wishgranter.dm"
-#include "code\game\machinery\atmoalter\area_atmos_computer.dm"
-#include "code\game\machinery\atmoalter\canister.dm"
-#include "code\game\machinery\atmoalter\meter.dm"
-#include "code\game\machinery\atmoalter\portable_atmospherics.dm"
-#include "code\game\machinery\atmoalter\pump.dm"
-#include "code\game\machinery\atmoalter\scrubber.dm"
-#include "code\game\machinery\atmoalter\zvent.dm"
-#include "code\game\machinery\bots\bots.dm"
-#include "code\game\machinery\bots\cleanbot.dm"
-#include "code\game\machinery\bots\ed209bot.dm"
-#include "code\game\machinery\bots\floorbot.dm"
-#include "code\game\machinery\bots\medbot.dm"
-#include "code\game\machinery\bots\mulebot.dm"
-#include "code\game\machinery\bots\secbot.dm"
-#include "code\game\machinery\camera\camera.dm"
-#include "code\game\machinery\camera\camera_assembly.dm"
-#include "code\game\machinery\camera\motion.dm"
-#include "code\game\machinery\camera\presets.dm"
-#include "code\game\machinery\camera\tracking.dm"
-#include "code\game\machinery\computer\ai_core.dm"
-#include "code\game\machinery\computer\aifixer.dm"
-#include "code\game\machinery\computer\arcade.dm"
-#include "code\game\machinery\computer\atmos_alert.dm"
-#include "code\game\machinery\computer\buildandrepair.dm"
-#include "code\game\machinery\computer\camera.dm"
-#include "code\game\machinery\computer\card.dm"
-#include "code\game\machinery\computer\cloning.dm"
-#include "code\game\machinery\computer\communications.dm"
-#include "code\game\machinery\computer\computer.dm"
-#include "code\game\machinery\computer\crew.dm"
-#include "code\game\machinery\computer\HolodeckControl.dm"
-#include "code\game\machinery\computer\law.dm"
-#include "code\game\machinery\computer\medical.dm"
-#include "code\game\machinery\computer\message.dm"
-#include "code\game\machinery\computer\Operating.dm"
-#include "code\game\machinery\computer\pod.dm"
-#include "code\game\machinery\computer\power.dm"
-#include "code\game\machinery\computer\prisoner.dm"
-#include "code\game\machinery\computer\robot.dm"
-#include "code\game\machinery\computer\security.dm"
-#include "code\game\machinery\computer\shuttle.dm"
-#include "code\game\machinery\computer\station_alert.dm"
-#include "code\game\machinery\computer\syndicate_shuttle.dm"
-#include "code\game\machinery\computer\telecrystalconsoles.dm"
-#include "code\game\machinery\doors\airlock.dm"
-#include "code\game\machinery\doors\airlock_electronics.dm"
-#include "code\game\machinery\doors\alarmlock.dm"
-#include "code\game\machinery\doors\brigdoors.dm"
-#include "code\game\machinery\doors\checkForMultipleDoors.dm"
-#include "code\game\machinery\doors\door.dm"
-#include "code\game\machinery\doors\firedoor.dm"
-#include "code\game\machinery\doors\poddoor.dm"
-#include "code\game\machinery\doors\shutters.dm"
-#include "code\game\machinery\doors\unpowered.dm"
-#include "code\game\machinery\doors\windowdoor.dm"
-#include "code\game\machinery\embedded_controller\access_controller.dm"
-#include "code\game\machinery\embedded_controller\airlock_controller.dm"
-#include "code\game\machinery\embedded_controller\embedded_controller_base.dm"
-#include "code\game\machinery\embedded_controller\simple_vent_controller.dm"
-#include "code\game\machinery\kitchen\gibber.dm"
-#include "code\game\machinery\kitchen\icecream_vat.dm"
-#include "code\game\machinery\kitchen\juicer.dm"
-#include "code\game\machinery\kitchen\microwave.dm"
-#include "code\game\machinery\kitchen\monkeyrecycler.dm"
-#include "code\game\machinery\kitchen\processor.dm"
-#include "code\game\machinery\kitchen\smartfridge.dm"
-#include "code\game\machinery\pipe\construction.dm"
-#include "code\game\machinery\pipe\pipe_dispenser.dm"
-#include "code\game\machinery\telecomms\broadcaster.dm"
-#include "code\game\machinery\telecomms\logbrowser.dm"
-#include "code\game\machinery\telecomms\machine_interactions.dm"
-#include "code\game\machinery\telecomms\presets.dm"
-#include "code\game\machinery\telecomms\telecomunications.dm"
-#include "code\game\machinery\telecomms\telemonitor.dm"
-#include "code\game\machinery\telecomms\traffic_control.dm"
-#include "code\game\mecha\mech_bay.dm"
-#include "code\game\mecha\mech_fabricator.dm"
-#include "code\game\mecha\mecha.dm"
-#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_wreckage.dm"
-#include "code\game\mecha\combat\combat.dm"
-#include "code\game\mecha\combat\durand.dm"
-#include "code\game\mecha\combat\gygax.dm"
-#include "code\game\mecha\combat\honker.dm"
-#include "code\game\mecha\combat\marauder.dm"
-#include "code\game\mecha\combat\phazon.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\weapons\weapons.dm"
-#include "code\game\mecha\medical\medical.dm"
-#include "code\game\mecha\medical\odysseus.dm"
-#include "code\game\mecha\working\ripley.dm"
-#include "code\game\mecha\working\working.dm"
-#include "code\game\objects\empulse.dm"
-#include "code\game\objects\explosion.dm"
-#include "code\game\objects\explosion_recursive.dm"
-#include "code\game\objects\items.dm"
-#include "code\game\objects\objs.dm"
-#include "code\game\objects\structures.dm"
-#include "code\game\objects\weapons.dm"
-#include "code\game\objects\effects\aliens.dm"
-#include "code\game\objects\effects\anomalies.dm"
-#include "code\game\objects\effects\bump_teleporter.dm"
-#include "code\game\objects\effects\effect_system.dm"
-#include "code\game\objects\effects\forcefields.dm"
-#include "code\game\objects\effects\gibs.dm"
-#include "code\game\objects\effects\glowshroom.dm"
-#include "code\game\objects\effects\landmarks.dm"
-#include "code\game\objects\effects\manifest.dm"
-#include "code\game\objects\effects\mines.dm"
-#include "code\game\objects\effects\misc.dm"
-#include "code\game\objects\effects\overlays.dm"
-#include "code\game\objects\effects\portals.dm"
-#include "code\game\objects\effects\spiders.dm"
-#include "code\game\objects\effects\step_triggers.dm"
-#include "code\game\objects\effects\decals\cleanable.dm"
-#include "code\game\objects\effects\decals\contraband.dm"
-#include "code\game\objects\effects\decals\crayon.dm"
-#include "code\game\objects\effects\decals\decal.dm"
-#include "code\game\objects\effects\decals\misc.dm"
-#include "code\game\objects\effects\decals\remains.dm"
-#include "code\game\objects\effects\decals\Cleanable\aliens.dm"
-#include "code\game\objects\effects\decals\Cleanable\humans.dm"
-#include "code\game\objects\effects\decals\Cleanable\misc.dm"
-#include "code\game\objects\effects\decals\Cleanable\robots.dm"
-#include "code\game\objects\effects\spawners\bombspawner.dm"
-#include "code\game\objects\effects\spawners\gibspawner.dm"
-#include "code\game\objects\effects\spawners\vaultspawner.dm"
-#include "code\game\objects\items\apc_frame.dm"
-#include "code\game\objects\items\blueprints.dm"
-#include "code\game\objects\items\bodybag.dm"
-#include "code\game\objects\items\candle.dm"
-#include "code\game\objects\items\crayons.dm"
-#include "code\game\objects\items\latexballoon.dm"
-#include "code\game\objects\items\shooting_range.dm"
-#include "code\game\objects\items\toys.dm"
-#include "code\game\objects\items\trash.dm"
-#include "code\game\objects\items\devices\aicard.dm"
-#include "code\game\objects\items\devices\camera_bug.dm"
-#include "code\game\objects\items\devices\chameleonproj.dm"
-#include "code\game\objects\items\devices\flash.dm"
-#include "code\game\objects\items\devices\flashlight.dm"
-#include "code\game\objects\items\devices\laserpointer.dm"
-#include "code\game\objects\items\devices\lightreplacer.dm"
-#include "code\game\objects\items\devices\multitool.dm"
-#include "code\game\objects\items\devices\paicard.dm"
-#include "code\game\objects\items\devices\powersink.dm"
-#include "code\game\objects\items\devices\scanners.dm"
-#include "code\game\objects\items\devices\taperecorder.dm"
-#include "code\game\objects\items\devices\traitordevices.dm"
-#include "code\game\objects\items\devices\transfer_valve.dm"
-#include "code\game\objects\items\devices\uplinks.dm"
-#include "code\game\objects\items\devices\violin.dm"
-#include "code\game\objects\items\devices\PDA\cart.dm"
-#include "code\game\objects\items\devices\PDA\chatroom.dm"
-#include "code\game\objects\items\devices\PDA\PDA.dm"
-#include "code\game\objects\items\devices\PDA\radio.dm"
-#include "code\game\objects\items\devices\radio\beacon.dm"
-#include "code\game\objects\items\devices\radio\electropack.dm"
-#include "code\game\objects\items\devices\radio\encryptionkey.dm"
-#include "code\game\objects\items\devices\radio\headset.dm"
-#include "code\game\objects\items\devices\radio\intercom.dm"
-#include "code\game\objects\items\devices\radio\radio.dm"
-#include "code\game\objects\items\robot\robot_items.dm"
-#include "code\game\objects\items\robot\robot_parts.dm"
-#include "code\game\objects\items\robot\robot_upgrades.dm"
-#include "code\game\objects\items\stacks\medical.dm"
-#include "code\game\objects\items\stacks\rods.dm"
-#include "code\game\objects\items\stacks\stack.dm"
-#include "code\game\objects\items\stacks\sheets\glass.dm"
-#include "code\game\objects\items\stacks\sheets\leather.dm"
-#include "code\game\objects\items\stacks\sheets\light.dm"
-#include "code\game\objects\items\stacks\sheets\mineral.dm"
-#include "code\game\objects\items\stacks\sheets\sheet_types.dm"
-#include "code\game\objects\items\stacks\sheets\sheets.dm"
-#include "code\game\objects\items\stacks\tiles\light.dm"
-#include "code\game\objects\items\stacks\tiles\plasteel.dm"
-#include "code\game\objects\items\stacks\tiles\tile_types.dm"
-#include "code\game\objects\items\weapons\AI_modules.dm"
-#include "code\game\objects\items\weapons\airlock_painter.dm"
-#include "code\game\objects\items\weapons\cards_ids.dm"
-#include "code\game\objects\items\weapons\cigs_lighters.dm"
-#include "code\game\objects\items\weapons\clown_items.dm"
-#include "code\game\objects\items\weapons\cosmetics.dm"
-#include "code\game\objects\items\weapons\dice.dm"
-#include "code\game\objects\items\weapons\dna_injector.dm"
-#include "code\game\objects\items\weapons\explosives.dm"
-#include "code\game\objects\items\weapons\extinguisher.dm"
-#include "code\game\objects\items\weapons\flamethrower.dm"
-#include "code\game\objects\items\weapons\gift_wrappaper.dm"
-#include "code\game\objects\items\weapons\handcuffs.dm"
-#include "code\game\objects\items\weapons\kitchen.dm"
-#include "code\game\objects\items\weapons\manuals.dm"
-#include "code\game\objects\items\weapons\mop.dm"
-#include "code\game\objects\items\weapons\paint.dm"
-#include "code\game\objects\items\weapons\paiwire.dm"
-#include "code\game\objects\items\weapons\power_cells.dm"
-#include "code\game\objects\items\weapons\RCD.dm"
-#include "code\game\objects\items\weapons\RSF.dm"
-#include "code\game\objects\items\weapons\scrolls.dm"
-#include "code\game\objects\items\weapons\shields.dm"
-#include "code\game\objects\items\weapons\singularityhammer.dm"
-#include "code\game\objects\items\weapons\stunbaton.dm"
-#include "code\game\objects\items\weapons\table_rack_parts.dm"
-#include "code\game\objects\items\weapons\teleportation.dm"
-#include "code\game\objects\items\weapons\tools.dm"
-#include "code\game\objects\items\weapons\twohanded.dm"
-#include "code\game\objects\items\weapons\vending_items.dm"
-#include "code\game\objects\items\weapons\weaponry.dm"
-#include "code\game\objects\items\weapons\grenades\chem_grenade.dm"
-#include "code\game\objects\items\weapons\grenades\emgrenade.dm"
-#include "code\game\objects\items\weapons\grenades\flashbang.dm"
-#include "code\game\objects\items\weapons\grenades\ghettobomb.dm"
-#include "code\game\objects\items\weapons\grenades\grenade.dm"
-#include "code\game\objects\items\weapons\grenades\smokebomb.dm"
-#include "code\game\objects\items\weapons\grenades\spawnergrenade.dm"
-#include "code\game\objects\items\weapons\grenades\syndieminibomb.dm"
-#include "code\game\objects\items\weapons\implants\implant.dm"
-#include "code\game\objects\items\weapons\implants\implantcase.dm"
-#include "code\game\objects\items\weapons\implants\implantchair.dm"
-#include "code\game\objects\items\weapons\implants\implanter.dm"
-#include "code\game\objects\items\weapons\implants\implantfreedom.dm"
-#include "code\game\objects\items\weapons\implants\implantpad.dm"
-#include "code\game\objects\items\weapons\implants\implantuplink.dm"
-#include "code\game\objects\items\weapons\melee\energy.dm"
-#include "code\game\objects\items\weapons\melee\misc.dm"
-#include "code\game\objects\items\weapons\storage\backpack.dm"
-#include "code\game\objects\items\weapons\storage\bags.dm"
-#include "code\game\objects\items\weapons\storage\belt.dm"
-#include "code\game\objects\items\weapons\storage\bible.dm"
-#include "code\game\objects\items\weapons\storage\boxes.dm"
-#include "code\game\objects\items\weapons\storage\briefcase.dm"
-#include "code\game\objects\items\weapons\storage\fancy.dm"
-#include "code\game\objects\items\weapons\storage\firstaid.dm"
-#include "code\game\objects\items\weapons\storage\lockbox.dm"
-#include "code\game\objects\items\weapons\storage\secure.dm"
-#include "code\game\objects\items\weapons\storage\storage.dm"
-#include "code\game\objects\items\weapons\storage\toolbox.dm"
-#include "code\game\objects\items\weapons\storage\uplink_kits.dm"
-#include "code\game\objects\items\weapons\storage\wallets.dm"
-#include "code\game\objects\items\weapons\tanks\jetpack.dm"
-#include "code\game\objects\items\weapons\tanks\tank_types.dm"
-#include "code\game\objects\items\weapons\tanks\tanks.dm"
-#include "code\game\objects\items\weapons\tanks\watertank.dm"
-#include "code\game\objects\structures\bedsheet_bin.dm"
-#include "code\game\objects\structures\displaycase.dm"
-#include "code\game\objects\structures\door_assembly.dm"
-#include "code\game\objects\structures\dresser.dm"
-#include "code\game\objects\structures\electricchair.dm"
-#include "code\game\objects\structures\extinguisher.dm"
-#include "code\game\objects\structures\false_walls.dm"
-#include "code\game\objects\structures\flora.dm"
-#include "code\game\objects\structures\girders.dm"
-#include "code\game\objects\structures\grille.dm"
-#include "code\game\objects\structures\janicart.dm"
-#include "code\game\objects\structures\kitchen_spike.dm"
-#include "code\game\objects\structures\ladders.dm"
-#include "code\game\objects\structures\lamarr_cage.dm"
-#include "code\game\objects\structures\lattice.dm"
-#include "code\game\objects\structures\mineral_doors.dm"
-#include "code\game\objects\structures\mirror.dm"
-#include "code\game\objects\structures\mop_bucket.dm"
-#include "code\game\objects\structures\morgue.dm"
-#include "code\game\objects\structures\musician.dm"
-#include "code\game\objects\structures\noticeboard.dm"
-#include "code\game\objects\structures\OpTable.dm"
-#include "code\game\objects\structures\safe.dm"
-#include "code\game\objects\structures\signs.dm"
-#include "code\game\objects\structures\tables_racks.dm"
-#include "code\game\objects\structures\tank_dispenser.dm"
-#include "code\game\objects\structures\target_stake.dm"
-#include "code\game\objects\structures\transit_tubes.dm"
-#include "code\game\objects\structures\watercloset.dm"
-#include "code\game\objects\structures\windoor_assembly.dm"
-#include "code\game\objects\structures\window.dm"
-#include "code\game\objects\structures\crates_lockers\bins.dm"
-#include "code\game\objects\structures\crates_lockers\closets.dm"
-#include "code\game\objects\structures\crates_lockers\crates.dm"
-#include "code\game\objects\structures\crates_lockers\largecrate.dm"
-#include "code\game\objects\structures\crates_lockers\closets\coffin.dm"
-#include "code\game\objects\structures\crates_lockers\closets\crittercrate.dm"
-#include "code\game\objects\structures\crates_lockers\closets\fireaxe.dm"
-#include "code\game\objects\structures\crates_lockers\closets\fitness.dm"
-#include "code\game\objects\structures\crates_lockers\closets\gimmick.dm"
-#include "code\game\objects\structures\crates_lockers\closets\job_closets.dm"
-#include "code\game\objects\structures\crates_lockers\closets\l3closet.dm"
-#include "code\game\objects\structures\crates_lockers\closets\malfunction.dm"
-#include "code\game\objects\structures\crates_lockers\closets\statue.dm"
-#include "code\game\objects\structures\crates_lockers\closets\syndicate.dm"
-#include "code\game\objects\structures\crates_lockers\closets\utility_closets.dm"
-#include "code\game\objects\structures\crates_lockers\closets\wardrobe.dm"
-#include "code\game\objects\structures\crates_lockers\closets\secure\bar.dm"
-#include "code\game\objects\structures\crates_lockers\closets\secure\cargo.dm"
-#include "code\game\objects\structures\crates_lockers\closets\secure\engineering.dm"
-#include "code\game\objects\structures\crates_lockers\closets\secure\freezer.dm"
-#include "code\game\objects\structures\crates_lockers\closets\secure\hydroponics.dm"
-#include "code\game\objects\structures\crates_lockers\closets\secure\medical.dm"
-#include "code\game\objects\structures\crates_lockers\closets\secure\personal.dm"
-#include "code\game\objects\structures\crates_lockers\closets\secure\scientist.dm"
-#include "code\game\objects\structures\crates_lockers\closets\secure\secure_closets.dm"
-#include "code\game\objects\structures\crates_lockers\closets\secure\security.dm"
-#include "code\game\objects\structures\stool_bed_chair_nest\alien_nests.dm"
-#include "code\game\objects\structures\stool_bed_chair_nest\bed.dm"
-#include "code\game\objects\structures\stool_bed_chair_nest\chairs.dm"
-#include "code\game\objects\structures\stool_bed_chair_nest\stools.dm"
-#include "code\game\turfs\simulated.dm"
-#include "code\game\turfs\turf.dm"
-#include "code\game\turfs\unsimulated.dm"
-#include "code\game\turfs\simulated\dirtystation.dm"
-#include "code\game\turfs\simulated\floor.dm"
-#include "code\game\turfs\simulated\floor_types.dm"
-#include "code\game\turfs\simulated\walls.dm"
-#include "code\game\turfs\simulated\walls_mineral.dm"
-#include "code\game\turfs\simulated\walls_misc.dm"
-#include "code\game\turfs\simulated\walls_reinforced.dm"
-#include "code\game\turfs\space\space.dm"
-#include "code\game\turfs\space\transit.dm"
-#include "code\game\turfs\unsimulated\beach.dm"
-#include "code\game\turfs\unsimulated\floor.dm"
-#include "code\game\turfs\unsimulated\walls.dm"
-#include "code\game\verbs\atom_verbs.dm"
-#include "code\game\verbs\ooc.dm"
-#include "code\game\verbs\suicide.dm"
-#include "code\game\verbs\who.dm"
-#include "code\js\byjax.dm"
-#include "code\js\menus.dm"
-#include "code\LINDA\LINDA_fire.dm"
-#include "code\LINDA\LINDA_system.dm"
-#include "code\LINDA\LINDA_turf_tile.dm"
-#include "code\modules\admin\admin.dm"
-#include "code\modules\admin\admin_investigate.dm"
-#include "code\modules\admin\admin_memo.dm"
-#include "code\modules\admin\admin_ranks.dm"
-#include "code\modules\admin\admin_verbs.dm"
-#include "code\modules\admin\banappearance.dm"
-#include "code\modules\admin\banjob.dm"
-#include "code\modules\admin\create_mob.dm"
-#include "code\modules\admin\create_object.dm"
-#include "code\modules\admin\create_turf.dm"
-#include "code\modules\admin\holder2.dm"
-#include "code\modules\admin\IsBanned.dm"
-#include "code\modules\admin\NewBan.dm"
-#include "code\modules\admin\newbanjob.dm"
-#include "code\modules\admin\player_notes.dm"
-#include "code\modules\admin\player_panel.dm"
-#include "code\modules\admin\topic.dm"
-#include "code\modules\admin\DB ban\functions.dm"
-#include "code\modules\admin\permissionverbs\permissionedit.dm"
-#include "code\modules\admin\verbs\adminhelp.dm"
-#include "code\modules\admin\verbs\adminjump.dm"
-#include "code\modules\admin\verbs\adminpm.dm"
-#include "code\modules\admin\verbs\adminsay.dm"
-#include "code\modules\admin\verbs\atmosdebug.dm"
-#include "code\modules\admin\verbs\BrokenInhands.dm"
-#include "code\modules\admin\verbs\cinematic.dm"
-#include "code\modules\admin\verbs\deadsay.dm"
-#include "code\modules\admin\verbs\debug.dm"
-#include "code\modules\admin\verbs\diagnostics.dm"
-#include "code\modules\admin\verbs\getlogs.dm"
-#include "code\modules\admin\verbs\mapping.dm"
-#include "code\modules\admin\verbs\massmodvar.dm"
-#include "code\modules\admin\verbs\modifyvariables.dm"
-#include "code\modules\admin\verbs\one_click_antag.dm"
-#include "code\modules\admin\verbs\onlyone.dm"
-#include "code\modules\admin\verbs\playsound.dm"
-#include "code\modules\admin\verbs\possess.dm"
-#include "code\modules\admin\verbs\pray.dm"
-#include "code\modules\admin\verbs\randomverbs.dm"
-#include "code\modules\admin\verbs\ticklag.dm"
-#include "code\modules\admin\verbs\tripAI.dm"
-#include "code\modules\assembly\assembly.dm"
-#include "code\modules\assembly\bomb.dm"
-#include "code\modules\assembly\helpers.dm"
-#include "code\modules\assembly\holder.dm"
-#include "code\modules\assembly\igniter.dm"
-#include "code\modules\assembly\infrared.dm"
-#include "code\modules\assembly\mousetrap.dm"
-#include "code\modules\assembly\proximity.dm"
-#include "code\modules\assembly\shock_kit.dm"
-#include "code\modules\assembly\signaler.dm"
-#include "code\modules\assembly\timer.dm"
-#include "code\modules\assembly\voice.dm"
-#include "code\modules\awaymissions\bluespaceartillery.dm"
-#include "code\modules\awaymissions\corpse.dm"
-#include "code\modules\awaymissions\exile.dm"
-#include "code\modules\awaymissions\gateway.dm"
-#include "code\modules\awaymissions\loot.dm"
-#include "code\modules\awaymissions\pamphlet.dm"
-#include "code\modules\awaymissions\trigger.dm"
-#include "code\modules\awaymissions\zlevel.dm"
-#include "code\modules\awaymissions\maploader\dmm_suite.dm"
-#include "code\modules\awaymissions\maploader\reader.dm"
-#include "code\modules\awaymissions\maploader\swapmaps.dm"
-#include "code\modules\awaymissions\maploader\writer.dm"
-#include "code\modules\awaymissions\mission_code\Academy.dm"
-#include "code\modules\awaymissions\mission_code\blackmarketpackers.dm"
-#include "code\modules\awaymissions\mission_code\box2550Away.dm"
-#include "code\modules\awaymissions\mission_code\centcomAway.dm"
-#include "code\modules\awaymissions\mission_code\challenge.dm"
-#include "code\modules\awaymissions\mission_code\spacebattle.dm"
-#include "code\modules\awaymissions\mission_code\stationCollision.dm"
-#include "code\modules\awaymissions\mission_code\wildwest.dm"
-#include "code\modules\client\client defines.dm"
-#include "code\modules\client\client procs.dm"
-#include "code\modules\client\preferences.dm"
-#include "code\modules\client\preferences_savefile.dm"
-#include "code\modules\client\preferences_toggles.dm"
-#include "code\modules\clothing\clothing.dm"
-#include "code\modules\clothing\glasses\glasses.dm"
-#include "code\modules\clothing\glasses\hud.dm"
-#include "code\modules\clothing\gloves\boxing.dm"
-#include "code\modules\clothing\gloves\color.dm"
-#include "code\modules\clothing\gloves\miscellaneous.dm"
-#include "code\modules\clothing\gloves\ninja.dm"
-#include "code\modules\clothing\head\collectable.dm"
-#include "code\modules\clothing\head\hardhat.dm"
-#include "code\modules\clothing\head\helmet.dm"
-#include "code\modules\clothing\head\jobs.dm"
-#include "code\modules\clothing\head\misc.dm"
-#include "code\modules\clothing\head\misc_special.dm"
-#include "code\modules\clothing\head\soft_caps.dm"
-#include "code\modules\clothing\masks\boxing.dm"
-#include "code\modules\clothing\masks\breath.dm"
-#include "code\modules\clothing\masks\gasmask.dm"
-#include "code\modules\clothing\masks\miscellaneous.dm"
-#include "code\modules\clothing\shoes\colour.dm"
-#include "code\modules\clothing\shoes\magboots.dm"
-#include "code\modules\clothing\shoes\miscellaneous.dm"
-#include "code\modules\clothing\spacesuits\miscellaneous.dm"
-#include "code\modules\clothing\spacesuits\ninja.dm"
-#include "code\modules\clothing\spacesuits\rig.dm"
-#include "code\modules\clothing\spacesuits\syndi.dm"
-#include "code\modules\clothing\suits\armor.dm"
-#include "code\modules\clothing\suits\bio.dm"
-#include "code\modules\clothing\suits\jobs.dm"
-#include "code\modules\clothing\suits\labcoat.dm"
-#include "code\modules\clothing\suits\miscellaneous.dm"
-#include "code\modules\clothing\suits\utility.dm"
-#include "code\modules\clothing\suits\wiz_robe.dm"
-#include "code\modules\clothing\under\chameleon.dm"
-#include "code\modules\clothing\under\color.dm"
-#include "code\modules\clothing\under\miscellaneous.dm"
-#include "code\modules\clothing\under\shorts.dm"
-#include "code\modules\clothing\under\syndicate.dm"
-#include "code\modules\clothing\under\ties.dm"
-#include "code\modules\clothing\under\jobs\civilian.dm"
-#include "code\modules\clothing\under\jobs\engineering.dm"
-#include "code\modules\clothing\under\jobs\medsci.dm"
-#include "code\modules\clothing\under\jobs\security.dm"
-#include "code\modules\detectivework\detective_work.dm"
-#include "code\modules\detectivework\evidence.dm"
-#include "code\modules\detectivework\footprints_and_rag.dm"
-#include "code\modules\detectivework\scanner.dm"
-#include "code\modules\events\alien_infestation.dm"
-#include "code\modules\events\anomaly.dm"
-#include "code\modules\events\anomaly_bluespace.dm"
-#include "code\modules\events\anomaly_flux.dm"
-#include "code\modules\events\anomaly_grav.dm"
-#include "code\modules\events\anomaly_pyro.dm"
-#include "code\modules\events\anomaly_vortex.dm"
-#include "code\modules\events\blob.dm"
-#include "code\modules\events\brand_intelligence.dm"
-#include "code\modules\events\carp_migration.dm"
-#include "code\modules\events\communications_blackout.dm"
-#include "code\modules\events\disease_outbreak.dm"
-#include "code\modules\events\dust.dm"
-#include "code\modules\events\electrical_storm.dm"
-#include "code\modules\events\event.dm"
-#include "code\modules\events\event_manager.dm"
-#include "code\modules\events\false_alarm.dm"
-#include "code\modules\events\immovable_rod.dm"
-#include "code\modules\events\ion_storm.dm"
-#include "code\modules\events\mass_hallucination.dm"
-#include "code\modules\events\meteor_wave.dm"
-#include "code\modules\events\ninja.dm"
-#include "code\modules\events\prison_break.dm"
-#include "code\modules\events\radiation_storm.dm"
-#include "code\modules\events\shuttle_loan.dm"
-#include "code\modules\events\spacevine.dm"
-#include "code\modules\events\spider_infestation.dm"
-#include "code\modules\events\spontaneous_appendicitis.dm"
-#include "code\modules\events\vent_clog.dm"
-#include "code\modules\events\wormholes.dm"
-#include "code\modules\events\holiday\halloween.dm"
-#include "code\modules\events\holiday\xmas.dm"
-#include "code\modules\flufftext\Dreaming.dm"
-#include "code\modules\flufftext\Hallucination.dm"
-#include "code\modules\flufftext\TextFilters.dm"
-#include "code\modules\food\recipes_microwave.dm"
-#include "code\modules\hydroponics\biogenerator.dm"
-#include "code\modules\hydroponics\grown.dm"
-#include "code\modules\hydroponics\growninedible.dm"
-#include "code\modules\hydroponics\hydroitemcode.dm"
-#include "code\modules\hydroponics\hydroitemdefines.dm"
-#include "code\modules\hydroponics\hydroponics.dm"
-#include "code\modules\hydroponics\seed_extractor.dm"
-#include "code\modules\hydroponics\seeds.dm"
-#include "code\modules\library\lib_items.dm"
-#include "code\modules\library\lib_machines.dm"
-#include "code\modules\library\lib_readme.dm"
-#include "code\modules\mining\machine_input_output_plates.dm"
-#include "code\modules\mining\machine_processing.dm"
-#include "code\modules\mining\machine_stacking.dm"
-#include "code\modules\mining\machine_unloading.dm"
-#include "code\modules\mining\mine_areas.dm"
-#include "code\modules\mining\mine_items.dm"
-#include "code\modules\mining\mine_turfs.dm"
-#include "code\modules\mining\mint.dm"
-#include "code\modules\mining\money_bag.dm"
-#include "code\modules\mining\ores_coins.dm"
-#include "code\modules\mining\satchel_ore_boxdm.dm"
-#include "code\modules\mining\laborcamp\laborminerals.dm"
-#include "code\modules\mining\laborcamp\laborshuttle.dm"
-#include "code\modules\mining\laborcamp\laborstacker.dm"
-#include "code\modules\mob\death.dm"
-#include "code\modules\mob\inventory.dm"
-#include "code\modules\mob\login.dm"
-#include "code\modules\mob\logout.dm"
-#include "code\modules\mob\mob.dm"
-#include "code\modules\mob\mob_cleanup.dm"
-#include "code\modules\mob\mob_defines.dm"
-#include "code\modules\mob\mob_grab.dm"
-#include "code\modules\mob\mob_helpers.dm"
-#include "code\modules\mob\mob_movement.dm"
-#include "code\modules\mob\mob_transformation_simple.dm"
-#include "code\modules\mob\say.dm"
-#include "code\modules\mob\transform_procs.dm"
-#include "code\modules\mob\update_icons.dm"
-#include "code\modules\mob\camera\camera.dm"
-#include "code\modules\mob\dead\death.dm"
-#include "code\modules\mob\dead\observer\login.dm"
-#include "code\modules\mob\dead\observer\logout.dm"
-#include "code\modules\mob\dead\observer\observer.dm"
-#include "code\modules\mob\dead\observer\say.dm"
-#include "code\modules\mob\living\damage_procs.dm"
-#include "code\modules\mob\living\death.dm"
-#include "code\modules\mob\living\emote.dm"
-#include "code\modules\mob\living\living.dm"
-#include "code\modules\mob\living\living_defense.dm"
-#include "code\modules\mob\living\living_defines.dm"
-#include "code\modules\mob\living\login.dm"
-#include "code\modules\mob\living\logout.dm"
-#include "code\modules\mob\living\say.dm"
-#include "code\modules\mob\living\carbon\carbon.dm"
-#include "code\modules\mob\living\carbon\carbon_defense.dm"
-#include "code\modules\mob\living\carbon\carbon_defines.dm"
-#include "code\modules\mob\living\carbon\emote.dm"
-#include "code\modules\mob\living\carbon\inventory.dm"
-#include "code\modules\mob\living\carbon\update_icons.dm"
-#include "code\modules\mob\living\carbon\alien\alien.dm"
-#include "code\modules\mob\living\carbon\alien\alien_defense.dm"
-#include "code\modules\mob\living\carbon\alien\death.dm"
-#include "code\modules\mob\living\carbon\alien\login.dm"
-#include "code\modules\mob\living\carbon\alien\logout.dm"
-#include "code\modules\mob\living\carbon\alien\powers.dm"
-#include "code\modules\mob\living\carbon\alien\say.dm"
-#include "code\modules\mob\living\carbon\alien\screen.dm"
-#include "code\modules\mob\living\carbon\alien\humanoid\alien_powers.dm"
-#include "code\modules\mob\living\carbon\alien\humanoid\death.dm"
-#include "code\modules\mob\living\carbon\alien\humanoid\emote.dm"
-#include "code\modules\mob\living\carbon\alien\humanoid\humanoid.dm"
-#include "code\modules\mob\living\carbon\alien\humanoid\inventory.dm"
-#include "code\modules\mob\living\carbon\alien\humanoid\life.dm"
-#include "code\modules\mob\living\carbon\alien\humanoid\login.dm"
-#include "code\modules\mob\living\carbon\alien\humanoid\queen.dm"
-#include "code\modules\mob\living\carbon\alien\humanoid\update_icons.dm"
-#include "code\modules\mob\living\carbon\alien\humanoid\caste\drone.dm"
-#include "code\modules\mob\living\carbon\alien\humanoid\caste\hunter.dm"
-#include "code\modules\mob\living\carbon\alien\humanoid\caste\sentinel.dm"
-#include "code\modules\mob\living\carbon\alien\larva\death.dm"
-#include "code\modules\mob\living\carbon\alien\larva\emote.dm"
-#include "code\modules\mob\living\carbon\alien\larva\inventory.dm"
-#include "code\modules\mob\living\carbon\alien\larva\larva.dm"
-#include "code\modules\mob\living\carbon\alien\larva\life.dm"
-#include "code\modules\mob\living\carbon\alien\larva\powers.dm"
-#include "code\modules\mob\living\carbon\alien\larva\update_icons.dm"
-#include "code\modules\mob\living\carbon\alien\special\alien_embryo.dm"
-#include "code\modules\mob\living\carbon\alien\special\facehugger.dm"
-#include "code\modules\mob\living\carbon\brain\brain.dm"
-#include "code\modules\mob\living\carbon\brain\brain_item.dm"
-#include "code\modules\mob\living\carbon\brain\death.dm"
-#include "code\modules\mob\living\carbon\brain\emote.dm"
-#include "code\modules\mob\living\carbon\brain\life.dm"
-#include "code\modules\mob\living\carbon\brain\MMI.dm"
-#include "code\modules\mob\living\carbon\brain\say.dm"
-#include "code\modules\mob\living\carbon\human\death.dm"
-#include "code\modules\mob\living\carbon\human\emote.dm"
-#include "code\modules\mob\living\carbon\human\examine.dm"
-#include "code\modules\mob\living\carbon\human\human.dm"
-#include "code\modules\mob\living\carbon\human\human_attackalien.dm"
-#include "code\modules\mob\living\carbon\human\human_attackhand.dm"
-#include "code\modules\mob\living\carbon\human\human_attackpaw.dm"
-#include "code\modules\mob\living\carbon\human\human_damage.dm"
-#include "code\modules\mob\living\carbon\human\human_defense.dm"
-#include "code\modules\mob\living\carbon\human\human_defines.dm"
-#include "code\modules\mob\living\carbon\human\human_helpers.dm"
-#include "code\modules\mob\living\carbon\human\human_movement.dm"
-#include "code\modules\mob\living\carbon\human\inventory.dm"
-#include "code\modules\mob\living\carbon\human\life.dm"
-#include "code\modules\mob\living\carbon\human\login.dm"
-#include "code\modules\mob\living\carbon\human\say.dm"
-#include "code\modules\mob\living\carbon\human\update_icons.dm"
-#include "code\modules\mob\living\carbon\human\whisper.dm"
-#include "code\modules\mob\living\carbon\metroid\death.dm"
-#include "code\modules\mob\living\carbon\metroid\emote.dm"
-#include "code\modules\mob\living\carbon\metroid\examine.dm"
-#include "code\modules\mob\living\carbon\metroid\hud.dm"
-#include "code\modules\mob\living\carbon\metroid\life.dm"
-#include "code\modules\mob\living\carbon\metroid\login.dm"
-#include "code\modules\mob\living\carbon\metroid\metroid.dm"
-#include "code\modules\mob\living\carbon\metroid\powers.dm"
-#include "code\modules\mob\living\carbon\metroid\say.dm"
-#include "code\modules\mob\living\carbon\metroid\subtypes.dm"
-#include "code\modules\mob\living\carbon\metroid\update_icons.dm"
-#include "code\modules\mob\living\carbon\monkey\death.dm"
-#include "code\modules\mob\living\carbon\monkey\emote.dm"
-#include "code\modules\mob\living\carbon\monkey\examine.dm"
-#include "code\modules\mob\living\carbon\monkey\inventory.dm"
-#include "code\modules\mob\living\carbon\monkey\life.dm"
-#include "code\modules\mob\living\carbon\monkey\login.dm"
-#include "code\modules\mob\living\carbon\monkey\monkey.dm"
-#include "code\modules\mob\living\carbon\monkey\powers.dm"
-#include "code\modules\mob\living\carbon\monkey\say.dm"
-#include "code\modules\mob\living\carbon\monkey\update_icons.dm"
-#include "code\modules\mob\living\silicon\death.dm"
-#include "code\modules\mob\living\silicon\laws.dm"
-#include "code\modules\mob\living\silicon\login.dm"
-#include "code\modules\mob\living\silicon\say.dm"
-#include "code\modules\mob\living\silicon\silicon.dm"
-#include "code\modules\mob\living\silicon\ai\ai.dm"
-#include "code\modules\mob\living\silicon\ai\death.dm"
-#include "code\modules\mob\living\silicon\ai\examine.dm"
-#include "code\modules\mob\living\silicon\ai\laws.dm"
-#include "code\modules\mob\living\silicon\ai\life.dm"
-#include "code\modules\mob\living\silicon\ai\login.dm"
-#include "code\modules\mob\living\silicon\ai\logout.dm"
-#include "code\modules\mob\living\silicon\ai\say.dm"
-#include "code\modules\mob\living\silicon\ai\vox_sounds.dm"
-#include "code\modules\mob\living\silicon\ai\freelook\cameranet.dm"
-#include "code\modules\mob\living\silicon\ai\freelook\chunk.dm"
-#include "code\modules\mob\living\silicon\ai\freelook\eye.dm"
-#include "code\modules\mob\living\silicon\ai\freelook\read_me.dm"
-#include "code\modules\mob\living\silicon\ai\freelook\update_triggers.dm"
-#include "code\modules\mob\living\silicon\decoy\death.dm"
-#include "code\modules\mob\living\silicon\decoy\decoy.dm"
-#include "code\modules\mob\living\silicon\decoy\life.dm"
-#include "code\modules\mob\living\silicon\pai\death.dm"
-#include "code\modules\mob\living\silicon\pai\examine.dm"
-#include "code\modules\mob\living\silicon\pai\hud.dm"
-#include "code\modules\mob\living\silicon\pai\life.dm"
-#include "code\modules\mob\living\silicon\pai\pai.dm"
-#include "code\modules\mob\living\silicon\pai\personality.dm"
-#include "code\modules\mob\living\silicon\pai\recruit.dm"
-#include "code\modules\mob\living\silicon\pai\say.dm"
-#include "code\modules\mob\living\silicon\pai\software.dm"
-#include "code\modules\mob\living\silicon\robot\death.dm"
-#include "code\modules\mob\living\silicon\robot\emote.dm"
-#include "code\modules\mob\living\silicon\robot\examine.dm"
-#include "code\modules\mob\living\silicon\robot\inventory.dm"
-#include "code\modules\mob\living\silicon\robot\laws.dm"
-#include "code\modules\mob\living\silicon\robot\life.dm"
-#include "code\modules\mob\living\silicon\robot\login.dm"
-#include "code\modules\mob\living\silicon\robot\robot.dm"
-#include "code\modules\mob\living\silicon\robot\robot_modules.dm"
-#include "code\modules\mob\living\silicon\robot\robot_movement.dm"
-#include "code\modules\mob\living\silicon\robot\say.dm"
-#include "code\modules\mob\living\simple_animal\constructs.dm"
-#include "code\modules\mob\living\simple_animal\corpse.dm"
-#include "code\modules\mob\living\simple_animal\parrot.dm"
-#include "code\modules\mob\living\simple_animal\shade.dm"
-#include "code\modules\mob\living\simple_animal\simple_animal.dm"
-#include "code\modules\mob\living\simple_animal\friendly\cat.dm"
-#include "code\modules\mob\living\simple_animal\friendly\corgi.dm"
-#include "code\modules\mob\living\simple_animal\friendly\crab.dm"
-#include "code\modules\mob\living\simple_animal\friendly\farm_animals.dm"
-#include "code\modules\mob\living\simple_animal\friendly\lizard.dm"
-#include "code\modules\mob\living\simple_animal\friendly\mouse.dm"
-#include "code\modules\mob\living\simple_animal\friendly\pug.dm"
-#include "code\modules\mob\living\simple_animal\friendly\slime.dm"
-#include "code\modules\mob\living\simple_animal\friendly\tomato.dm"
-#include "code\modules\mob\living\simple_animal\hostile\alien.dm"
-#include "code\modules\mob\living\simple_animal\hostile\bear.dm"
-#include "code\modules\mob\living\simple_animal\hostile\carp.dm"
-#include "code\modules\mob\living\simple_animal\hostile\creature.dm"
-#include "code\modules\mob\living\simple_animal\hostile\faithless.dm"
-#include "code\modules\mob\living\simple_animal\hostile\giant_spider.dm"
-#include "code\modules\mob\living\simple_animal\hostile\hivebot.dm"
-#include "code\modules\mob\living\simple_animal\hostile\hostile.dm"
-#include "code\modules\mob\living\simple_animal\hostile\mimic.dm"
-#include "code\modules\mob\living\simple_animal\hostile\mining_mobs.dm"
-#include "code\modules\mob\living\simple_animal\hostile\mushroom.dm"
-#include "code\modules\mob\living\simple_animal\hostile\pirate.dm"
-#include "code\modules\mob\living\simple_animal\hostile\russian.dm"
-#include "code\modules\mob\living\simple_animal\hostile\syndicate.dm"
-#include "code\modules\mob\living\simple_animal\hostile\tree.dm"
-#include "code\modules\mob\living\simple_animal\hostile\retaliate\bat.dm"
-#include "code\modules\mob\living\simple_animal\hostile\retaliate\clown.dm"
-#include "code\modules\mob\living\simple_animal\hostile\retaliate\retaliate.dm"
-#include "code\modules\mob\new_player\login.dm"
-#include "code\modules\mob\new_player\logout.dm"
-#include "code\modules\mob\new_player\new_player.dm"
-#include "code\modules\mob\new_player\poll.dm"
-#include "code\modules\mob\new_player\preferences_setup.dm"
-#include "code\modules\mob\new_player\sprite_accessories.dm"
-#include "code\modules\nano\_JSON.dm"
-#include "code\modules\nano\JSON Reader.dm"
-#include "code\modules\nano\JSON Writer.dm"
-#include "code\modules\nano\nanoexternal.dm"
-#include "code\modules\nano\nanomanager.dm"
-#include "code\modules\nano\nanoui.dm"
-#include "code\modules\paperwork\clipboard.dm"
-#include "code\modules\paperwork\filingcabinet.dm"
-#include "code\modules\paperwork\folders.dm"
-#include "code\modules\paperwork\handlabeler.dm"
-#include "code\modules\paperwork\paper.dm"
-#include "code\modules\paperwork\paperbin.dm"
-#include "code\modules\paperwork\pen.dm"
-#include "code\modules\paperwork\photocopier.dm"
-#include "code\modules\paperwork\photography.dm"
-#include "code\modules\paperwork\stamps.dm"
-#include "code\modules\power\apc.dm"
-#include "code\modules\power\cable.dm"
-#include "code\modules\power\cell.dm"
-#include "code\modules\power\engine.dm"
-#include "code\modules\power\generator.dm"
-#include "code\modules\power\gravitygenerator.dm"
-#include "code\modules\power\lighting.dm"
-#include "code\modules\power\port_gen.dm"
-#include "code\modules\power\power.dm"
-#include "code\modules\power\smes.dm"
-#include "code\modules\power\solar.dm"
-#include "code\modules\power\switch.dm"
-#include "code\modules\power\terminal.dm"
-#include "code\modules\power\tracker.dm"
-#include "code\modules\power\turbine.dm"
-#include "code\modules\power\antimatter\containment_jar.dm"
-#include "code\modules\power\antimatter\control.dm"
-#include "code\modules\power\antimatter\shielding.dm"
-#include "code\modules\power\singularity\collector.dm"
-#include "code\modules\power\singularity\containment_field.dm"
-#include "code\modules\power\singularity\emitter.dm"
-#include "code\modules\power\singularity\field_generator.dm"
-#include "code\modules\power\singularity\generator.dm"
-#include "code\modules\power\singularity\investigate.dm"
-#include "code\modules\power\singularity\singularity.dm"
-#include "code\modules\power\singularity\particle_accelerator\particle.dm"
-#include "code\modules\power\singularity\particle_accelerator\particle_accelerator.dm"
-#include "code\modules\power\singularity\particle_accelerator\particle_chamber.dm"
-#include "code\modules\power\singularity\particle_accelerator\particle_control.dm"
-#include "code\modules\power\singularity\particle_accelerator\particle_emitter.dm"
-#include "code\modules\power\singularity\particle_accelerator\particle_power.dm"
-#include "code\modules\projectiles\ammunition.dm"
-#include "code\modules\projectiles\firing.dm"
-#include "code\modules\projectiles\gun.dm"
-#include "code\modules\projectiles\projectile.dm"
-#include "code\modules\projectiles\ammunition\boxes.dm"
-#include "code\modules\projectiles\ammunition\bullets.dm"
-#include "code\modules\projectiles\ammunition\energy.dm"
-#include "code\modules\projectiles\ammunition\magazines.dm"
-#include "code\modules\projectiles\ammunition\special.dm"
-#include "code\modules\projectiles\guns\energy.dm"
-#include "code\modules\projectiles\guns\magic.dm"
-#include "code\modules\projectiles\guns\projectile.dm"
-#include "code\modules\projectiles\guns\energy\laser.dm"
-#include "code\modules\projectiles\guns\energy\nuclear.dm"
-#include "code\modules\projectiles\guns\energy\pulse.dm"
-#include "code\modules\projectiles\guns\energy\special.dm"
-#include "code\modules\projectiles\guns\energy\stun.dm"
-#include "code\modules\projectiles\guns\energy\temperature.dm"
-#include "code\modules\projectiles\guns\magic\staff.dm"
-#include "code\modules\projectiles\guns\magic\wand.dm"
-#include "code\modules\projectiles\guns\projectile\automatic.dm"
-#include "code\modules\projectiles\guns\projectile\pistol.dm"
-#include "code\modules\projectiles\guns\projectile\revolver.dm"
-#include "code\modules\projectiles\guns\projectile\shotgun.dm"
-#include "code\modules\projectiles\projectile\beams.dm"
-#include "code\modules\projectiles\projectile\bullets.dm"
-#include "code\modules\projectiles\projectile\energy.dm"
-#include "code\modules\projectiles\projectile\magic.dm"
-#include "code\modules\projectiles\projectile\special.dm"
-#include "code\modules\reagents\Chemistry-Colours.dm"
-#include "code\modules\reagents\Chemistry-Holder.dm"
-#include "code\modules\reagents\Chemistry-Machinery.dm"
-#include "code\modules\reagents\Chemistry-Readme.dm"
-#include "code\modules\reagents\Chemistry-Reagents.dm"
-#include "code\modules\reagents\Chemistry-Recipes.dm"
-#include "code\modules\reagents\grenade_launcher.dm"
-#include "code\modules\reagents\reagent_containers.dm"
-#include "code\modules\reagents\reagent_dispenser.dm"
-#include "code\modules\reagents\syringe_gun.dm"
-#include "code\modules\reagents\reagent_containers\borghydro.dm"
-#include "code\modules\reagents\reagent_containers\dropper.dm"
-#include "code\modules\reagents\reagent_containers\food.dm"
-#include "code\modules\reagents\reagent_containers\glass.dm"
-#include "code\modules\reagents\reagent_containers\hypospray.dm"
-#include "code\modules\reagents\reagent_containers\pill.dm"
-#include "code\modules\reagents\reagent_containers\spray.dm"
-#include "code\modules\reagents\reagent_containers\syringes.dm"
-#include "code\modules\reagents\reagent_containers\food\condiment.dm"
-#include "code\modules\reagents\reagent_containers\food\drinks.dm"
-#include "code\modules\reagents\reagent_containers\food\snacks.dm"
-#include "code\modules\reagents\reagent_containers\food\drinks\bottle.dm"
-#include "code\modules\reagents\reagent_containers\food\drinks\drinkingglass.dm"
-#include "code\modules\reagents\reagent_containers\food\drinks\bottle\robot.dm"
-#include "code\modules\reagents\reagent_containers\food\snacks\meat.dm"
-#include "code\modules\reagents\reagent_containers\glass\bottle.dm"
-#include "code\modules\reagents\reagent_containers\glass\bottle\robot.dm"
-#include "code\modules\recycling\conveyor2.dm"
-#include "code\modules\recycling\disposal-construction.dm"
-#include "code\modules\recycling\disposal.dm"
-#include "code\modules\recycling\sortingmachinery.dm"
-#include "code\modules\research\circuitprinter.dm"
-#include "code\modules\research\designs.dm"
-#include "code\modules\research\destructive_analyzer.dm"
-#include "code\modules\research\message_server.dm"
-#include "code\modules\research\protolathe.dm"
-#include "code\modules\research\rd-readme.dm"
-#include "code\modules\research\rdconsole.dm"
-#include "code\modules\research\rdmachines.dm"
-#include "code\modules\research\research.dm"
-#include "code\modules\research\server.dm"
-#include "code\modules\scripting\Errors.dm"
-#include "code\modules\scripting\IDE.dm"
-#include "code\modules\scripting\Options.dm"
-#include "code\modules\scripting\stack.dm"
-#include "code\modules\scripting\AST\AST Nodes.dm"
-#include "code\modules\scripting\AST\Blocks.dm"
-#include "code\modules\scripting\AST\Statements.dm"
-#include "code\modules\scripting\AST\Operators\Binary Operators.dm"
-#include "code\modules\scripting\AST\Operators\Unary Operators.dm"
-#include "code\modules\scripting\Implementations\_Logic.dm"
-#include "code\modules\scripting\Implementations\Telecomms.dm"
-#include "code\modules\scripting\Interpreter\Evaluation.dm"
-#include "code\modules\scripting\Interpreter\Interaction.dm"
-#include "code\modules\scripting\Interpreter\Interpreter.dm"
-#include "code\modules\scripting\Interpreter\Scope.dm"
-#include "code\modules\scripting\Parser\Expressions.dm"
-#include "code\modules\scripting\Parser\Keywords.dm"
-#include "code\modules\scripting\Parser\Parser.dm"
-#include "code\modules\scripting\Scanner\Scanner.dm"
-#include "code\modules\scripting\Scanner\Tokens.dm"
-#include "code\modules\security levels\keycard authentication.dm"
-#include "code\modules\security levels\security levels.dm"
-#include "code\modules\shuttle\shuttle.dm"
-#include "code\modules\surgery\appendectomy.dm"
-#include "code\modules\surgery\brain_removal.dm"
-#include "code\modules\surgery\cavity_implant.dm"
-#include "code\modules\surgery\core_removal.dm"
-#include "code\modules\surgery\eye_surgery.dm"
-#include "code\modules\surgery\gender_reassignment.dm"
-#include "code\modules\surgery\generic_steps.dm"
-#include "code\modules\surgery\helpers.dm"
-#include "code\modules\surgery\implant_removal.dm"
-#include "code\modules\surgery\limb augmentation.dm"
-#include "code\modules\surgery\lipoplasty.dm"
-#include "code\modules\surgery\plastic_surgery.dm"
-#include "code\modules\surgery\surgery.dm"
-#include "code\modules\surgery\surgery_step.dm"
-#include "code\modules\surgery\tools.dm"
-#include "code\modules\surgery\xenomorph_removal.dm"
-#include "code\modules\surgery\organs\augments.dm"
-#include "code\modules\surgery\organs\helpers.dm"
-#include "code\modules\surgery\organs\organ.dm"
-#include "code\modules\telesci\bscrystal.dm"
-#include "code\modules\telesci\gps.dm"
-#include "code\modules\telesci\telepad.dm"
-#include "code\modules\telesci\telesci_computer.dm"
-#include "code\WorkInProgress\buildmode.dm"
-#include "code\WorkInProgress\explosion_particles.dm"
-#include "code\WorkInProgress\Sigyn\Department Sec\jobs.dm"
-#include "interface\interface.dm"
-#include "interface\stylesheet.dm"
-#include "interface\skin.dmf"
-// END_INCLUDE
+// DM Environment file for tgstation.dme.
+// All manual changes should be made outside the BEGIN_ and END_ blocks.
+ // New source code should be placed in .dm files: choose File/New --> Code File.
+// BEGIN_INTERNALS
+// END_INTERNALS
+
+// BEGIN_FILE_DIR
+#define FILE_DIR .
+// END_FILE_DIR
+
+// BEGIN_PREFERENCES
+#define DEBUG
+// END_PREFERENCES
+
+// BEGIN_INCLUDE
+#include "_maps\tgstation2.dm"
+#include "code\_compile_options.dm"
+#include "code\hub.dm"
+#include "code\world.dm"
+#include "code\__DEFINES\admin.dm"
+#include "code\__DEFINES\atmospherics.dm"
+#include "code\__DEFINES\clothing.dm"
+#include "code\__DEFINES\combat.dm"
+#include "code\__DEFINES\flags.dm"
+#include "code\__DEFINES\genetics.dm"
+#include "code\__DEFINES\machines.dm"
+#include "code\__DEFINES\math.dm"
+#include "code\__DEFINES\misc.dm"
+#include "code\__DEFINES\preferences.dm"
+#include "code\__DEFINES\sight.dm"
+#include "code\__DEFINES\stat.dm"
+#include "code\__HELPERS\files.dm"
+#include "code\__HELPERS\game.dm"
+#include "code\__HELPERS\global_lists.dm"
+#include "code\__HELPERS\icons.dm"
+#include "code\__HELPERS\lists.dm"
+#include "code\__HELPERS\logging.dm"
+#include "code\__HELPERS\maths.dm"
+#include "code\__HELPERS\matrices.dm"
+#include "code\__HELPERS\mobs.dm"
+#include "code\__HELPERS\names.dm"
+#include "code\__HELPERS\sanitize_values.dm"
+#include "code\__HELPERS\text.dm"
+#include "code\__HELPERS\time.dm"
+#include "code\__HELPERS\type2type.dm"
+#include "code\__HELPERS\unsorted.dm"
+#include "code\_globalvars\configuration.dm"
+#include "code\_globalvars\database.dm"
+#include "code\_globalvars\game_modes.dm"
+#include "code\_globalvars\genetics.dm"
+#include "code\_globalvars\logging.dm"
+#include "code\_globalvars\misc.dm"
+#include "code\_globalvars\station.dm"
+#include "code\_globalvars\unused.dm"
+#include "code\_globalvars\lists\flavor_misc.dm"
+#include "code\_globalvars\lists\mapping.dm"
+#include "code\_globalvars\lists\mobs.dm"
+#include "code\_globalvars\lists\names.dm"
+#include "code\_globalvars\lists\objects.dm"
+#include "code\_onclick\adjacent.dm"
+#include "code\_onclick\ai.dm"
+#include "code\_onclick\click.dm"
+#include "code\_onclick\cyborg.dm"
+#include "code\_onclick\drag_drop.dm"
+#include "code\_onclick\item_attack.dm"
+#include "code\_onclick\observer.dm"
+#include "code\_onclick\other_mobs.dm"
+#include "code\_onclick\overmind.dm"
+#include "code\_onclick\telekinesis.dm"
+#include "code\_onclick\hud\_defines.dm"
+#include "code\_onclick\hud\alien.dm"
+#include "code\_onclick\hud\alien_larva.dm"
+#include "code\_onclick\hud\hud.dm"
+#include "code\_onclick\hud\human.dm"
+#include "code\_onclick\hud\monkey.dm"
+#include "code\_onclick\hud\other_mobs.dm"
+#include "code\_onclick\hud\robot.dm"
+#include "code\_onclick\hud\screen_objects.dm"
+#include "code\ATMOSPHERICS\atmospherics.dm"
+#include "code\ATMOSPHERICS\datum_pipe_network.dm"
+#include "code\ATMOSPHERICS\datum_pipeline.dm"
+#include "code\ATMOSPHERICS\he_pipes.dm"
+#include "code\ATMOSPHERICS\pipes.dm"
+#include "code\ATMOSPHERICS\components\portables_connector.dm"
+#include "code\ATMOSPHERICS\components\valve.dm"
+#include "code\ATMOSPHERICS\components\binary_devices\binary_atmos_base.dm"
+#include "code\ATMOSPHERICS\components\binary_devices\circulator.dm"
+#include "code\ATMOSPHERICS\components\binary_devices\dp_vent_pump.dm"
+#include "code\ATMOSPHERICS\components\binary_devices\passive_gate.dm"
+#include "code\ATMOSPHERICS\components\binary_devices\pump.dm"
+#include "code\ATMOSPHERICS\components\binary_devices\volume_pump.dm"
+#include "code\ATMOSPHERICS\components\trinary_devices\filter.dm"
+#include "code\ATMOSPHERICS\components\trinary_devices\mixer.dm"
+#include "code\ATMOSPHERICS\components\trinary_devices\trinary_base.dm"
+#include "code\ATMOSPHERICS\components\unary\cold_sink.dm"
+#include "code\ATMOSPHERICS\components\unary\generator_input.dm"
+#include "code\ATMOSPHERICS\components\unary\heat_exchanger.dm"
+#include "code\ATMOSPHERICS\components\unary\heat_source.dm"
+#include "code\ATMOSPHERICS\components\unary\outlet_injector.dm"
+#include "code\ATMOSPHERICS\components\unary\oxygen_generator.dm"
+#include "code\ATMOSPHERICS\components\unary\unary_base.dm"
+#include "code\ATMOSPHERICS\components\unary\vent_pump.dm"
+#include "code\ATMOSPHERICS\components\unary\vent_scrubber.dm"
+#include "code\controllers\_DynamicAreaLighting_TG.dm"
+#include "code\controllers\configuration.dm"
+#include "code\controllers\failsafe.dm"
+#include "code\controllers\lighting_controller.dm"
+#include "code\controllers\master_controller.dm"
+#include "code\controllers\shuttle_controller.dm"
+#include "code\controllers\supply_shuttle.dm"
+#include "code\controllers\verbs.dm"
+#include "code\controllers\voting.dm"
+#include "code\datums\ai_laws.dm"
+#include "code\datums\browser.dm"
+#include "code\datums\computerfiles.dm"
+#include "code\datums\datacore.dm"
+#include "code\datums\datumvars.dm"
+#include "code\datums\disease.dm"
+#include "code\datums\mind.dm"
+#include "code\datums\mixed.dm"
+#include "code\datums\modules.dm"
+#include "code\datums\recipe.dm"
+#include "code\datums\spell.dm"
+#include "code\datums\sun.dm"
+#include "code\datums\supplypacks.dm"
+#include "code\datums\uplink_item.dm"
+#include "code\datums\diseases\appendicitis.dm"
+#include "code\datums\diseases\beesease.dm"
+#include "code\datums\diseases\brainrot.dm"
+#include "code\datums\diseases\cold.dm"
+#include "code\datums\diseases\cold9.dm"
+#include "code\datums\diseases\dna_spread.dm"
+#include "code\datums\diseases\fake_gbs.dm"
+#include "code\datums\diseases\flu.dm"
+#include "code\datums\diseases\fluspanish.dm"
+#include "code\datums\diseases\gbs.dm"
+#include "code\datums\diseases\jungle_fever.dm"
+#include "code\datums\diseases\magnitis.dm"
+#include "code\datums\diseases\pierrot_throat.dm"
+#include "code\datums\diseases\plasmatoid.dm"
+#include "code\datums\diseases\retrovirus.dm"
+#include "code\datums\diseases\rhumba_beat.dm"
+#include "code\datums\diseases\transformation.dm"
+#include "code\datums\diseases\wizarditis.dm"
+#include "code\datums\diseases\advance\advance.dm"
+#include "code\datums\diseases\advance\presets.dm"
+#include "code\datums\diseases\advance\symptoms\beard.dm"
+#include "code\datums\diseases\advance\symptoms\choking.dm"
+#include "code\datums\diseases\advance\symptoms\confusion.dm"
+#include "code\datums\diseases\advance\symptoms\cough.dm"
+#include "code\datums\diseases\advance\symptoms\damage_converter.dm"
+#include "code\datums\diseases\advance\symptoms\deafness.dm"
+#include "code\datums\diseases\advance\symptoms\dizzy.dm"
+#include "code\datums\diseases\advance\symptoms\fever.dm"
+#include "code\datums\diseases\advance\symptoms\flesh_eating.dm"
+#include "code\datums\diseases\advance\symptoms\hallucigen.dm"
+#include "code\datums\diseases\advance\symptoms\headache.dm"
+#include "code\datums\diseases\advance\symptoms\heal.dm"
+#include "code\datums\diseases\advance\symptoms\itching.dm"
+#include "code\datums\diseases\advance\symptoms\oxygen.dm"
+#include "code\datums\diseases\advance\symptoms\shedding.dm"
+#include "code\datums\diseases\advance\symptoms\shivering.dm"
+#include "code\datums\diseases\advance\symptoms\sneeze.dm"
+#include "code\datums\diseases\advance\symptoms\stimulant.dm"
+#include "code\datums\diseases\advance\symptoms\symptoms.dm"
+#include "code\datums\diseases\advance\symptoms\visionloss.dm"
+#include "code\datums\diseases\advance\symptoms\vitiligo.dm"
+#include "code\datums\diseases\advance\symptoms\voice_change.dm"
+#include "code\datums\diseases\advance\symptoms\vomit.dm"
+#include "code\datums\diseases\advance\symptoms\weight.dm"
+#include "code\datums\diseases\advance\symptoms\youth.dm"
+#include "code\datums\helper_datums\construction_datum.dm"
+#include "code\datums\helper_datums\events.dm"
+#include "code\datums\helper_datums\getrev.dm"
+#include "code\datums\helper_datums\global_iterator.dm"
+#include "code\datums\helper_datums\teleport.dm"
+#include "code\datums\helper_datums\topic_input.dm"
+#include "code\datums\spells\area_teleport.dm"
+#include "code\datums\spells\charge.dm"
+#include "code\datums\spells\conjure.dm"
+#include "code\datums\spells\construct_spells.dm"
+#include "code\datums\spells\dumbfire.dm"
+#include "code\datums\spells\emplosion.dm"
+#include "code\datums\spells\ethereal_jaunt.dm"
+#include "code\datums\spells\explosion.dm"
+#include "code\datums\spells\genetic.dm"
+#include "code\datums\spells\horsemask.dm"
+#include "code\datums\spells\inflict_handler.dm"
+#include "code\datums\spells\knock.dm"
+#include "code\datums\spells\mime.dm"
+#include "code\datums\spells\mind_transfer.dm"
+#include "code\datums\spells\projectile.dm"
+#include "code\datums\spells\trigger.dm"
+#include "code\datums\spells\turf_teleport.dm"
+#include "code\datums\spells\wizard.dm"
+#include "code\datums\wires\airlock.dm"
+#include "code\datums\wires\alarm.dm"
+#include "code\datums\wires\apc.dm"
+#include "code\datums\wires\camera.dm"
+#include "code\datums\wires\explosive.dm"
+#include "code\datums\wires\mulebot.dm"
+#include "code\datums\wires\particle_accelerator.dm"
+#include "code\datums\wires\radio.dm"
+#include "code\datums\wires\robot.dm"
+#include "code\datums\wires\syndicatebomb.dm"
+#include "code\datums\wires\taperecorder.dm"
+#include "code\datums\wires\vending.dm"
+#include "code\datums\wires\wires.dm"
+#include "code\defines\obj.dm"
+#include "code\defines\obj\weapon.dm"
+#include "code\defines\procs\AStar.dm"
+#include "code\defines\procs\captain_announce.dm"
+#include "code\defines\procs\command_alert.dm"
+#include "code\defines\procs\dbcore.dm"
+#include "code\defines\procs\statistics.dm"
+#include "code\FEA\FEA_gas_mixture.dm"
+#include "code\game\asteroid.dm"
+#include "code\game\atoms.dm"
+#include "code\game\atoms_movable.dm"
+#include "code\game\communications.dm"
+#include "code\game\dna.dm"
+#include "code\game\shuttle_engines.dm"
+#include "code\game\skincmd.dm"
+#include "code\game\smoothwall.dm"
+#include "code\game\sound.dm"
+#include "code\game\area\ai_monitored.dm"
+#include "code\game\area\areas.dm"
+#include "code\game\area\Space Station 13 areas.dm"
+#include "code\game\gamemodes\antag_spawner.dm"
+#include "code\game\gamemodes\events.dm"
+#include "code\game\gamemodes\factions.dm"
+#include "code\game\gamemodes\game_mode.dm"
+#include "code\game\gamemodes\gameticker.dm"
+#include "code\game\gamemodes\intercept_report.dm"
+#include "code\game\gamemodes\objective.dm"
+#include "code\game\gamemodes\objective_items.dm"
+#include "code\game\gamemodes\setupgame.dm"
+#include "code\game\gamemodes\blob\blob.dm"
+#include "code\game\gamemodes\blob\blob_finish.dm"
+#include "code\game\gamemodes\blob\blob_report.dm"
+#include "code\game\gamemodes\blob\overmind.dm"
+#include "code\game\gamemodes\blob\powers.dm"
+#include "code\game\gamemodes\blob\theblob.dm"
+#include "code\game\gamemodes\blob\blobs\core.dm"
+#include "code\game\gamemodes\blob\blobs\factory.dm"
+#include "code\game\gamemodes\blob\blobs\node.dm"
+#include "code\game\gamemodes\blob\blobs\resource.dm"
+#include "code\game\gamemodes\blob\blobs\shield.dm"
+#include "code\game\gamemodes\changeling\changeling.dm"
+#include "code\game\gamemodes\changeling\changeling_mutations.dm"
+#include "code\game\gamemodes\changeling\changeling_powers.dm"
+#include "code\game\gamemodes\changeling\modularchangling.dm"
+#include "code\game\gamemodes\changeling\traitor_chan.dm"
+#include "code\game\gamemodes\cult\cult.dm"
+#include "code\game\gamemodes\cult\cult_items.dm"
+#include "code\game\gamemodes\cult\cult_structures.dm"
+#include "code\game\gamemodes\cult\ritual.dm"
+#include "code\game\gamemodes\cult\runes.dm"
+#include "code\game\gamemodes\cult\talisman.dm"
+#include "code\game\gamemodes\extended\extended.dm"
+#include "code\game\gamemodes\malfunction\Malf_Modules.dm"
+#include "code\game\gamemodes\malfunction\malfunction.dm"
+#include "code\game\gamemodes\meteor\meteor.dm"
+#include "code\game\gamemodes\meteor\meteors.dm"
+#include "code\game\gamemodes\nuclear\nuclear.dm"
+#include "code\game\gamemodes\nuclear\nuclearbomb.dm"
+#include "code\game\gamemodes\nuclear\pinpointer.dm"
+#include "code\game\gamemodes\revolution\revolution.dm"
+#include "code\game\gamemodes\sandbox\airlock_maker.dm"
+#include "code\game\gamemodes\sandbox\h_sandbox.dm"
+#include "code\game\gamemodes\sandbox\sandbox.dm"
+#include "code\game\gamemodes\traitor\double_agents.dm"
+#include "code\game\gamemodes\traitor\traitor.dm"
+#include "code\game\gamemodes\wizard\artefact.dm"
+#include "code\game\gamemodes\wizard\rightandwrong.dm"
+#include "code\game\gamemodes\wizard\soulstone.dm"
+#include "code\game\gamemodes\wizard\spellbook.dm"
+#include "code\game\gamemodes\wizard\wizard.dm"
+#include "code\game\jobs\access.dm"
+#include "code\game\jobs\job_controller.dm"
+#include "code\game\jobs\jobprocs.dm"
+#include "code\game\jobs\jobs.dm"
+#include "code\game\jobs\whitelist.dm"
+#include "code\game\jobs\job\assistant.dm"
+#include "code\game\jobs\job\captain.dm"
+#include "code\game\jobs\job\civilian.dm"
+#include "code\game\jobs\job\civilian_chaplain.dm"
+#include "code\game\jobs\job\engineering.dm"
+#include "code\game\jobs\job\job.dm"
+#include "code\game\jobs\job\medical.dm"
+#include "code\game\jobs\job\science.dm"
+#include "code\game\jobs\job\security.dm"
+#include "code\game\jobs\job\silicon.dm"
+#include "code\game\machinery\ai_slipper.dm"
+#include "code\game\machinery\airlock_control.dm"
+#include "code\game\machinery\alarm.dm"
+#include "code\game\machinery\atmo_control.dm"
+#include "code\game\machinery\autolathe.dm"
+#include "code\game\machinery\Beacon.dm"
+#include "code\game\machinery\buttons.dm"
+#include "code\game\machinery\cell_charger.dm"
+#include "code\game\machinery\cloning.dm"
+#include "code\game\machinery\constructable_frame.dm"
+#include "code\game\machinery\cryo.dm"
+#include "code\game\machinery\deployable.dm"
+#include "code\game\machinery\door_control.dm"
+#include "code\game\machinery\doppler_array.dm"
+#include "code\game\machinery\drying_rack.dm"
+#include "code\game\machinery\flasher.dm"
+#include "code\game\machinery\Freezer.dm"
+#include "code\game\machinery\hologram.dm"
+#include "code\game\machinery\igniter.dm"
+#include "code\game\machinery\lightswitch.dm"
+#include "code\game\machinery\machinery.dm"
+#include "code\game\machinery\magnet.dm"
+#include "code\game\machinery\mass_driver.dm"
+#include "code\game\machinery\navbeacon.dm"
+#include "code\game\machinery\newscaster.dm"
+#include "code\game\machinery\overview.dm"
+#include "code\game\machinery\PDApainter.dm"
+#include "code\game\machinery\portable_turret.dm"
+#include "code\game\machinery\recharger.dm"
+#include "code\game\machinery\rechargestation.dm"
+#include "code\game\machinery\recycler.dm"
+#include "code\game\machinery\requests_console.dm"
+#include "code\game\machinery\robot_fabricator.dm"
+#include "code\game\machinery\shieldgen.dm"
+#include "code\game\machinery\Sleeper.dm"
+#include "code\game\machinery\spaceheater.dm"
+#include "code\game\machinery\status_display.dm"
+#include "code\game\machinery\suit_storage_unit.dm"
+#include "code\game\machinery\syndicatebeacon.dm"
+#include "code\game\machinery\syndicatebomb.dm"
+#include "code\game\machinery\teleporter.dm"
+#include "code\game\machinery\transformer.dm"
+#include "code\game\machinery\turrets.dm"
+#include "code\game\machinery\vending.dm"
+#include "code\game\machinery\washing_machine.dm"
+#include "code\game\machinery\wishgranter.dm"
+#include "code\game\machinery\atmoalter\area_atmos_computer.dm"
+#include "code\game\machinery\atmoalter\canister.dm"
+#include "code\game\machinery\atmoalter\meter.dm"
+#include "code\game\machinery\atmoalter\portable_atmospherics.dm"
+#include "code\game\machinery\atmoalter\pump.dm"
+#include "code\game\machinery\atmoalter\scrubber.dm"
+#include "code\game\machinery\atmoalter\zvent.dm"
+#include "code\game\machinery\bots\bots.dm"
+#include "code\game\machinery\bots\cleanbot.dm"
+#include "code\game\machinery\bots\ed209bot.dm"
+#include "code\game\machinery\bots\floorbot.dm"
+#include "code\game\machinery\bots\medbot.dm"
+#include "code\game\machinery\bots\mulebot.dm"
+#include "code\game\machinery\bots\secbot.dm"
+#include "code\game\machinery\camera\camera.dm"
+#include "code\game\machinery\camera\camera_assembly.dm"
+#include "code\game\machinery\camera\motion.dm"
+#include "code\game\machinery\camera\presets.dm"
+#include "code\game\machinery\camera\tracking.dm"
+#include "code\game\machinery\computer\ai_core.dm"
+#include "code\game\machinery\computer\aifixer.dm"
+#include "code\game\machinery\computer\arcade.dm"
+#include "code\game\machinery\computer\atmos_alert.dm"
+#include "code\game\machinery\computer\buildandrepair.dm"
+#include "code\game\machinery\computer\camera.dm"
+#include "code\game\machinery\computer\card.dm"
+#include "code\game\machinery\computer\cloning.dm"
+#include "code\game\machinery\computer\communications.dm"
+#include "code\game\machinery\computer\computer.dm"
+#include "code\game\machinery\computer\crew.dm"
+#include "code\game\machinery\computer\HolodeckControl.dm"
+#include "code\game\machinery\computer\law.dm"
+#include "code\game\machinery\computer\medical.dm"
+#include "code\game\machinery\computer\message.dm"
+#include "code\game\machinery\computer\Operating.dm"
+#include "code\game\machinery\computer\pod.dm"
+#include "code\game\machinery\computer\power.dm"
+#include "code\game\machinery\computer\prisoner.dm"
+#include "code\game\machinery\computer\robot.dm"
+#include "code\game\machinery\computer\security.dm"
+#include "code\game\machinery\computer\shuttle.dm"
+#include "code\game\machinery\computer\station_alert.dm"
+#include "code\game\machinery\computer\syndicate_shuttle.dm"
+#include "code\game\machinery\computer\telecrystalconsoles.dm"
+#include "code\game\machinery\doors\airlock.dm"
+#include "code\game\machinery\doors\airlock_electronics.dm"
+#include "code\game\machinery\doors\alarmlock.dm"
+#include "code\game\machinery\doors\brigdoors.dm"
+#include "code\game\machinery\doors\checkForMultipleDoors.dm"
+#include "code\game\machinery\doors\door.dm"
+#include "code\game\machinery\doors\firedoor.dm"
+#include "code\game\machinery\doors\poddoor.dm"
+#include "code\game\machinery\doors\shutters.dm"
+#include "code\game\machinery\doors\unpowered.dm"
+#include "code\game\machinery\doors\windowdoor.dm"
+#include "code\game\machinery\embedded_controller\access_controller.dm"
+#include "code\game\machinery\embedded_controller\airlock_controller.dm"
+#include "code\game\machinery\embedded_controller\embedded_controller_base.dm"
+#include "code\game\machinery\embedded_controller\simple_vent_controller.dm"
+#include "code\game\machinery\kitchen\gibber.dm"
+#include "code\game\machinery\kitchen\icecream_vat.dm"
+#include "code\game\machinery\kitchen\juicer.dm"
+#include "code\game\machinery\kitchen\microwave.dm"
+#include "code\game\machinery\kitchen\monkeyrecycler.dm"
+#include "code\game\machinery\kitchen\processor.dm"
+#include "code\game\machinery\kitchen\smartfridge.dm"
+#include "code\game\machinery\pipe\construction.dm"
+#include "code\game\machinery\pipe\pipe_dispenser.dm"
+#include "code\game\machinery\telecomms\broadcaster.dm"
+#include "code\game\machinery\telecomms\logbrowser.dm"
+#include "code\game\machinery\telecomms\machine_interactions.dm"
+#include "code\game\machinery\telecomms\presets.dm"
+#include "code\game\machinery\telecomms\telecomunications.dm"
+#include "code\game\machinery\telecomms\telemonitor.dm"
+#include "code\game\machinery\telecomms\traffic_control.dm"
+#include "code\game\mecha\mech_bay.dm"
+#include "code\game\mecha\mech_fabricator.dm"
+#include "code\game\mecha\mecha.dm"
+#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_wreckage.dm"
+#include "code\game\mecha\combat\combat.dm"
+#include "code\game\mecha\combat\durand.dm"
+#include "code\game\mecha\combat\gygax.dm"
+#include "code\game\mecha\combat\honker.dm"
+#include "code\game\mecha\combat\marauder.dm"
+#include "code\game\mecha\combat\phazon.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\weapons\weapons.dm"
+#include "code\game\mecha\medical\medical.dm"
+#include "code\game\mecha\medical\odysseus.dm"
+#include "code\game\mecha\working\ripley.dm"
+#include "code\game\mecha\working\working.dm"
+#include "code\game\objects\empulse.dm"
+#include "code\game\objects\explosion.dm"
+#include "code\game\objects\explosion_recursive.dm"
+#include "code\game\objects\items.dm"
+#include "code\game\objects\objs.dm"
+#include "code\game\objects\structures.dm"
+#include "code\game\objects\weapons.dm"
+#include "code\game\objects\effects\aliens.dm"
+#include "code\game\objects\effects\anomalies.dm"
+#include "code\game\objects\effects\bump_teleporter.dm"
+#include "code\game\objects\effects\effect_system.dm"
+#include "code\game\objects\effects\forcefields.dm"
+#include "code\game\objects\effects\gibs.dm"
+#include "code\game\objects\effects\glowshroom.dm"
+#include "code\game\objects\effects\landmarks.dm"
+#include "code\game\objects\effects\manifest.dm"
+#include "code\game\objects\effects\mines.dm"
+#include "code\game\objects\effects\misc.dm"
+#include "code\game\objects\effects\overlays.dm"
+#include "code\game\objects\effects\portals.dm"
+#include "code\game\objects\effects\spiders.dm"
+#include "code\game\objects\effects\step_triggers.dm"
+#include "code\game\objects\effects\decals\cleanable.dm"
+#include "code\game\objects\effects\decals\contraband.dm"
+#include "code\game\objects\effects\decals\crayon.dm"
+#include "code\game\objects\effects\decals\decal.dm"
+#include "code\game\objects\effects\decals\misc.dm"
+#include "code\game\objects\effects\decals\remains.dm"
+#include "code\game\objects\effects\decals\Cleanable\aliens.dm"
+#include "code\game\objects\effects\decals\Cleanable\humans.dm"
+#include "code\game\objects\effects\decals\Cleanable\misc.dm"
+#include "code\game\objects\effects\decals\Cleanable\robots.dm"
+#include "code\game\objects\effects\spawners\bombspawner.dm"
+#include "code\game\objects\effects\spawners\gibspawner.dm"
+#include "code\game\objects\effects\spawners\vaultspawner.dm"
+#include "code\game\objects\items\apc_frame.dm"
+#include "code\game\objects\items\blueprints.dm"
+#include "code\game\objects\items\bodybag.dm"
+#include "code\game\objects\items\candle.dm"
+#include "code\game\objects\items\crayons.dm"
+#include "code\game\objects\items\latexballoon.dm"
+#include "code\game\objects\items\shooting_range.dm"
+#include "code\game\objects\items\toys.dm"
+#include "code\game\objects\items\trash.dm"
+#include "code\game\objects\items\devices\aicard.dm"
+#include "code\game\objects\items\devices\camera_bug.dm"
+#include "code\game\objects\items\devices\chameleonproj.dm"
+#include "code\game\objects\items\devices\flash.dm"
+#include "code\game\objects\items\devices\flashlight.dm"
+#include "code\game\objects\items\devices\laserpointer.dm"
+#include "code\game\objects\items\devices\lightreplacer.dm"
+#include "code\game\objects\items\devices\multitool.dm"
+#include "code\game\objects\items\devices\paicard.dm"
+#include "code\game\objects\items\devices\powersink.dm"
+#include "code\game\objects\items\devices\scanners.dm"
+#include "code\game\objects\items\devices\taperecorder.dm"
+#include "code\game\objects\items\devices\traitordevices.dm"
+#include "code\game\objects\items\devices\transfer_valve.dm"
+#include "code\game\objects\items\devices\uplinks.dm"
+#include "code\game\objects\items\devices\violin.dm"
+#include "code\game\objects\items\devices\PDA\cart.dm"
+#include "code\game\objects\items\devices\PDA\chatroom.dm"
+#include "code\game\objects\items\devices\PDA\PDA.dm"
+#include "code\game\objects\items\devices\PDA\radio.dm"
+#include "code\game\objects\items\devices\radio\beacon.dm"
+#include "code\game\objects\items\devices\radio\electropack.dm"
+#include "code\game\objects\items\devices\radio\encryptionkey.dm"
+#include "code\game\objects\items\devices\radio\headset.dm"
+#include "code\game\objects\items\devices\radio\intercom.dm"
+#include "code\game\objects\items\devices\radio\radio.dm"
+#include "code\game\objects\items\robot\robot_items.dm"
+#include "code\game\objects\items\robot\robot_parts.dm"
+#include "code\game\objects\items\robot\robot_upgrades.dm"
+#include "code\game\objects\items\stacks\medical.dm"
+#include "code\game\objects\items\stacks\rods.dm"
+#include "code\game\objects\items\stacks\stack.dm"
+#include "code\game\objects\items\stacks\sheets\glass.dm"
+#include "code\game\objects\items\stacks\sheets\leather.dm"
+#include "code\game\objects\items\stacks\sheets\light.dm"
+#include "code\game\objects\items\stacks\sheets\mineral.dm"
+#include "code\game\objects\items\stacks\sheets\sheet_types.dm"
+#include "code\game\objects\items\stacks\sheets\sheets.dm"
+#include "code\game\objects\items\stacks\tiles\light.dm"
+#include "code\game\objects\items\stacks\tiles\plasteel.dm"
+#include "code\game\objects\items\stacks\tiles\tile_types.dm"
+#include "code\game\objects\items\weapons\AI_modules.dm"
+#include "code\game\objects\items\weapons\airlock_painter.dm"
+#include "code\game\objects\items\weapons\cards_ids.dm"
+#include "code\game\objects\items\weapons\cigs_lighters.dm"
+#include "code\game\objects\items\weapons\clown_items.dm"
+#include "code\game\objects\items\weapons\cosmetics.dm"
+#include "code\game\objects\items\weapons\dice.dm"
+#include "code\game\objects\items\weapons\dna_injector.dm"
+#include "code\game\objects\items\weapons\explosives.dm"
+#include "code\game\objects\items\weapons\extinguisher.dm"
+#include "code\game\objects\items\weapons\flamethrower.dm"
+#include "code\game\objects\items\weapons\gift_wrappaper.dm"
+#include "code\game\objects\items\weapons\handcuffs.dm"
+#include "code\game\objects\items\weapons\kitchen.dm"
+#include "code\game\objects\items\weapons\manuals.dm"
+#include "code\game\objects\items\weapons\mop.dm"
+#include "code\game\objects\items\weapons\paint.dm"
+#include "code\game\objects\items\weapons\paiwire.dm"
+#include "code\game\objects\items\weapons\power_cells.dm"
+#include "code\game\objects\items\weapons\RCD.dm"
+#include "code\game\objects\items\weapons\RSF.dm"
+#include "code\game\objects\items\weapons\scrolls.dm"
+#include "code\game\objects\items\weapons\shields.dm"
+#include "code\game\objects\items\weapons\singularityhammer.dm"
+#include "code\game\objects\items\weapons\stunbaton.dm"
+#include "code\game\objects\items\weapons\table_rack_parts.dm"
+#include "code\game\objects\items\weapons\teleportation.dm"
+#include "code\game\objects\items\weapons\tools.dm"
+#include "code\game\objects\items\weapons\twohanded.dm"
+#include "code\game\objects\items\weapons\vending_items.dm"
+#include "code\game\objects\items\weapons\weaponry.dm"
+#include "code\game\objects\items\weapons\grenades\chem_grenade.dm"
+#include "code\game\objects\items\weapons\grenades\emgrenade.dm"
+#include "code\game\objects\items\weapons\grenades\flashbang.dm"
+#include "code\game\objects\items\weapons\grenades\ghettobomb.dm"
+#include "code\game\objects\items\weapons\grenades\grenade.dm"
+#include "code\game\objects\items\weapons\grenades\smokebomb.dm"
+#include "code\game\objects\items\weapons\grenades\spawnergrenade.dm"
+#include "code\game\objects\items\weapons\grenades\syndieminibomb.dm"
+#include "code\game\objects\items\weapons\implants\implant.dm"
+#include "code\game\objects\items\weapons\implants\implantcase.dm"
+#include "code\game\objects\items\weapons\implants\implantchair.dm"
+#include "code\game\objects\items\weapons\implants\implanter.dm"
+#include "code\game\objects\items\weapons\implants\implantfreedom.dm"
+#include "code\game\objects\items\weapons\implants\implantpad.dm"
+#include "code\game\objects\items\weapons\implants\implantuplink.dm"
+#include "code\game\objects\items\weapons\melee\energy.dm"
+#include "code\game\objects\items\weapons\melee\misc.dm"
+#include "code\game\objects\items\weapons\storage\backpack.dm"
+#include "code\game\objects\items\weapons\storage\bags.dm"
+#include "code\game\objects\items\weapons\storage\belt.dm"
+#include "code\game\objects\items\weapons\storage\bible.dm"
+#include "code\game\objects\items\weapons\storage\boxes.dm"
+#include "code\game\objects\items\weapons\storage\briefcase.dm"
+#include "code\game\objects\items\weapons\storage\fancy.dm"
+#include "code\game\objects\items\weapons\storage\firstaid.dm"
+#include "code\game\objects\items\weapons\storage\lockbox.dm"
+#include "code\game\objects\items\weapons\storage\secure.dm"
+#include "code\game\objects\items\weapons\storage\storage.dm"
+#include "code\game\objects\items\weapons\storage\toolbox.dm"
+#include "code\game\objects\items\weapons\storage\uplink_kits.dm"
+#include "code\game\objects\items\weapons\storage\wallets.dm"
+#include "code\game\objects\items\weapons\tanks\jetpack.dm"
+#include "code\game\objects\items\weapons\tanks\tank_types.dm"
+#include "code\game\objects\items\weapons\tanks\tanks.dm"
+#include "code\game\objects\items\weapons\tanks\watertank.dm"
+#include "code\game\objects\structures\bedsheet_bin.dm"
+#include "code\game\objects\structures\displaycase.dm"
+#include "code\game\objects\structures\door_assembly.dm"
+#include "code\game\objects\structures\dresser.dm"
+#include "code\game\objects\structures\electricchair.dm"
+#include "code\game\objects\structures\extinguisher.dm"
+#include "code\game\objects\structures\false_walls.dm"
+#include "code\game\objects\structures\flora.dm"
+#include "code\game\objects\structures\girders.dm"
+#include "code\game\objects\structures\grille.dm"
+#include "code\game\objects\structures\janicart.dm"
+#include "code\game\objects\structures\kitchen_spike.dm"
+#include "code\game\objects\structures\ladders.dm"
+#include "code\game\objects\structures\lamarr_cage.dm"
+#include "code\game\objects\structures\lattice.dm"
+#include "code\game\objects\structures\mineral_doors.dm"
+#include "code\game\objects\structures\mirror.dm"
+#include "code\game\objects\structures\mop_bucket.dm"
+#include "code\game\objects\structures\morgue.dm"
+#include "code\game\objects\structures\musician.dm"
+#include "code\game\objects\structures\noticeboard.dm"
+#include "code\game\objects\structures\OpTable.dm"
+#include "code\game\objects\structures\safe.dm"
+#include "code\game\objects\structures\signs.dm"
+#include "code\game\objects\structures\tables_racks.dm"
+#include "code\game\objects\structures\tank_dispenser.dm"
+#include "code\game\objects\structures\target_stake.dm"
+#include "code\game\objects\structures\transit_tubes.dm"
+#include "code\game\objects\structures\watercloset.dm"
+#include "code\game\objects\structures\windoor_assembly.dm"
+#include "code\game\objects\structures\window.dm"
+#include "code\game\objects\structures\crates_lockers\bins.dm"
+#include "code\game\objects\structures\crates_lockers\closets.dm"
+#include "code\game\objects\structures\crates_lockers\crates.dm"
+#include "code\game\objects\structures\crates_lockers\largecrate.dm"
+#include "code\game\objects\structures\crates_lockers\closets\coffin.dm"
+#include "code\game\objects\structures\crates_lockers\closets\crittercrate.dm"
+#include "code\game\objects\structures\crates_lockers\closets\fireaxe.dm"
+#include "code\game\objects\structures\crates_lockers\closets\fitness.dm"
+#include "code\game\objects\structures\crates_lockers\closets\gimmick.dm"
+#include "code\game\objects\structures\crates_lockers\closets\job_closets.dm"
+#include "code\game\objects\structures\crates_lockers\closets\l3closet.dm"
+#include "code\game\objects\structures\crates_lockers\closets\malfunction.dm"
+#include "code\game\objects\structures\crates_lockers\closets\statue.dm"
+#include "code\game\objects\structures\crates_lockers\closets\syndicate.dm"
+#include "code\game\objects\structures\crates_lockers\closets\utility_closets.dm"
+#include "code\game\objects\structures\crates_lockers\closets\wardrobe.dm"
+#include "code\game\objects\structures\crates_lockers\closets\secure\bar.dm"
+#include "code\game\objects\structures\crates_lockers\closets\secure\cargo.dm"
+#include "code\game\objects\structures\crates_lockers\closets\secure\engineering.dm"
+#include "code\game\objects\structures\crates_lockers\closets\secure\freezer.dm"
+#include "code\game\objects\structures\crates_lockers\closets\secure\hydroponics.dm"
+#include "code\game\objects\structures\crates_lockers\closets\secure\medical.dm"
+#include "code\game\objects\structures\crates_lockers\closets\secure\personal.dm"
+#include "code\game\objects\structures\crates_lockers\closets\secure\scientist.dm"
+#include "code\game\objects\structures\crates_lockers\closets\secure\secure_closets.dm"
+#include "code\game\objects\structures\crates_lockers\closets\secure\security.dm"
+#include "code\game\objects\structures\stool_bed_chair_nest\alien_nests.dm"
+#include "code\game\objects\structures\stool_bed_chair_nest\bed.dm"
+#include "code\game\objects\structures\stool_bed_chair_nest\chairs.dm"
+#include "code\game\objects\structures\stool_bed_chair_nest\stools.dm"
+#include "code\game\turfs\simulated.dm"
+#include "code\game\turfs\turf.dm"
+#include "code\game\turfs\unsimulated.dm"
+#include "code\game\turfs\simulated\dirtystation.dm"
+#include "code\game\turfs\simulated\floor.dm"
+#include "code\game\turfs\simulated\floor_types.dm"
+#include "code\game\turfs\simulated\walls.dm"
+#include "code\game\turfs\simulated\walls_mineral.dm"
+#include "code\game\turfs\simulated\walls_misc.dm"
+#include "code\game\turfs\simulated\walls_reinforced.dm"
+#include "code\game\turfs\space\space.dm"
+#include "code\game\turfs\space\transit.dm"
+#include "code\game\turfs\unsimulated\beach.dm"
+#include "code\game\turfs\unsimulated\floor.dm"
+#include "code\game\turfs\unsimulated\walls.dm"
+#include "code\game\verbs\atom_verbs.dm"
+#include "code\game\verbs\ooc.dm"
+#include "code\game\verbs\suicide.dm"
+#include "code\game\verbs\who.dm"
+#include "code\js\byjax.dm"
+#include "code\js\menus.dm"
+#include "code\LINDA\LINDA_fire.dm"
+#include "code\LINDA\LINDA_system.dm"
+#include "code\LINDA\LINDA_turf_tile.dm"
+#include "code\modules\admin\admin.dm"
+#include "code\modules\admin\admin_investigate.dm"
+#include "code\modules\admin\admin_memo.dm"
+#include "code\modules\admin\admin_ranks.dm"
+#include "code\modules\admin\admin_verbs.dm"
+#include "code\modules\admin\banappearance.dm"
+#include "code\modules\admin\banjob.dm"
+#include "code\modules\admin\create_mob.dm"
+#include "code\modules\admin\create_object.dm"
+#include "code\modules\admin\create_turf.dm"
+#include "code\modules\admin\holder2.dm"
+#include "code\modules\admin\IsBanned.dm"
+#include "code\modules\admin\NewBan.dm"
+#include "code\modules\admin\newbanjob.dm"
+#include "code\modules\admin\player_notes.dm"
+#include "code\modules\admin\player_panel.dm"
+#include "code\modules\admin\topic.dm"
+#include "code\modules\admin\DB ban\functions.dm"
+#include "code\modules\admin\permissionverbs\permissionedit.dm"
+#include "code\modules\admin\verbs\adminhelp.dm"
+#include "code\modules\admin\verbs\adminjump.dm"
+#include "code\modules\admin\verbs\adminpm.dm"
+#include "code\modules\admin\verbs\adminsay.dm"
+#include "code\modules\admin\verbs\atmosdebug.dm"
+#include "code\modules\admin\verbs\BrokenInhands.dm"
+#include "code\modules\admin\verbs\cinematic.dm"
+#include "code\modules\admin\verbs\deadsay.dm"
+#include "code\modules\admin\verbs\debug.dm"
+#include "code\modules\admin\verbs\diagnostics.dm"
+#include "code\modules\admin\verbs\getlogs.dm"
+#include "code\modules\admin\verbs\mapping.dm"
+#include "code\modules\admin\verbs\massmodvar.dm"
+#include "code\modules\admin\verbs\modifyvariables.dm"
+#include "code\modules\admin\verbs\one_click_antag.dm"
+#include "code\modules\admin\verbs\onlyone.dm"
+#include "code\modules\admin\verbs\playsound.dm"
+#include "code\modules\admin\verbs\possess.dm"
+#include "code\modules\admin\verbs\pray.dm"
+#include "code\modules\admin\verbs\randomverbs.dm"
+#include "code\modules\admin\verbs\ticklag.dm"
+#include "code\modules\admin\verbs\tripAI.dm"
+#include "code\modules\assembly\assembly.dm"
+#include "code\modules\assembly\bomb.dm"
+#include "code\modules\assembly\helpers.dm"
+#include "code\modules\assembly\holder.dm"
+#include "code\modules\assembly\igniter.dm"
+#include "code\modules\assembly\infrared.dm"
+#include "code\modules\assembly\mousetrap.dm"
+#include "code\modules\assembly\proximity.dm"
+#include "code\modules\assembly\shock_kit.dm"
+#include "code\modules\assembly\signaler.dm"
+#include "code\modules\assembly\timer.dm"
+#include "code\modules\assembly\voice.dm"
+#include "code\modules\awaymissions\bluespaceartillery.dm"
+#include "code\modules\awaymissions\corpse.dm"
+#include "code\modules\awaymissions\exile.dm"
+#include "code\modules\awaymissions\gateway.dm"
+#include "code\modules\awaymissions\loot.dm"
+#include "code\modules\awaymissions\pamphlet.dm"
+#include "code\modules\awaymissions\trigger.dm"
+#include "code\modules\awaymissions\zlevel.dm"
+#include "code\modules\awaymissions\maploader\dmm_suite.dm"
+#include "code\modules\awaymissions\maploader\reader.dm"
+#include "code\modules\awaymissions\maploader\swapmaps.dm"
+#include "code\modules\awaymissions\maploader\writer.dm"
+#include "code\modules\awaymissions\mission_code\Academy.dm"
+#include "code\modules\awaymissions\mission_code\blackmarketpackers.dm"
+#include "code\modules\awaymissions\mission_code\box2550Away.dm"
+#include "code\modules\awaymissions\mission_code\centcomAway.dm"
+#include "code\modules\awaymissions\mission_code\challenge.dm"
+#include "code\modules\awaymissions\mission_code\spacebattle.dm"
+#include "code\modules\awaymissions\mission_code\stationCollision.dm"
+#include "code\modules\awaymissions\mission_code\wildwest.dm"
+#include "code\modules\client\client defines.dm"
+#include "code\modules\client\client procs.dm"
+#include "code\modules\client\preferences.dm"
+#include "code\modules\client\preferences_savefile.dm"
+#include "code\modules\client\preferences_toggles.dm"
+#include "code\modules\clothing\clothing.dm"
+#include "code\modules\clothing\glasses\glasses.dm"
+#include "code\modules\clothing\glasses\hud.dm"
+#include "code\modules\clothing\gloves\boxing.dm"
+#include "code\modules\clothing\gloves\color.dm"
+#include "code\modules\clothing\gloves\miscellaneous.dm"
+#include "code\modules\clothing\gloves\ninja.dm"
+#include "code\modules\clothing\head\collectable.dm"
+#include "code\modules\clothing\head\hardhat.dm"
+#include "code\modules\clothing\head\helmet.dm"
+#include "code\modules\clothing\head\jobs.dm"
+#include "code\modules\clothing\head\misc.dm"
+#include "code\modules\clothing\head\misc_special.dm"
+#include "code\modules\clothing\head\soft_caps.dm"
+#include "code\modules\clothing\masks\boxing.dm"
+#include "code\modules\clothing\masks\breath.dm"
+#include "code\modules\clothing\masks\gasmask.dm"
+#include "code\modules\clothing\masks\miscellaneous.dm"
+#include "code\modules\clothing\shoes\colour.dm"
+#include "code\modules\clothing\shoes\magboots.dm"
+#include "code\modules\clothing\shoes\miscellaneous.dm"
+#include "code\modules\clothing\spacesuits\miscellaneous.dm"
+#include "code\modules\clothing\spacesuits\ninja.dm"
+#include "code\modules\clothing\spacesuits\rig.dm"
+#include "code\modules\clothing\spacesuits\syndi.dm"
+#include "code\modules\clothing\suits\armor.dm"
+#include "code\modules\clothing\suits\bio.dm"
+#include "code\modules\clothing\suits\jobs.dm"
+#include "code\modules\clothing\suits\labcoat.dm"
+#include "code\modules\clothing\suits\miscellaneous.dm"
+#include "code\modules\clothing\suits\utility.dm"
+#include "code\modules\clothing\suits\wiz_robe.dm"
+#include "code\modules\clothing\under\chameleon.dm"
+#include "code\modules\clothing\under\color.dm"
+#include "code\modules\clothing\under\miscellaneous.dm"
+#include "code\modules\clothing\under\shorts.dm"
+#include "code\modules\clothing\under\syndicate.dm"
+#include "code\modules\clothing\under\ties.dm"
+#include "code\modules\clothing\under\jobs\civilian.dm"
+#include "code\modules\clothing\under\jobs\engineering.dm"
+#include "code\modules\clothing\under\jobs\medsci.dm"
+#include "code\modules\clothing\under\jobs\security.dm"
+#include "code\modules\detectivework\detective_work.dm"
+#include "code\modules\detectivework\evidence.dm"
+#include "code\modules\detectivework\footprints_and_rag.dm"
+#include "code\modules\detectivework\scanner.dm"
+#include "code\modules\events\alien_infestation.dm"
+#include "code\modules\events\anomaly.dm"
+#include "code\modules\events\anomaly_bluespace.dm"
+#include "code\modules\events\anomaly_flux.dm"
+#include "code\modules\events\anomaly_grav.dm"
+#include "code\modules\events\anomaly_pyro.dm"
+#include "code\modules\events\anomaly_vortex.dm"
+#include "code\modules\events\blob.dm"
+#include "code\modules\events\brand_intelligence.dm"
+#include "code\modules\events\carp_migration.dm"
+#include "code\modules\events\communications_blackout.dm"
+#include "code\modules\events\disease_outbreak.dm"
+#include "code\modules\events\dust.dm"
+#include "code\modules\events\electrical_storm.dm"
+#include "code\modules\events\event.dm"
+#include "code\modules\events\event_manager.dm"
+#include "code\modules\events\false_alarm.dm"
+#include "code\modules\events\immovable_rod.dm"
+#include "code\modules\events\ion_storm.dm"
+#include "code\modules\events\mass_hallucination.dm"
+#include "code\modules\events\meteor_wave.dm"
+#include "code\modules\events\ninja.dm"
+#include "code\modules\events\prison_break.dm"
+#include "code\modules\events\radiation_storm.dm"
+#include "code\modules\events\shuttle_loan.dm"
+#include "code\modules\events\spacevine.dm"
+#include "code\modules\events\spider_infestation.dm"
+#include "code\modules\events\spontaneous_appendicitis.dm"
+#include "code\modules\events\vent_clog.dm"
+#include "code\modules\events\wormholes.dm"
+#include "code\modules\events\holiday\halloween.dm"
+#include "code\modules\events\holiday\xmas.dm"
+#include "code\modules\flufftext\Dreaming.dm"
+#include "code\modules\flufftext\Hallucination.dm"
+#include "code\modules\flufftext\TextFilters.dm"
+#include "code\modules\food\recipes_microwave.dm"
+#include "code\modules\hydroponics\biogenerator.dm"
+#include "code\modules\hydroponics\grown.dm"
+#include "code\modules\hydroponics\growninedible.dm"
+#include "code\modules\hydroponics\hydroitemcode.dm"
+#include "code\modules\hydroponics\hydroitemdefines.dm"
+#include "code\modules\hydroponics\hydroponics.dm"
+#include "code\modules\hydroponics\seed_extractor.dm"
+#include "code\modules\hydroponics\seeds.dm"
+#include "code\modules\library\lib_items.dm"
+#include "code\modules\library\lib_machines.dm"
+#include "code\modules\library\lib_readme.dm"
+#include "code\modules\mining\machine_input_output_plates.dm"
+#include "code\modules\mining\machine_processing.dm"
+#include "code\modules\mining\machine_stacking.dm"
+#include "code\modules\mining\machine_unloading.dm"
+#include "code\modules\mining\mine_areas.dm"
+#include "code\modules\mining\mine_items.dm"
+#include "code\modules\mining\mine_turfs.dm"
+#include "code\modules\mining\mint.dm"
+#include "code\modules\mining\money_bag.dm"
+#include "code\modules\mining\ores_coins.dm"
+#include "code\modules\mining\satchel_ore_boxdm.dm"
+#include "code\modules\mining\laborcamp\laborminerals.dm"
+#include "code\modules\mining\laborcamp\laborshuttle.dm"
+#include "code\modules\mining\laborcamp\laborstacker.dm"
+#include "code\modules\mob\death.dm"
+#include "code\modules\mob\inventory.dm"
+#include "code\modules\mob\login.dm"
+#include "code\modules\mob\logout.dm"
+#include "code\modules\mob\mob.dm"
+#include "code\modules\mob\mob_cleanup.dm"
+#include "code\modules\mob\mob_defines.dm"
+#include "code\modules\mob\mob_grab.dm"
+#include "code\modules\mob\mob_helpers.dm"
+#include "code\modules\mob\mob_movement.dm"
+#include "code\modules\mob\mob_transformation_simple.dm"
+#include "code\modules\mob\say.dm"
+#include "code\modules\mob\transform_procs.dm"
+#include "code\modules\mob\update_icons.dm"
+#include "code\modules\mob\camera\camera.dm"
+#include "code\modules\mob\dead\death.dm"
+#include "code\modules\mob\dead\observer\login.dm"
+#include "code\modules\mob\dead\observer\logout.dm"
+#include "code\modules\mob\dead\observer\observer.dm"
+#include "code\modules\mob\dead\observer\say.dm"
+#include "code\modules\mob\living\damage_procs.dm"
+#include "code\modules\mob\living\death.dm"
+#include "code\modules\mob\living\emote.dm"
+#include "code\modules\mob\living\living.dm"
+#include "code\modules\mob\living\living_defense.dm"
+#include "code\modules\mob\living\living_defines.dm"
+#include "code\modules\mob\living\login.dm"
+#include "code\modules\mob\living\logout.dm"
+#include "code\modules\mob\living\say.dm"
+#include "code\modules\mob\living\carbon\carbon.dm"
+#include "code\modules\mob\living\carbon\carbon_defense.dm"
+#include "code\modules\mob\living\carbon\carbon_defines.dm"
+#include "code\modules\mob\living\carbon\emote.dm"
+#include "code\modules\mob\living\carbon\inventory.dm"
+#include "code\modules\mob\living\carbon\update_icons.dm"
+#include "code\modules\mob\living\carbon\alien\alien.dm"
+#include "code\modules\mob\living\carbon\alien\alien_defense.dm"
+#include "code\modules\mob\living\carbon\alien\death.dm"
+#include "code\modules\mob\living\carbon\alien\login.dm"
+#include "code\modules\mob\living\carbon\alien\logout.dm"
+#include "code\modules\mob\living\carbon\alien\powers.dm"
+#include "code\modules\mob\living\carbon\alien\say.dm"
+#include "code\modules\mob\living\carbon\alien\screen.dm"
+#include "code\modules\mob\living\carbon\alien\humanoid\alien_powers.dm"
+#include "code\modules\mob\living\carbon\alien\humanoid\death.dm"
+#include "code\modules\mob\living\carbon\alien\humanoid\emote.dm"
+#include "code\modules\mob\living\carbon\alien\humanoid\humanoid.dm"
+#include "code\modules\mob\living\carbon\alien\humanoid\inventory.dm"
+#include "code\modules\mob\living\carbon\alien\humanoid\life.dm"
+#include "code\modules\mob\living\carbon\alien\humanoid\login.dm"
+#include "code\modules\mob\living\carbon\alien\humanoid\queen.dm"
+#include "code\modules\mob\living\carbon\alien\humanoid\update_icons.dm"
+#include "code\modules\mob\living\carbon\alien\humanoid\caste\drone.dm"
+#include "code\modules\mob\living\carbon\alien\humanoid\caste\hunter.dm"
+#include "code\modules\mob\living\carbon\alien\humanoid\caste\sentinel.dm"
+#include "code\modules\mob\living\carbon\alien\larva\death.dm"
+#include "code\modules\mob\living\carbon\alien\larva\emote.dm"
+#include "code\modules\mob\living\carbon\alien\larva\inventory.dm"
+#include "code\modules\mob\living\carbon\alien\larva\larva.dm"
+#include "code\modules\mob\living\carbon\alien\larva\life.dm"
+#include "code\modules\mob\living\carbon\alien\larva\powers.dm"
+#include "code\modules\mob\living\carbon\alien\larva\update_icons.dm"
+#include "code\modules\mob\living\carbon\alien\special\alien_embryo.dm"
+#include "code\modules\mob\living\carbon\alien\special\facehugger.dm"
+#include "code\modules\mob\living\carbon\brain\brain.dm"
+#include "code\modules\mob\living\carbon\brain\brain_item.dm"
+#include "code\modules\mob\living\carbon\brain\death.dm"
+#include "code\modules\mob\living\carbon\brain\emote.dm"
+#include "code\modules\mob\living\carbon\brain\life.dm"
+#include "code\modules\mob\living\carbon\brain\MMI.dm"
+#include "code\modules\mob\living\carbon\brain\say.dm"
+#include "code\modules\mob\living\carbon\human\death.dm"
+#include "code\modules\mob\living\carbon\human\emote.dm"
+#include "code\modules\mob\living\carbon\human\examine.dm"
+#include "code\modules\mob\living\carbon\human\human.dm"
+#include "code\modules\mob\living\carbon\human\human_attackalien.dm"
+#include "code\modules\mob\living\carbon\human\human_attackhand.dm"
+#include "code\modules\mob\living\carbon\human\human_attackpaw.dm"
+#include "code\modules\mob\living\carbon\human\human_damage.dm"
+#include "code\modules\mob\living\carbon\human\human_defense.dm"
+#include "code\modules\mob\living\carbon\human\human_defines.dm"
+#include "code\modules\mob\living\carbon\human\human_helpers.dm"
+#include "code\modules\mob\living\carbon\human\human_movement.dm"
+#include "code\modules\mob\living\carbon\human\inventory.dm"
+#include "code\modules\mob\living\carbon\human\life.dm"
+#include "code\modules\mob\living\carbon\human\login.dm"
+#include "code\modules\mob\living\carbon\human\say.dm"
+#include "code\modules\mob\living\carbon\human\update_icons.dm"
+#include "code\modules\mob\living\carbon\human\whisper.dm"
+#include "code\modules\mob\living\carbon\metroid\death.dm"
+#include "code\modules\mob\living\carbon\metroid\emote.dm"
+#include "code\modules\mob\living\carbon\metroid\examine.dm"
+#include "code\modules\mob\living\carbon\metroid\hud.dm"
+#include "code\modules\mob\living\carbon\metroid\life.dm"
+#include "code\modules\mob\living\carbon\metroid\login.dm"
+#include "code\modules\mob\living\carbon\metroid\metroid.dm"
+#include "code\modules\mob\living\carbon\metroid\powers.dm"
+#include "code\modules\mob\living\carbon\metroid\say.dm"
+#include "code\modules\mob\living\carbon\metroid\subtypes.dm"
+#include "code\modules\mob\living\carbon\metroid\update_icons.dm"
+#include "code\modules\mob\living\carbon\monkey\death.dm"
+#include "code\modules\mob\living\carbon\monkey\emote.dm"
+#include "code\modules\mob\living\carbon\monkey\examine.dm"
+#include "code\modules\mob\living\carbon\monkey\inventory.dm"
+#include "code\modules\mob\living\carbon\monkey\life.dm"
+#include "code\modules\mob\living\carbon\monkey\login.dm"
+#include "code\modules\mob\living\carbon\monkey\monkey.dm"
+#include "code\modules\mob\living\carbon\monkey\powers.dm"
+#include "code\modules\mob\living\carbon\monkey\say.dm"
+#include "code\modules\mob\living\carbon\monkey\update_icons.dm"
+#include "code\modules\mob\living\silicon\death.dm"
+#include "code\modules\mob\living\silicon\laws.dm"
+#include "code\modules\mob\living\silicon\login.dm"
+#include "code\modules\mob\living\silicon\say.dm"
+#include "code\modules\mob\living\silicon\silicon.dm"
+#include "code\modules\mob\living\silicon\ai\ai.dm"
+#include "code\modules\mob\living\silicon\ai\death.dm"
+#include "code\modules\mob\living\silicon\ai\examine.dm"
+#include "code\modules\mob\living\silicon\ai\laws.dm"
+#include "code\modules\mob\living\silicon\ai\life.dm"
+#include "code\modules\mob\living\silicon\ai\login.dm"
+#include "code\modules\mob\living\silicon\ai\logout.dm"
+#include "code\modules\mob\living\silicon\ai\say.dm"
+#include "code\modules\mob\living\silicon\ai\vox_sounds.dm"
+#include "code\modules\mob\living\silicon\ai\freelook\cameranet.dm"
+#include "code\modules\mob\living\silicon\ai\freelook\chunk.dm"
+#include "code\modules\mob\living\silicon\ai\freelook\eye.dm"
+#include "code\modules\mob\living\silicon\ai\freelook\read_me.dm"
+#include "code\modules\mob\living\silicon\ai\freelook\update_triggers.dm"
+#include "code\modules\mob\living\silicon\decoy\death.dm"
+#include "code\modules\mob\living\silicon\decoy\decoy.dm"
+#include "code\modules\mob\living\silicon\decoy\life.dm"
+#include "code\modules\mob\living\silicon\pai\death.dm"
+#include "code\modules\mob\living\silicon\pai\examine.dm"
+#include "code\modules\mob\living\silicon\pai\hud.dm"
+#include "code\modules\mob\living\silicon\pai\life.dm"
+#include "code\modules\mob\living\silicon\pai\pai.dm"
+#include "code\modules\mob\living\silicon\pai\personality.dm"
+#include "code\modules\mob\living\silicon\pai\recruit.dm"
+#include "code\modules\mob\living\silicon\pai\say.dm"
+#include "code\modules\mob\living\silicon\pai\software.dm"
+#include "code\modules\mob\living\silicon\robot\death.dm"
+#include "code\modules\mob\living\silicon\robot\emote.dm"
+#include "code\modules\mob\living\silicon\robot\examine.dm"
+#include "code\modules\mob\living\silicon\robot\inventory.dm"
+#include "code\modules\mob\living\silicon\robot\laws.dm"
+#include "code\modules\mob\living\silicon\robot\life.dm"
+#include "code\modules\mob\living\silicon\robot\login.dm"
+#include "code\modules\mob\living\silicon\robot\robot.dm"
+#include "code\modules\mob\living\silicon\robot\robot_modules.dm"
+#include "code\modules\mob\living\silicon\robot\robot_movement.dm"
+#include "code\modules\mob\living\silicon\robot\say.dm"
+#include "code\modules\mob\living\simple_animal\constructs.dm"
+#include "code\modules\mob\living\simple_animal\corpse.dm"
+#include "code\modules\mob\living\simple_animal\parrot.dm"
+#include "code\modules\mob\living\simple_animal\shade.dm"
+#include "code\modules\mob\living\simple_animal\simple_animal.dm"
+#include "code\modules\mob\living\simple_animal\friendly\cat.dm"
+#include "code\modules\mob\living\simple_animal\friendly\corgi.dm"
+#include "code\modules\mob\living\simple_animal\friendly\crab.dm"
+#include "code\modules\mob\living\simple_animal\friendly\farm_animals.dm"
+#include "code\modules\mob\living\simple_animal\friendly\lizard.dm"
+#include "code\modules\mob\living\simple_animal\friendly\mouse.dm"
+#include "code\modules\mob\living\simple_animal\friendly\pug.dm"
+#include "code\modules\mob\living\simple_animal\friendly\slime.dm"
+#include "code\modules\mob\living\simple_animal\friendly\tomato.dm"
+#include "code\modules\mob\living\simple_animal\hostile\alien.dm"
+#include "code\modules\mob\living\simple_animal\hostile\bear.dm"
+#include "code\modules\mob\living\simple_animal\hostile\carp.dm"
+#include "code\modules\mob\living\simple_animal\hostile\creature.dm"
+#include "code\modules\mob\living\simple_animal\hostile\faithless.dm"
+#include "code\modules\mob\living\simple_animal\hostile\giant_spider.dm"
+#include "code\modules\mob\living\simple_animal\hostile\hivebot.dm"
+#include "code\modules\mob\living\simple_animal\hostile\hostile.dm"
+#include "code\modules\mob\living\simple_animal\hostile\mimic.dm"
+#include "code\modules\mob\living\simple_animal\hostile\mining_mobs.dm"
+#include "code\modules\mob\living\simple_animal\hostile\mushroom.dm"
+#include "code\modules\mob\living\simple_animal\hostile\pirate.dm"
+#include "code\modules\mob\living\simple_animal\hostile\russian.dm"
+#include "code\modules\mob\living\simple_animal\hostile\syndicate.dm"
+#include "code\modules\mob\living\simple_animal\hostile\tree.dm"
+#include "code\modules\mob\living\simple_animal\hostile\retaliate\bat.dm"
+#include "code\modules\mob\living\simple_animal\hostile\retaliate\clown.dm"
+#include "code\modules\mob\living\simple_animal\hostile\retaliate\retaliate.dm"
+#include "code\modules\mob\new_player\login.dm"
+#include "code\modules\mob\new_player\logout.dm"
+#include "code\modules\mob\new_player\new_player.dm"
+#include "code\modules\mob\new_player\poll.dm"
+#include "code\modules\mob\new_player\preferences_setup.dm"
+#include "code\modules\mob\new_player\sprite_accessories.dm"
+#include "code\modules\nano\_JSON.dm"
+#include "code\modules\nano\JSON Reader.dm"
+#include "code\modules\nano\JSON Writer.dm"
+#include "code\modules\nano\nanoexternal.dm"
+#include "code\modules\nano\nanomanager.dm"
+#include "code\modules\nano\nanoui.dm"
+#include "code\modules\paperwork\clipboard.dm"
+#include "code\modules\paperwork\filingcabinet.dm"
+#include "code\modules\paperwork\folders.dm"
+#include "code\modules\paperwork\handlabeler.dm"
+#include "code\modules\paperwork\paper.dm"
+#include "code\modules\paperwork\paperbin.dm"
+#include "code\modules\paperwork\pen.dm"
+#include "code\modules\paperwork\photocopier.dm"
+#include "code\modules\paperwork\photography.dm"
+#include "code\modules\paperwork\stamps.dm"
+#include "code\modules\power\apc.dm"
+#include "code\modules\power\cable.dm"
+#include "code\modules\power\cell.dm"
+#include "code\modules\power\engine.dm"
+#include "code\modules\power\generator.dm"
+#include "code\modules\power\gravitygenerator.dm"
+#include "code\modules\power\lighting.dm"
+#include "code\modules\power\port_gen.dm"
+#include "code\modules\power\power.dm"
+#include "code\modules\power\smes.dm"
+#include "code\modules\power\solar.dm"
+#include "code\modules\power\switch.dm"
+#include "code\modules\power\terminal.dm"
+#include "code\modules\power\tracker.dm"
+#include "code\modules\power\turbine.dm"
+#include "code\modules\power\antimatter\containment_jar.dm"
+#include "code\modules\power\antimatter\control.dm"
+#include "code\modules\power\antimatter\shielding.dm"
+#include "code\modules\power\singularity\collector.dm"
+#include "code\modules\power\singularity\containment_field.dm"
+#include "code\modules\power\singularity\emitter.dm"
+#include "code\modules\power\singularity\field_generator.dm"
+#include "code\modules\power\singularity\generator.dm"
+#include "code\modules\power\singularity\investigate.dm"
+#include "code\modules\power\singularity\singularity.dm"
+#include "code\modules\power\singularity\particle_accelerator\particle.dm"
+#include "code\modules\power\singularity\particle_accelerator\particle_accelerator.dm"
+#include "code\modules\power\singularity\particle_accelerator\particle_chamber.dm"
+#include "code\modules\power\singularity\particle_accelerator\particle_control.dm"
+#include "code\modules\power\singularity\particle_accelerator\particle_emitter.dm"
+#include "code\modules\power\singularity\particle_accelerator\particle_power.dm"
+#include "code\modules\projectiles\ammunition.dm"
+#include "code\modules\projectiles\firing.dm"
+#include "code\modules\projectiles\gun.dm"
+#include "code\modules\projectiles\projectile.dm"
+#include "code\modules\projectiles\ammunition\boxes.dm"
+#include "code\modules\projectiles\ammunition\bullets.dm"
+#include "code\modules\projectiles\ammunition\energy.dm"
+#include "code\modules\projectiles\ammunition\magazines.dm"
+#include "code\modules\projectiles\ammunition\special.dm"
+#include "code\modules\projectiles\guns\energy.dm"
+#include "code\modules\projectiles\guns\magic.dm"
+#include "code\modules\projectiles\guns\projectile.dm"
+#include "code\modules\projectiles\guns\energy\laser.dm"
+#include "code\modules\projectiles\guns\energy\nuclear.dm"
+#include "code\modules\projectiles\guns\energy\pulse.dm"
+#include "code\modules\projectiles\guns\energy\special.dm"
+#include "code\modules\projectiles\guns\energy\stun.dm"
+#include "code\modules\projectiles\guns\energy\temperature.dm"
+#include "code\modules\projectiles\guns\magic\staff.dm"
+#include "code\modules\projectiles\guns\magic\wand.dm"
+#include "code\modules\projectiles\guns\projectile\automatic.dm"
+#include "code\modules\projectiles\guns\projectile\pistol.dm"
+#include "code\modules\projectiles\guns\projectile\revolver.dm"
+#include "code\modules\projectiles\guns\projectile\shotgun.dm"
+#include "code\modules\projectiles\projectile\beams.dm"
+#include "code\modules\projectiles\projectile\bullets.dm"
+#include "code\modules\projectiles\projectile\energy.dm"
+#include "code\modules\projectiles\projectile\magic.dm"
+#include "code\modules\projectiles\projectile\special.dm"
+#include "code\modules\reagents\Chemistry-Colours.dm"
+#include "code\modules\reagents\Chemistry-Holder.dm"
+#include "code\modules\reagents\Chemistry-Machinery.dm"
+#include "code\modules\reagents\Chemistry-Readme.dm"
+#include "code\modules\reagents\Chemistry-Reagents.dm"
+#include "code\modules\reagents\Chemistry-Recipes.dm"
+#include "code\modules\reagents\grenade_launcher.dm"
+#include "code\modules\reagents\reagent_containers.dm"
+#include "code\modules\reagents\reagent_dispenser.dm"
+#include "code\modules\reagents\syringe_gun.dm"
+#include "code\modules\reagents\reagent_containers\borghydro.dm"
+#include "code\modules\reagents\reagent_containers\dropper.dm"
+#include "code\modules\reagents\reagent_containers\food.dm"
+#include "code\modules\reagents\reagent_containers\glass.dm"
+#include "code\modules\reagents\reagent_containers\hypospray.dm"
+#include "code\modules\reagents\reagent_containers\pill.dm"
+#include "code\modules\reagents\reagent_containers\spray.dm"
+#include "code\modules\reagents\reagent_containers\syringes.dm"
+#include "code\modules\reagents\reagent_containers\food\condiment.dm"
+#include "code\modules\reagents\reagent_containers\food\drinks.dm"
+#include "code\modules\reagents\reagent_containers\food\snacks.dm"
+#include "code\modules\reagents\reagent_containers\food\drinks\bottle.dm"
+#include "code\modules\reagents\reagent_containers\food\drinks\drinkingglass.dm"
+#include "code\modules\reagents\reagent_containers\food\drinks\bottle\robot.dm"
+#include "code\modules\reagents\reagent_containers\food\snacks\meat.dm"
+#include "code\modules\reagents\reagent_containers\glass\bottle.dm"
+#include "code\modules\reagents\reagent_containers\glass\bottle\robot.dm"
+#include "code\modules\recycling\conveyor2.dm"
+#include "code\modules\recycling\disposal-construction.dm"
+#include "code\modules\recycling\disposal.dm"
+#include "code\modules\recycling\sortingmachinery.dm"
+#include "code\modules\research\circuitprinter.dm"
+#include "code\modules\research\designs.dm"
+#include "code\modules\research\destructive_analyzer.dm"
+#include "code\modules\research\message_server.dm"
+#include "code\modules\research\protolathe.dm"
+#include "code\modules\research\rd-readme.dm"
+#include "code\modules\research\rdconsole.dm"
+#include "code\modules\research\rdmachines.dm"
+#include "code\modules\research\research.dm"
+#include "code\modules\research\server.dm"
+#include "code\modules\scripting\Errors.dm"
+#include "code\modules\scripting\IDE.dm"
+#include "code\modules\scripting\Options.dm"
+#include "code\modules\scripting\stack.dm"
+#include "code\modules\scripting\AST\AST Nodes.dm"
+#include "code\modules\scripting\AST\Blocks.dm"
+#include "code\modules\scripting\AST\Statements.dm"
+#include "code\modules\scripting\AST\Operators\Binary Operators.dm"
+#include "code\modules\scripting\AST\Operators\Unary Operators.dm"
+#include "code\modules\scripting\Implementations\_Logic.dm"
+#include "code\modules\scripting\Implementations\Telecomms.dm"
+#include "code\modules\scripting\Interpreter\Evaluation.dm"
+#include "code\modules\scripting\Interpreter\Interaction.dm"
+#include "code\modules\scripting\Interpreter\Interpreter.dm"
+#include "code\modules\scripting\Interpreter\Scope.dm"
+#include "code\modules\scripting\Parser\Expressions.dm"
+#include "code\modules\scripting\Parser\Keywords.dm"
+#include "code\modules\scripting\Parser\Parser.dm"
+#include "code\modules\scripting\Scanner\Scanner.dm"
+#include "code\modules\scripting\Scanner\Tokens.dm"
+#include "code\modules\security levels\keycard authentication.dm"
+#include "code\modules\security levels\security levels.dm"
+#include "code\modules\shuttle\shuttle.dm"
+#include "code\modules\surgery\appendectomy.dm"
+#include "code\modules\surgery\brain_removal.dm"
+#include "code\modules\surgery\cavity_implant.dm"
+#include "code\modules\surgery\core_removal.dm"
+#include "code\modules\surgery\eye_surgery.dm"
+#include "code\modules\surgery\gender_reassignment.dm"
+#include "code\modules\surgery\generic_steps.dm"
+#include "code\modules\surgery\helpers.dm"
+#include "code\modules\surgery\implant_removal.dm"
+#include "code\modules\surgery\limb augmentation.dm"
+#include "code\modules\surgery\lipoplasty.dm"
+#include "code\modules\surgery\plastic_surgery.dm"
+#include "code\modules\surgery\surgery.dm"
+#include "code\modules\surgery\surgery_step.dm"
+#include "code\modules\surgery\tools.dm"
+#include "code\modules\surgery\xenomorph_removal.dm"
+#include "code\modules\surgery\organs\augments.dm"
+#include "code\modules\surgery\organs\helpers.dm"
+#include "code\modules\surgery\organs\organ.dm"
+#include "code\modules\telesci\bscrystal.dm"
+#include "code\modules\telesci\gps.dm"
+#include "code\modules\telesci\telepad.dm"
+#include "code\modules\telesci\telesci_computer.dm"
+#include "code\WorkInProgress\buildmode.dm"
+#include "code\WorkInProgress\explosion_particles.dm"
+#include "code\WorkInProgress\Sigyn\Department Sec\jobs.dm"
+#include "interface\interface.dm"
+#include "interface\stylesheet.dm"
+#include "interface\skin.dmf"
+// END_INCLUDE