Merge pull request #1011 from Erthilo/TGUpdates

TG updates up to r3571
This commit is contained in:
CIB
2012-05-09 23:50:10 -07:00
93 changed files with 3055 additions and 1491 deletions
+7 -2
View File
@@ -102,6 +102,7 @@
#define FILE_DIR "code/modules/DetectiveWork"
#define FILE_DIR "code/modules/flufftext"
#define FILE_DIR "code/modules/food"
#define FILE_DIR "code/modules/maps"
#define FILE_DIR "code/modules/mining"
#define FILE_DIR "code/modules/mob"
#define FILE_DIR "code/modules/mob/dead"
@@ -198,6 +199,7 @@
#define FILE_DIR "icons/vending_icons"
#define FILE_DIR "interface"
#define FILE_DIR "maps"
#define FILE_DIR "maps/RandomZLevels"
#define FILE_DIR "sound"
#define FILE_DIR "sound/AI"
#define FILE_DIR "sound/ambience"
@@ -873,6 +875,11 @@
#include "code\modules\food\food.dm"
#include "code\modules\food\meat.dm"
#include "code\modules\food\recipes_microwave.dm"
#include "code\modules\maps\dmm_suite.dm"
#include "code\modules\maps\randomZlevel.dm"
#include "code\modules\maps\reader.dm"
#include "code\modules\maps\SwapMaps.dm"
#include "code\modules\maps\writer.dm"
#include "code\modules\mining\machine_input_output_plates.dm"
#include "code\modules\mining\machine_processing.dm"
#include "code\modules\mining\machine_stacking.dm"
@@ -1149,8 +1156,6 @@
#include "code\WorkInProgress\Cael_Aislinn\Tajara\tajaran.dm"
#include "code\WorkInProgress\Cael_Aislinn\Tajara\whisper.dm"
#include "code\WorkInProgress\Chinsky\ashtray.dm"
#include "code\WorkInProgress\mapload\dmm_suite.dm"
#include "code\WorkInProgress\mapload\reader.dm"
#include "code\WorkInProgress\Mini\ATM.dm"
#include "code\WorkInProgress\Mini\atmos_control.dm"
#include "code\WorkInProgress\Mini\pipe_heater.dm"
@@ -354,37 +354,8 @@
overlays += image("icon" = 'belt.dmi', "icon_state" = text("[][]", t1, (!( lying ) ? null : "2")), "layer" = MOB_LAYER)
belt.screen_loc = ui_belt
if ((wear_mask && !(wear_mask.see_face)) || (head && !(head.see_face))) // can't see the face
if (wear_id)
if (istype(wear_id, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/id = wear_id
if (id.registered_name)
name = id.registered_name
else
name = "Unknown"
else if (istype(wear_id, /obj/item/device/pda))
var/obj/item/device/pda/pda = wear_id
if (pda.owner)
name = pda.owner
else
name = "Unknown"
else
name = "Unknown"
else
if (wear_id)
if (istype(wear_id, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/id = wear_id
if (id.registered_name != real_name)
name = "[real_name] (as [id.registered_name])"
else if (istype(wear_id, /obj/item/device/pda))
var/obj/item/device/pda/pda = wear_id
if (pda.owner)
if (pda.owner != real_name)
name = "[real_name] (as [pda.owner])"
else
name = real_name
name = get_visible_name()
if (wear_id)
wear_id.screen_loc = ui_id
+387 -381
View File
@@ -390,398 +390,404 @@ client
return html
Topic(href, href_list, hsrc)
//All BYOND links pass through client/Topic() FIRST and are then directed to [hsrc]/Topic() by the ..() call at the end.
client/Topic(href, href_list, hsrc)
if (href_list["Vars"])
debug_variables(locate(href_list["Vars"]))
//search the href for script injection //This is a temporary measure
if( findtext(href,"<script",1,0) )
world.log << "Attempted use of scripts within a topic call, by [src]"
message_admins("Attempted use of scripts within a topic call, by [src]")
del(usr)
return
//~CARN: for renaming mobs (updates their real_name and their ID/PDA if applicable).
else if (href_list["rename"])
var/new_name = input(usr,"What would you like to name this mob?","Input a name") as text|null
if(!new_name) return
var/mob/M = locate(href_list["rename"])
if(!istype(M)) return
if(href_list["priv_msg"])
var/client/C = locate(href_list["priv_msg"])
if(ismob(C)) //Old stuff can pass in mobs instead of clients
var/mob/M = C
C = M.client
cmd_admin_pm(C,null)
return
message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].", 1)
if(istype(M, /mob/living/carbon/human))
for(var/obj/item/weapon/card/id/ID in M.contents)
if(ID.registered_name == M.real_name)
ID.name = "[new_name]'s ID Card ([ID.assignment])"
ID.registered_name = new_name
break
for(var/obj/item/device/pda/PDA in M.contents)
if(PDA.owner == M.real_name)
PDA.name = "PDA-[new_name] ([PDA.ownjob])"
PDA.owner = new_name
break
M.real_name = new_name
M.name = new_name
M.original_name = new_name
href_list["datumrefresh"] = href_list["rename"]
else
//THIS **REALLY** NEEDS TO BE REWRITTEN AS obj/admin/Topic or something. As a matter of urgency.
if( (usr.client == src) && src.holder )
if (href_list["Vars"])
debug_variables(locate(href_list["Vars"]))
else if (href_list["varnameedit"])
if(!href_list["datumedit"] || !href_list["varnameedit"])
usr << "Varedit error: Not all information has been sent Contact a coder."
return
var/DAT = locate(href_list["datumedit"])
if(!DAT)
usr << "Item not found"
return
if(!istype(DAT,/datum) && !istype(DAT,/client))
usr << "Can't edit an item of this type. Type must be /datum or /client, so anything except simple variables."
return
modify_variables(DAT, href_list["varnameedit"], 1)
else if (href_list["varnamechange"])
if(!href_list["datumchange"] || !href_list["varnamechange"])
usr << "Varedit error: Not all information has been sent. Contact a coder."
return
var/DAT = locate(href_list["datumchange"])
if(!DAT)
usr << "Item not found"
return
if(!istype(DAT,/datum) && !istype(DAT,/client))
usr << "Can't edit an item of this type. Type must be /datum or /client, so anything except simple variables."
return
modify_variables(DAT, href_list["varnamechange"], 0)
else if (href_list["varnamemass"])
if(!href_list["datummass"] || !href_list["varnamemass"])
usr << "Varedit error: Not all information has been sent. Contact a coder."
return
var/atom/A = locate(href_list["datummass"])
if(!A)
usr << "Item not found"
return
if(!istype(A,/atom))
usr << "Can't mass edit an item of this type. Type must be /atom, so an object, turf, mob or area. You cannot mass edit clients!"
return
cmd_mass_modify_object_variables(A, href_list["varnamemass"])
else if (href_list["mob_player_panel"])
if(!href_list["mob_player_panel"])
return
var/mob/MOB = locate(href_list["mob_player_panel"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
src.holder.show_player_panel(MOB)
href_list["datumrefresh"] = href_list["mob_player_panel"]
else if (href_list["give_spell"])
if(!href_list["give_spell"])
return
var/mob/MOB = locate(href_list["give_spell"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
src.give_spell(MOB)
href_list["datumrefresh"] = href_list["give_spell"]
else if (href_list["ninja"])
if(!href_list["ninja"])
return
var/mob/MOB = locate(href_list["ninja"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
src.cmd_admin_ninjafy(MOB)
href_list["datumrefresh"] = href_list["ninja"]
else if (href_list["godmode"])
if(!href_list["godmode"])
return
var/mob/MOB = locate(href_list["godmode"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
src.cmd_admin_godmode(MOB)
href_list["datumrefresh"] = href_list["godmode"]
else if (href_list["gib"])
if(!href_list["gib"])
return
var/mob/MOB = locate(href_list["gib"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
src.cmd_admin_gib(MOB)
//~CARN: for renaming mobs (updates their real_name and their ID/PDA if applicable).
else if (href_list["rename"])
var/new_name = input(usr,"What would you like to name this mob?","Input a name") as text|null
if(!new_name) return
var/mob/M = locate(href_list["rename"])
if(!istype(M)) return
else if (href_list["build_mode"])
if(!href_list["build_mode"])
return
var/mob/MOB = locate(href_list["build_mode"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
togglebuildmode(MOB)
href_list["datumrefresh"] = href_list["build_mode"]
message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].", 1)
if(istype(M, /mob/living/carbon/human))
for(var/obj/item/weapon/card/id/ID in M.contents)
if(ID.registered_name == M.real_name)
ID.name = "[new_name]'s ID Card ([ID.assignment])"
ID.registered_name = new_name
break
for(var/obj/item/device/pda/PDA in M.contents)
if(PDA.owner == M.real_name)
PDA.name = "PDA-[new_name] ([PDA.ownjob])"
PDA.owner = new_name
break
M.real_name = new_name
M.name = new_name
M.original_name = new_name
href_list["datumrefresh"] = href_list["rename"]
else if (href_list["drop_everything"])
if(!href_list["drop_everything"])
return
var/mob/MOB = locate(href_list["drop_everything"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
if(usr.client)
usr.client.cmd_admin_drop_everything(MOB)
else if (href_list["direct_control"])
if(!href_list["direct_control"])
return
var/mob/MOB = locate(href_list["direct_control"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
if(usr.client)
usr.client.cmd_assume_direct_control(MOB)
else if (href_list["delall"])
if(!href_list["delall"])
return
var/atom/A = locate(href_list["delall"])
if(!A)
return
if(!isobj(A))
usr << "This can only be used on objects (of type /obj)"
return
if(!A.type)
return
var/action_type = alert("Strict type ([A.type]) or type and all subtypes?",,"Strict type","Type and subtypes","Cancel")
if(!action_type || action_type == "Cancel")
return
if(alert("Are you really sure you want to delete all objects of type [A.type]?",,"Yes","No") != "Yes")
return
if(alert("Second confirmation required. Delete?",,"Yes","No") != "Yes")
return
var/a_type = A.type
if(action_type == "Strict type")
var/i = 0
for(var/obj/O in world)
if(O.type == a_type)
i++
del(O)
if(!i)
usr << "No objects of this type exist"
else if (href_list["varnameedit"])
if(!href_list["datumedit"] || !href_list["varnameedit"])
usr << "Varedit error: Not all information has been sent Contact a coder."
return
log_admin("[key_name(usr)] deleted all objects of scrict type [a_type] ([i] objects deleted) ")
message_admins("\blue [key_name(usr)] deleted all objects of scrict type [a_type] ([i] objects deleted) ", 1)
else if(action_type == "Type and subtypes")
var/i = 0
for(var/obj/O in world)
if(istype(O,a_type))
i++
del(O)
if(!i)
usr << "No objects of this type exist"
var/DAT = locate(href_list["datumedit"])
if(!DAT)
usr << "Item not found"
return
log_admin("[key_name(usr)] deleted all objects of scrict type with subtypes [a_type] ([i] objects deleted) ")
message_admins("\blue [key_name(usr)] deleted all objects of type with subtypes [a_type] ([i] objects deleted) ", 1)
if(!istype(DAT,/datum) && !istype(DAT,/client))
usr << "Can't edit an item of this type. Type must be /datum or /client, so anything except simple variables."
return
modify_variables(DAT, href_list["varnameedit"], 1)
else if (href_list["varnamechange"])
if(!href_list["datumchange"] || !href_list["varnamechange"])
usr << "Varedit error: Not all information has been sent. Contact a coder."
return
var/DAT = locate(href_list["datumchange"])
if(!DAT)
usr << "Item not found"
return
if(!istype(DAT,/datum) && !istype(DAT,/client))
usr << "Can't edit an item of this type. Type must be /datum or /client, so anything except simple variables."
return
modify_variables(DAT, href_list["varnamechange"], 0)
else if (href_list["varnamemass"])
if(!href_list["datummass"] || !href_list["varnamemass"])
usr << "Varedit error: Not all information has been sent. Contact a coder."
return
var/atom/A = locate(href_list["datummass"])
if(!A)
usr << "Item not found"
return
if(!istype(A,/atom))
usr << "Can't mass edit an item of this type. Type must be /atom, so an object, turf, mob or area. You cannot mass edit clients!"
return
cmd_mass_modify_object_variables(A, href_list["varnamemass"])
else if (href_list["mob_player_panel"])
if(!href_list["mob_player_panel"])
return
var/mob/MOB = locate(href_list["mob_player_panel"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
src.holder.show_player_panel(MOB)
href_list["datumrefresh"] = href_list["mob_player_panel"]
else if (href_list["give_spell"])
if(!href_list["give_spell"])
return
var/mob/MOB = locate(href_list["give_spell"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
src.give_spell(MOB)
href_list["datumrefresh"] = href_list["give_spell"]
else if (href_list["ninja"])
if(!href_list["ninja"])
return
var/mob/MOB = locate(href_list["ninja"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
src.cmd_admin_ninjafy(MOB)
href_list["datumrefresh"] = href_list["ninja"]
else if (href_list["godmode"])
if(!href_list["godmode"])
return
var/mob/MOB = locate(href_list["godmode"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
src.cmd_admin_godmode(MOB)
href_list["datumrefresh"] = href_list["godmode"]
else if (href_list["gib"])
if(!href_list["gib"])
return
var/mob/MOB = locate(href_list["gib"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
src.cmd_admin_gib(MOB)
else if (href_list["explode"])
if(!href_list["explode"])
return
var/atom/A = locate(href_list["explode"])
if(!A)
return
if(!isobj(A) && !ismob(A) && !isturf(A))
return
src.cmd_admin_explosion(A)
href_list["datumrefresh"] = href_list["explode"]
else if (href_list["emp"])
if(!href_list["emp"])
return
var/atom/A = locate(href_list["emp"])
if(!A)
return
if(!isobj(A) && !ismob(A) && !isturf(A))
return
src.cmd_admin_emp(A)
href_list["datumrefresh"] = href_list["emp"]
else if (href_list["mark_object"])
if(!href_list["mark_object"])
return
var/datum/D = locate(href_list["mark_object"])
if(!D)
return
if(!src.holder)
return
src.holder.marked_datum = D
href_list["datumrefresh"] = href_list["mark_object"]
else if (href_list["rotatedatum"])
if(!href_list["rotatedir"])
return
var/atom/A = locate(href_list["rotatedatum"])
if(!A)
return
if(!istype(A,/atom))
usr << "This can only be done to objects of type /atom"
return
if(!src.holder)
return
switch(href_list["rotatedir"])
if("right")
A.dir = turn(A.dir, -45)
if("left")
A.dir = turn(A.dir, 45)
href_list["datumrefresh"] = href_list["rotatedatum"]
else if (href_list["makemonkey"])
var/mob/M = locate(href_list["makemonkey"])
if(!M)
return
if(!ishuman(M))
usr << "This can only be done to objects of type /mob/living/carbon/human"
return
if(!src.holder)
usr << "You are not an administrator."
return
var/action_type = alert("Confirm mob type change?",,"Transform","Cancel")
if(!action_type || action_type == "Cancel")
return
if(!M)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("monkeyone"=href_list["makemonkey"]))
else if (href_list["makerobot"])
var/mob/M = locate(href_list["makerobot"])
if(!M)
return
if(!ishuman(M))
usr << "This can only be done to objects of type /mob/living/carbon/human"
return
if(!src.holder)
usr << "You are not an administrator."
return
var/action_type = alert("Confirm mob type change?",,"Transform","Cancel")
if(!action_type || action_type == "Cancel")
return
if(!M)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makerobot"=href_list["makerobot"]))
else if (href_list["makealien"])
var/mob/M = locate(href_list["makealien"])
if(!M)
return
if(!ishuman(M))
usr << "This can only be done to objects of type /mob/living/carbon/human"
return
if(!src.holder)
usr << "You are not an administrator."
return
var/action_type = alert("Confirm mob type change?",,"Transform","Cancel")
if(!action_type || action_type == "Cancel")
return
if(!M)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makealien"=href_list["makealien"]))
else if (href_list["makemetroid"])
var/mob/M = locate(href_list["makemetroid"])
if(!M)
return
if(!ishuman(M))
usr << "This can only be done to objects of type /mob/living/carbon/human"
return
if(!src.holder)
usr << "You are not an administrator."
return
var/action_type = alert("Confirm mob type change?",,"Transform","Cancel")
if(!action_type || action_type == "Cancel")
return
if(!M)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makemetroid"=href_list["makemetroid"]))
else if (href_list["makeai"])
var/mob/M = locate(href_list["makeai"])
if(!M)
return
if(!ishuman(M))
usr << "This can only be done to objects of type /mob/living/carbon/human"
return
if(!src.holder)
usr << "You are not an administrator."
return
var/action_type = alert("Confirm mob type change?",,"Transform","Cancel")
if(!action_type || action_type == "Cancel")
return
if(!M)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makeai"=href_list["makeai"]))
else if (href_list["makeaisilent"])
var/mob/M = locate(href_list["makeaisilent"])
if(!M)
return
if(!ishuman(M))
usr << "This can only be done to objects of type /mob/living/carbon/human"
return
if(!src.holder)
usr << "You are not an administrator."
return
var/action_type = alert("Confirm mob type change?",,"Transform","Cancel")
if(!action_type || action_type == "Cancel")
return
if(!M)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makeaisilent"=href_list["makeaisilent"]))
else if (href_list["adjustDamage"] && href_list["mobToDamage"])
var/mob/M = locate(href_list["mobToDamage"])
var/Text = locate(href_list["adjustDamage"])
else if (href_list["build_mode"])
if(!href_list["build_mode"])
return
var/mob/MOB = locate(href_list["build_mode"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
togglebuildmode(MOB)
href_list["datumrefresh"] = href_list["build_mode"]
var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num
if(Text == "brute")
M.adjustBruteLoss(amount)
else if(Text == "fire")
M.adjustFireLoss(amount)
else if(Text == "toxin")
M.adjustToxLoss(amount)
else if(Text == "oxygen")
M.adjustOxyLoss(amount)
else if(Text == "brain")
M.adjustBrainLoss(amount)
else if(Text == "clone")
M.adjustCloneLoss(amount)
else if (href_list["drop_everything"])
if(!href_list["drop_everything"])
return
var/mob/MOB = locate(href_list["drop_everything"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
if(usr.client)
usr.client.cmd_admin_drop_everything(MOB)
else if (href_list["direct_control"])
if(!href_list["direct_control"])
return
var/mob/MOB = locate(href_list["direct_control"])
if(!MOB)
return
if(!ismob(MOB))
return
if(!src.holder)
return
if(usr.client)
usr.client.cmd_assume_direct_control(MOB)
else if (href_list["delall"])
if(!href_list["delall"])
return
var/atom/A = locate(href_list["delall"])
if(!A)
return
if(!isobj(A))
usr << "This can only be used on objects (of type /obj)"
return
if(!A.type)
return
var/action_type = alert("Strict type ([A.type]) or type and all subtypes?",,"Strict type","Type and subtypes","Cancel")
if(!action_type || action_type == "Cancel")
return
if(alert("Are you really sure you want to delete all objects of type [A.type]?",,"Yes","No") != "Yes")
return
if(alert("Second confirmation required. Delete?",,"Yes","No") != "Yes")
return
var/a_type = A.type
if(action_type == "Strict type")
var/i = 0
for(var/obj/O in world)
if(O.type == a_type)
i++
del(O)
if(!i)
usr << "No objects of this type exist"
return
log_admin("[key_name(usr)] deleted all objects of scrict type [a_type] ([i] objects deleted) ")
message_admins("\blue [key_name(usr)] deleted all objects of scrict type [a_type] ([i] objects deleted) ", 1)
else if(action_type == "Type and subtypes")
var/i = 0
for(var/obj/O in world)
if(istype(O,a_type))
i++
del(O)
if(!i)
usr << "No objects of this type exist"
return
log_admin("[key_name(usr)] deleted all objects of scrict type with subtypes [a_type] ([i] objects deleted) ")
message_admins("\blue [key_name(usr)] deleted all objects of type with subtypes [a_type] ([i] objects deleted) ", 1)
else if (href_list["explode"])
if(!href_list["explode"])
return
var/atom/A = locate(href_list["explode"])
if(!A)
return
if(!isobj(A) && !ismob(A) && !isturf(A))
return
src.cmd_admin_explosion(A)
href_list["datumrefresh"] = href_list["explode"]
else if (href_list["emp"])
if(!href_list["emp"])
return
var/atom/A = locate(href_list["emp"])
if(!A)
return
if(!isobj(A) && !ismob(A) && !isturf(A))
return
src.cmd_admin_emp(A)
href_list["datumrefresh"] = href_list["emp"]
else if (href_list["mark_object"])
if(!href_list["mark_object"])
return
var/datum/D = locate(href_list["mark_object"])
if(!D)
return
if(!src.holder)
return
src.holder.marked_datum = D
href_list["datumrefresh"] = href_list["mark_object"]
else if (href_list["rotatedatum"])
if(!href_list["rotatedir"])
return
var/atom/A = locate(href_list["rotatedatum"])
if(!A)
return
if(!istype(A,/atom))
usr << "This can only be done to objects of type /atom"
return
if(!src.holder)
return
switch(href_list["rotatedir"])
if("right")
A.dir = turn(A.dir, -45)
if("left")
A.dir = turn(A.dir, 45)
href_list["datumrefresh"] = href_list["rotatedatum"]
else if (href_list["makemonkey"])
var/mob/M = locate(href_list["makemonkey"])
if(!M)
return
if(!ishuman(M))
usr << "This can only be done to objects of type /mob/living/carbon/human"
return
if(!src.holder)
usr << "You are not an administrator."
return
var/action_type = alert("Confirm mob type change?",,"Transform","Cancel")
if(!action_type || action_type == "Cancel")
return
if(!M)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("monkeyone"=href_list["makemonkey"]))
else if (href_list["makerobot"])
var/mob/M = locate(href_list["makerobot"])
if(!M)
return
if(!ishuman(M))
usr << "This can only be done to objects of type /mob/living/carbon/human"
return
if(!src.holder)
usr << "You are not an administrator."
return
var/action_type = alert("Confirm mob type change?",,"Transform","Cancel")
if(!action_type || action_type == "Cancel")
return
if(!M)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makerobot"=href_list["makerobot"]))
else if (href_list["makealien"])
var/mob/M = locate(href_list["makealien"])
if(!M)
return
if(!ishuman(M))
usr << "This can only be done to objects of type /mob/living/carbon/human"
return
if(!src.holder)
usr << "You are not an administrator."
return
var/action_type = alert("Confirm mob type change?",,"Transform","Cancel")
if(!action_type || action_type == "Cancel")
return
if(!M)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makealien"=href_list["makealien"]))
else if (href_list["makemetroid"])
var/mob/M = locate(href_list["makemetroid"])
if(!M)
return
if(!ishuman(M))
usr << "This can only be done to objects of type /mob/living/carbon/human"
return
if(!src.holder)
usr << "You are not an administrator."
return
var/action_type = alert("Confirm mob type change?",,"Transform","Cancel")
if(!action_type || action_type == "Cancel")
return
if(!M)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makemetroid"=href_list["makemetroid"]))
else if (href_list["makeai"])
var/mob/M = locate(href_list["makeai"])
if(!M)
return
if(!ishuman(M))
usr << "This can only be done to objects of type /mob/living/carbon/human"
return
if(!src.holder)
usr << "You are not an administrator."
return
var/action_type = alert("Confirm mob type change?",,"Transform","Cancel")
if(!action_type || action_type == "Cancel")
return
if(!M)
usr << "Mob doesn't exist anymore"
return
holder.Topic(href, list("makeai"=href_list["makeai"]))
else if (href_list["adjustDamage"] && href_list["mobToDamage"])
var/mob/M = locate(href_list["mobToDamage"])
var/Text = locate(href_list["adjustDamage"])
var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num
if(Text == "brute")
M.adjustBruteLoss(amount)
else if(Text == "fire")
M.adjustFireLoss(amount)
else if(Text == "toxin")
M.adjustToxLoss(amount)
else if(Text == "oxygen")
M.adjustOxyLoss(amount)
else if(Text == "brain")
M.adjustBrainLoss(amount)
else if(Text == "clone")
M.adjustCloneLoss(amount)
else
usr << "You caused an error. DEBUG: Text:[Text] Mob:[M]"
return
if(amount != 0)
log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [M] ")
message_admins("\blue [key_name(usr)] dealt [amount] amount of [Text] damage to [M] ", 1)
href_list["datumrefresh"] = href_list["mobToDamage"]
else
usr << "You caused an error. DEBUG: Text:[Text] Mob:[M]"
return
..()
if(amount != 0)
log_admin("[key_name(usr)] dealt [amount] amount of [Text] damage to [M] ")
message_admins("\blue [key_name(usr)] dealt [amount] amount of [Text] damage to [M] ", 1)
href_list["datumrefresh"] = href_list["mobToDamage"]
else
..()
if (href_list["datumrefresh"])
if(!href_list["datumrefresh"])
return
var/datum/DAT = locate(href_list["datumrefresh"])
if(!DAT)
return
if(!istype(DAT,/datum))
return
src.debug_variables(DAT)
return
if (href_list["datumrefresh"])
if(!href_list["datumrefresh"])
return
var/datum/DAT = locate(href_list["datumrefresh"])
if(!DAT)
return
if(!istype(DAT,/datum))
return
src.debug_variables(DAT)
//Ok, all done with that admin crap. redirect it to the Topic for hsrc
..()
+2
View File
@@ -100,6 +100,7 @@
var/turf/destturf
var/turf/curturf = get_turf(teleatom)
var/area/destarea = get_area(destination)
if(precision)
var/list/posturfs = circlerangeturfs(destination,precision)
destturf = safepick(posturfs)
@@ -125,6 +126,7 @@
// Re-Apply lum
teleatom.sd_SetLuminosity(prevlum)
destarea.Entered(teleatom)
return 1
+4
View File
@@ -46,6 +46,10 @@ datum/mind
recipient << browse(output,"window=memory")
proc/edit_memory()
if(!ticker || !ticker.mode)
alert("Not before round-start!", "Alert")
return
var/out = "<B>[current.real_name]</B><br>"
out += "Assigned role: [assigned_role]. <a href='?src=\ref[src];role_edit=1'>Edit</a><br>"
out += "Factions and special roles:<br>"
+41 -20
View File
@@ -10,6 +10,8 @@
range = -1
include_user = 1
var phaseshift = 0
var/jaunt_duration = 50 //in deciseconds
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded
@@ -25,26 +27,45 @@
animation.icon_state = "liquify"
animation.layer = 5
animation.master = holder
flick("liquify",animation)
target.loc = holder
target.client.eye = holder
var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread()
steam.set_up(10, 0, mobloc)
steam.start()
sleep(jaunt_duration)
mobloc = get_turf(target.loc)
animation.loc = mobloc
steam.location = mobloc
steam.start()
target.canmove = 0
sleep(20)
flick("reappear",animation)
sleep(5)
target.loc = mobloc
target.canmove = 1
target.client.eye = target
del(animation)
del(holder)
if(phaseshift == 1)
animation.dir = target.dir
flick("phase_shift",animation)
target.loc = holder
target.client.eye = holder
sleep(jaunt_duration)
mobloc = get_turf(target.loc)
animation.loc = mobloc
target.canmove = 0
sleep(20)
animation.dir = target.dir
flick("phase_shift2",animation)
sleep(5)
target.loc = mobloc
target.canmove = 1
target.client.eye = target
del(animation)
del(holder)
else
flick("liquify",animation)
target.loc = holder
target.client.eye = holder
var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread()
steam.set_up(10, 0, mobloc)
steam.start()
sleep(jaunt_duration)
mobloc = get_turf(target.loc)
animation.loc = mobloc
steam.location = mobloc
steam.start()
target.canmove = 0
sleep(20)
flick("reappear",animation)
sleep(5)
target.loc = mobloc
target.canmove = 1
target.client.eye = target
del(animation)
del(holder)
/obj/effect/dummy/spell_jaunt
name = "water"
+1 -1
View File
@@ -317,5 +317,5 @@
invocation_type = "none"
range = -1
include_user = 1
phaseshift = 1
jaunt_duration = 50 //in deciseconds
@@ -1504,6 +1504,21 @@ proc/process_ghost_teleport_locs()
icon_state = "tcomsatlounge"
/area/turret_protected/AssistantRoom
name = "Assistant Room"
icon_state = "storage"
sd_lighting = 0
/////////////////////////////////////////////////////////////////////
/*
Lists of areas to be used with is_type_in_list.
@@ -10,6 +10,7 @@
var/icon/stand_icon = null
var/icon/lying_icon = null
var/icon/resting_icon = null
var/icon/running_icon = null
var/last_b_state = 1.0
-13
View File
@@ -58,19 +58,6 @@
var/temp = null
/obj/machinery/computer/hologram_comp
name = "Hologram Computer"
desc = "Rumoured to control holograms."
icon = 'stationobjs.dmi'
icon_state = "holo_console0"
var/obj/machinery/hologram/projector/projector = null
var/temp = null
var/lumens = 0.0
var/h_r = 245.0
var/h_g = 245.0
var/h_b = 245.0
/obj/machinery/computer/security
name = "Security Cameras"
desc = "Used to access the various cameras on the station."
+22 -8
View File
@@ -781,10 +781,10 @@
"/obj/item/clothing/head/collectable/xenom",
"/obj/item/clothing/head/collectable/xenom",
"/obj/item/clothing/head/collectable/petehat")
name = "Collectable Hat Crate!"
name = "Collectable hat crate!"
cost = 200
containertype = "/obj/structure/closet/crate/hat"
containername = "Collectable Hats Crate! Brought to you by Bass.inc!"
containername = "Collectable hats crate! Brought to you by Bass.inc!"
group = "Clothing"
/datum/supply_packs/hats/New()
@@ -795,20 +795,34 @@
..()
/datum/supply_packs/contraband
/datum/supply_packs/poster
contains = list("/obj/item/weapon/contraband/poster",) //We randomly pick 5 items from this list through the constructor, look below
name = "Contraband Crate"
name = "Poster crate"
cost = 30
containertype = "/obj/structure/closet/crate/contraband"
containername = "Contraband crate"
group = "ERROR"
containertype = "/obj/structure/closet/crate/poster"
containername = "Poster crate"
contraband = 1
group = "Secure Storage"
/datum/supply_packs/contraband/New()
/datum/supply_packs/poster/New()
var/list/tempContains = list()
for(var/i = 0,i<5,i++)
tempContains += pick(contains)
src.contains = tempContains
..()
/datum/supply_packs/cigarettes
contains = list("/obj/item/weapon/cigpacket/dromedaryco",
"/obj/item/weapon/cigpacket/dromedaryco",
"/obj/item/weapon/cigpacket/dromedaryco",
"/obj/item/weapon/cigpacket/dromedaryco",
"/obj/item/weapon/cigpacket/dromedaryco",
"/obj/item/weapon/cigpacket/dromedaryco",)
name = "DromedaryCo cigarettes crate"
cost = 15
containertype = "/obj/structure/closet/crate/cigarettes"
containername = "DromedaryCo cigarettes crate"
contraband = 1
group = "Secure Storage"
//SUPPLY PACKS
+11
View File
@@ -756,6 +756,17 @@
item_state = "fire_extinguisher"
m_amt = 90
/obj/item/weapon/extinguisher/mini
name = "fire extinguisher"
desc = "A light and compact fibreglass-framed model fire extinguisher."
icon_state = "miniFE0"
flags = FPRINT | USEDELAY | TABLEPASS
throwforce = 5
w_class = 2.0
force = 6.0
item_state = "miniFE"
m_amt = 0
/obj/item/weapon/f_card
name = "finger print card"
desc = "Used to take fingerprints."
+13
View File
@@ -127,6 +127,19 @@
index = findtext(t, char)
return t
//For sanitizing user inputs
/proc/reject_bad_text(var/text)
if(length(text) > 512) return //message too long
var/non_whitespace = 0
for(var/i=1, i<=length(text), i++)
switch(text2ascii(text,i))
if(62,60,92,47) return //rejects the text if it contains these bad characters: <, >, \ or /
if(127 to 255) return //rejects weird letters like ÿ
if(0 to 31) return //more weird stuff
if(32) //whitespace
else non_whitespace = 1
if(non_whitespace) return text //only accepts the text if it has some non-spaces
/proc/strip_html_simple(var/t,var/limit=MAX_MESSAGE_LEN)
var/list/strip_chars = list("<",">","&","'")
t = copytext(t,1,limit)
+9 -9
View File
@@ -6,12 +6,12 @@ world
Topic(href, href_list[])
world << "Received a Topic() call!"
world << "[href]"
for(var/a in href_list)
world << "[a]"
if(href_list["hello"])
world << "Hello world!"
return "Hello world!"
world << "End of Topic() call."
..()
// world << "Received a Topic() call!"
// world << "[href]"
// for(var/a in href_list)
// world << "[a]"
// if(href_list["hello"])
// world << "Hello world!"
// return "Hello world!"
// world << "End of Topic() call."
// ..()
+5 -2
View File
@@ -758,7 +758,7 @@
// if (!M.client)
// for(var/mob/dead/observer/ghost in world)
// if(ghost.corpse == M && ghost.client)
// ghost << "<b><font color = #330033><font size = 3>Your corpse has been placed into a cloning scanner. Return to your body if you want to be ressurected/cloned!</b> (Verbs -> Ghost -> Re-enter corpse)</font color>"
// ghost << "<b><font color = #330033><font size = 3>Your corpse has been placed into a cloning scanner. Return to your body if you want to be resurrected/cloned!</b> (Verbs -> Ghost -> Re-enter corpse)</font color>"
// break
del(G)
return
@@ -853,7 +853,10 @@
/obj/machinery/computer/scan_consolenew/New()
..()
spawn(5)
src.connected = locate(/obj/machinery/dna_scannernew, get_step(src, WEST))
for(dir in list(NORTH,EAST,SOUTH,WEST))
connected = locate(/obj/machinery/dna_scannernew, get_step(src, dir))
if(!isnull(connected))
break
spawn(250)
src.injectorready = 1
return
+1 -1
View File
@@ -317,7 +317,7 @@ var/datum/roundinfo/roundinfo = new()
if (aiPlayer.connected_robots.len)
var/robolist = "<b>The AI's loyal minions were:</b> "
for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.key]), ":", (Played by: [robo.key])"]"
robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.key]), ":" (Played by: [robo.key]), "]"
world << "[robolist]"
for (var/mob/living/silicon/robot/robo in world)
+1
View File
@@ -234,6 +234,7 @@
synd_mob.equip_if_possible(new /obj/item/ammo_magazine/a12mm(synd_mob), synd_mob.slot_in_backpack)
synd_mob.equip_if_possible(new /obj/item/weapon/reagent_containers/pill/cyanide(synd_mob), synd_mob.slot_in_backpack)
synd_mob.equip_if_possible(new /obj/item/weapon/gun/projectile/automatic/c20r(synd_mob), synd_mob.slot_belt)
synd_mob.equip_if_possible(new /obj/item/weapon/storage/box/engineer(synd_mob.back), synd_mob.slot_in_backpack)
var/datum/organ/external/O = pick(synd_mob.organs)
var/obj/item/weapon/implant/dexplosive/E = new/obj/item/weapon/implant/dexplosive(O)
O.implant += E
+117 -114
View File
@@ -13,131 +13,135 @@
var/updatesicon = 1
var/obj/machinery/computer/operating/computer = null
var/id = 0.0
New()
..()
if(!isnull(id))
for(var/obj/machinery/computer/operating/O in world)
if(src.id == O.id)
src.computer = O
/obj/machinery/optable/New()
..()
for(dir in list(NORTH,EAST,SOUTH,WEST))
computer = locate(/obj/machinery/computer/operating, get_step(src, dir))
if (!isnull(computer))
break
spawn(100)
process()
ex_act(severity)
switch(severity)
if(1.0)
/obj/machinery/optable/ex_act(severity)
switch(severity)
if(1.0)
//SN src = null
del(src)
return
if(2.0)
if (prob(50))
//SN src = null
del(src)
return
if(2.0)
if (prob(50))
//SN src = null
del(src)
return
if(3.0)
if (prob(25))
src.density = 0
else
return
blob_act()
if(prob(75))
del(src)
hand_p(mob/user as mob)
return src.attack_paw(user)
return
attack_paw(mob/user as mob)
if ((usr.mutations & HULK))
usr << text("\blue You destroy the operating table.")
for(var/mob/O in oviewers())
if ((O.client && !( O.blinded )))
O << text("\red [usr] destroys the operating table.")
src.density = 0
del(src)
if (!( locate(/obj/machinery/optable, user.loc) ))
step(user, get_dir(user, src))
if (user.loc == src.loc)
user.layer = TURF_LAYER
for(var/mob/M in viewers(user, null))
M.show_message("The monkey hides under the table!", 1)
//Foreach goto(69)
return
attack_hand(mob/user as mob)
if ((usr.mutations & HULK))
usr << text("\blue You destroy the table.")
for(var/mob/O in oviewers())
if ((O.client && !( O.blinded )))
O << text("\red [usr] destroys the table.")
src.density = 0
del(src)
return
CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0)) return 1
if(istype(mover) && mover.checkpass(PASSTABLE))
return 1
if(3.0)
if (prob(25))
src.density = 0
else
return 0
return
MouseDrop_T(obj/O as obj, mob/user as mob)
if(isrobot(user))
return
if ((!( istype(O, /obj/item/weapon) ) || user.equipped() != O))
return
user.drop_item()
if (O.loc != src.loc)
step(O, get_dir(O, src))
return
/obj/machinery/optable/blob_act()
if(prob(75))
del(src)
proc/check_victim()
if(locate(/mob/living/carbon, src.loc))
var/mob/M = locate(/mob/living/carbon, src.loc)
if(M.resting)
victim = M
if(updatesicon)
icon_state = "table2-active"
return 1
if(victim)
victim.update_clothing()
victim = null
if(updatesicon)
icon_state = "table2-idle"
processing_objects.Remove(src)
/obj/machinery/optable/hand_p(mob/user as mob)
return src.attack_paw(user)
return
/obj/machinery/optable/attack_paw(mob/user as mob)
if ((usr.mutations & HULK))
usr << text("\blue You destroy the operating table.")
for(var/mob/O in oviewers())
if ((O.client && !( O.blinded )))
O << text("\red [usr] destroys the operating table.")
src.density = 0
del(src)
if (!( locate(/obj/machinery/optable, user.loc) ))
step(user, get_dir(user, src))
if (user.loc == src.loc)
user.layer = TURF_LAYER
for(var/mob/M in viewers(user, null))
M.show_message("The monkey hides under the table!", 1)
//Foreach goto(69)
return
/obj/machinery/optable/attack_hand(mob/user as mob)
if ((usr.mutations & HULK))
usr << text("\blue You destroy the table.")
for(var/mob/O in oviewers())
if ((O.client && !( O.blinded )))
O << text("\red [usr] destroys the table.")
src.density = 0
del(src)
return
/obj/machinery/optable/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0)) return 1
if(istype(mover) && mover.checkpass(PASSTABLE))
return 1
else
return 0
process()
check_victim()
attackby(obj/item/weapon/W as obj, mob/user as mob)
if(isrobot(user))
return
if (istype(W, /obj/item/weapon/grab))
if(ismob(W:affecting))
var/mob/M = W:affecting
if (M.client)
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
M.resting = 1
M.loc = src.loc
for (var/mob/C in viewers(src))
C.show_message("\red [M] has been laid on the operating table by [user].", 3)
for(var/obj/O in src)
O.loc = src.loc
src.add_fingerprint(user)
if(updatesicon)
icon_state = "table2-active"
src.victim = M
M.update_clothing()
processing_objects.Add(src)
del(W)
return
user.drop_item()
if(W && W.loc)
W.loc = src.loc
/obj/machinery/optable/MouseDrop_T(obj/O as obj, mob/user as mob)
if(isrobot(user))
return
if ((!( istype(O, /obj/item/weapon) ) || user.equipped() != O))
return
user.drop_item()
if (O.loc != src.loc)
step(O, get_dir(O, src))
return
/obj/machinery/optable/proc/check_victim()
if(locate(/mob/living/carbon, src.loc))
var/mob/M = locate(/mob/living/carbon, src.loc)
if(M.resting)
victim = M
if(updatesicon)
icon_state = "table2-active"
return 1
if(victim)
victim.update_clothing()
victim = null
if(updatesicon)
icon_state = "table2-idle"
processing_objects.Remove(src)
return 0
/obj/machinery/optable/process()
check_victim()
/obj/machinery/optable/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(isrobot(user))
return
if (istype(W, /obj/item/weapon/grab))
if(ismob(W:affecting))
var/mob/M = W:affecting
if (M.client)
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
M.resting = 1
M.loc = src.loc
for (var/mob/C in viewers(src))
C.show_message("\red [M] has been laid on the operating table by [user].", 3)
for(var/obj/O in src)
O.loc = src.loc
src.add_fingerprint(user)
if(updatesicon)
icon_state = "table2-active"
src.victim = M
M.update_clothing()
processing_objects.Add(src)
del(W)
return
user.drop_item()
if(W && W.loc)
W.loc = src.loc
return
/obj/machinery/optable/portable
name = "mobile operating table"
@@ -146,7 +150,6 @@
icon_state = "up"
density = 1
anchored = 0
id = null
updatesicon = 0
New()
+1 -1
View File
@@ -149,9 +149,9 @@
if(clonename)
src.occupant.real_name = clonename
src.occupant.original_name = clonename //we don't want random ghost names should we die again.
else
src.occupant.real_name = "clone" //No null names!!
src.occupant.original_name = original_name
var/datum/mind/clonemind = (locate(mindref) in ticker.minds)
@@ -34,9 +34,6 @@
dat += "Please ensure that only holographic weapons are used in the holodeck if a combat simulation has been loaded.<BR>"
if(issilicon(user) && !emagged)
dat += "<A href='?src=\ref[src];AIoverride=1'>(<font color=red>Override Safety Protocols?</font>)</A><BR>"
if(emagged)
dat += "<A href='?src=\ref[src];burntest=1'>(<font color=red>Begin Atmospheric Burn Simulation</font>)</A><BR>"
dat += "Ensure the holodeck is empty before testing.<BR>"
@@ -46,6 +43,8 @@
dat += "<BR>"
dat += "Safety Protocols are <font color=red> DISABLED </font><BR>"
else
if(issilicon(user))
dat += "<A href='?src=\ref[src];AIoverride=1'>(<font color=red>Override Safety Protocols?</font>)</A><BR>"
dat += "<BR>"
dat += "Safety Protocols are <font color=green> ENABLED </font><BR>"
@@ -88,16 +87,19 @@
loadProgram(target)
else if(href_list["burntest"])
if(!emagged) return
target = locate(/area/holodeck/source_burntest)
if(target)
loadProgram(target)
else if(href_list["wildlifecarp"])
if(!emagged) return
target = locate(/area/holodeck/source_wildlife)
if(target)
loadProgram(target)
else if(href_list["AIoverride"])
if(!issilicon(usr)) return
emagged = 1
src.add_fingerprint(usr)
+13 -10
View File
@@ -5,15 +5,16 @@
desc = "Used to monitor status of people being operated on."
icon_state = "operating"
circuit = "/obj/item/weapon/circuitboard/operating"
var/mob/living/carbon/human/victim = null
var/obj/machinery/optable/table = null
var/id = 0.0
var
mob/living/carbon/human/victim = null
obj/machinery/optable/table = null
/obj/machinery/computer/operating/New()
..()
for(var/obj/machinery/optable/O in world)
if(src.id == O.id)
src.table = O
for(dir in list(NORTH,EAST,SOUTH,WEST))
table = locate(/obj/machinery/optable, get_step(src, dir))
if (!isnull(table))
break
/obj/machinery/computer/operating/attack_ai(mob/user)
add_fingerprint(user)
@@ -21,12 +22,14 @@
return
interact(user)
/obj/machinery/computer/operating/attack_hand(mob/user)
add_fingerprint(user)
if(stat & (BROKEN|NOPOWER))
return
interact(user)
/obj/machinery/computer/operating/proc/interact(mob/user)
if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) )
if (!istype(user, /mob/living/silicon))
@@ -43,7 +46,7 @@
<B>Patient Information:</B><BR>
<BR>
<B>Name:</B> [src.victim.real_name]<BR>
<B>Age:</B> [!isnull(src.victim.age) ? src.victim.age : "Undetermined"]<BR>
<B>Age:</B> [src.victim.age]<BR>
<B>Blood Type:</B> [src.victim.dna.b_type]<BR>
<BR>
<B>Health:</B> [src.victim.health]<BR>
@@ -51,7 +54,7 @@
<B>Toxins Damage:</B> [src.victim.getToxLoss()]<BR>
<B>Fire Damage:</B> [src.victim.getFireLoss()]<BR>
<B>Suffocation Damage:</B> [src.victim.getOxyLoss()]<BR>
<B>Patient Status:</B> [src.victim.stat ? "Non-responsive" : "Stable"]<BR>
<B>Patient Status:</B> [src.victim.stat ? "Non-Responsive" : "Stable"]<BR>
"}
else
src.victim = null
@@ -63,15 +66,15 @@
user << browse(dat, "window=op")
onclose(user, "op")
/obj/machinery/computer/operating/Topic(href, href_list)
if(..())
return
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
usr.machine = src
// if (href_list["update"])
// src.interact(usr)
return
/obj/machinery/computer/operating/process()
if(!(stat & (NOPOWER|BROKEN)) )
use_power(500)
+3 -1
View File
@@ -245,7 +245,9 @@
if (authenticated)
var/t1 = href_list["assign_target"]
if(t1 == "Custom")
t1 = input("Enter a custom job assignment.","Assignment")
var/temp_t = copytext(sanitize(input("Enter a custom job assignment.","Assignment")),1,MAX_MESSAGE_LEN)
if(temp_t)
t1 = temp_t
else
modify.access = ( istype(src,/obj/machinery/computer/card/centcom) ? get_centcom_access(t1) : get_access(t1) )
if (modify)
+14
View File
@@ -1,3 +1,17 @@
/obj/machinery/computer/hologram_comp
name = "Hologram Computer"
desc = "Rumoured to control holograms."
icon = 'stationobjs.dmi'
icon_state = "holo_console0"
var
obj/machinery/hologram/projector/projector = null
temp = null
lumens = 0.0
h_r = 245.0
h_g = 245.0
h_b = 245.0
/obj/machinery/computer/hologram_comp/New()
..()
spawn( 10 )
+253 -204
View File
@@ -1,5 +1,5 @@
/******************** Requests Console ********************/
/** Originally written by errorage, updated by: <sign your updates here> **/
/** Originally written by errorage, updated by: Carn, needs more work though. I just added some security fixes */
var/req_console_assistance = list()
var/req_console_supplies = list()
@@ -41,7 +41,7 @@ var/list/obj/machinery/requests_console/allConsoles = list()
// 9 = authentication before sending
// 10 = send announcement
var/silent = 0 // set to 1 for it not to beep all the time
var/hackState = 0
// var/hackState = 0
// 0 = not hacked
// 1 = hacked
var/announcementConsole = 0
@@ -57,270 +57,319 @@ var/list/obj/machinery/requests_console/allConsoles = list()
luminosity = 0
/obj/machinery/requests_console/New()
src.name = "[src.department] Requests Console"
name = "[department] Requests Console"
allConsoles += src
//req_console_departments += department
switch(src.departmentType)
switch(departmentType)
if(1)
if(!("[src.department]" in req_console_assistance))
if(!("[department]" in req_console_assistance))
req_console_assistance += department
if(2)
if(!("[src.department]" in req_console_supplies))
if(!("[department]" in req_console_supplies))
req_console_supplies += department
if(3)
if(!("[src.department]" in req_console_information))
if(!("[department]" in req_console_information))
req_console_information += department
if(4)
if(!("[src.department]" in req_console_assistance))
if(!("[department]" in req_console_assistance))
req_console_assistance += department
if(!("[src.department]" in req_console_supplies))
if(!("[department]" in req_console_supplies))
req_console_supplies += department
if(5)
if(!("[src.department]" in req_console_assistance))
if(!("[department]" in req_console_assistance))
req_console_assistance += department
if(!("[src.department]" in req_console_information))
if(!("[department]" in req_console_information))
req_console_information += department
if(6)
if(!("[src.department]" in req_console_supplies))
if(!("[department]" in req_console_supplies))
req_console_supplies += department
if(!("[src.department]" in req_console_information))
if(!("[department]" in req_console_information))
req_console_information += department
if(7)
if(!("[src.department]" in req_console_assistance))
if(!("[department]" in req_console_assistance))
req_console_assistance += department
if(!("[src.department]" in req_console_supplies))
if(!("[department]" in req_console_supplies))
req_console_supplies += department
if(!("[src.department]" in req_console_information))
if(!("[department]" in req_console_information))
req_console_information += department
/obj/machinery/requests_console/attack_hand(user as mob)
var/dat
dat = text("<HEAD><TITLE>Requests Console</TITLE></HEAD><H3>[src.department] Requests Console</H3>")
if(!src.open)
if (src.screen == 0)
announceAuth = 0
if (src.newmessagepriority == 1)
dat += text("<FONT COLOR='RED'>There are new messages</FONT><BR>")
if (src.newmessagepriority == 2)
dat += text("<FONT COLOR='RED'><B>NEW PRIORITY MESSAGES</B></FONT><BR>")
dat += text("<A href='?src=\ref[src];setScreen=[8]'>View Messages</A><BR><BR>")
dat = text("<HEAD><TITLE>Requests Console</TITLE></HEAD><H3>[department] Requests Console</H3>")
if(!open)
switch(screen)
if(1) //req. assistance
dat += text("Which department do you need assistance from?<BR><BR>")
for(var/dpt in req_console_assistance)
if (dpt != department)
dat += text("[dpt] (<A href='?src=\ref[src];write=[ckey(dpt)]'>Message</A> or ")
dat += text("<A href='?src=\ref[src];write=[ckey(dpt)];priority=2'>High Priority</A>")
// if (hackState == 1)
// dat += text(" or <A href='?src=\ref[src];write=[ckey(dpt)];priority=3'>EXTREME</A>)")
dat += text(")<BR>")
dat += text("<BR><A href='?src=\ref[src];setScreen=0'>Back</A><BR>")
if(2) //req. supplies
dat += text("Which department do you need supplies from?<BR><BR>")
for(var/dpt in req_console_supplies)
if (dpt != department)
dat += text("[dpt] (<A href='?src=\ref[src];write=[ckey(dpt)]'>Message</A> or ")
dat += text("<A href='?src=\ref[src];write=[ckey(dpt)];priority=2'>High Priority</A>")
// if (hackState == 1)
// dat += text(" or <A href='?src=\ref[src];write=[ckey(dpt)];priority=3'>EXTREME</A>)")
dat += text(")<BR>")
dat += text("<BR><A href='?src=\ref[src];setScreen=0'>Back</A><BR>")
if(3) //relay information
dat += text("Which department would you like to send information to?<BR><BR>")
for(var/dpt in req_console_information)
if (dpt != department)
dat += text("[dpt] (<A href='?src=\ref[src];write=[ckey(dpt)]'>Message</A> or ")
dat += text("<A href='?src=\ref[src];write=[ckey(dpt)];priority=2'>High Priority</A>")
// if (hackState == 1)
// dat += text(" or <A href='?src=\ref[src];write=[ckey(dpt)];priority=3'>EXTREME</A>)")
dat += text(")<BR>")
dat += text("<BR><A href='?src=\ref[src];setScreen=0'>Back</A><BR>")
if(6) //sent successfully
dat += text("<FONT COLOR='GREEN'>Message sent</FONT><BR><BR>")
dat += text("<A href='?src=\ref[src];setScreen=0'>Continue</A><BR>")
if(7) //unsuccessful; not sent
dat += text("<FONT COLOR='RED'>An error occurred. </FONT><BR><BR>")
dat += text("<A href='?src=\ref[src];setScreen=0'>Continue</A><BR>")
if(8) //view messages
for (var/obj/machinery/requests_console/Console in allConsoles)
if (Console.department == department)
Console.newmessagepriority = 0
Console.icon_state = "req_comp0"
Console.luminosity = 1
newmessagepriority = 0
icon_state = "req_comp0"
for(var/msg in messages)
dat += text("[msg]<BR>")
dat += text("<A href='?src=\ref[src];setScreen=0'>Back to main menu</A><BR>")
if(9) //authentication before sending
dat += text("<B>Message Authentication</B><BR><BR>")
dat += text("<b>Message for [dpt]: </b>[message]<BR><BR>")
dat += text("You may authenticate your message now by scanning your ID or your stamp<BR><BR>")
dat += text("Validated by: [msgVerified]<br>");
dat += text("Stamped by: [msgStamped]<br>");
dat += text("<A href='?src=\ref[src];department=[dpt]'>Send</A><BR>");
dat += text("<BR><A href='?src=\ref[src];setScreen=0'>Back</A><BR>")
if(10) //send announcement
dat += text("<B>Station wide announcement</B><BR><BR>")
if(announceAuth)
dat += text("<b>Authentication accepted</b><BR><BR>")
else
dat += text("Swipe your card to authenticate yourself.<BR><BR>")
dat += text("<b>Message: </b>[message] <A href='?src=\ref[src];writeAnnouncement=1'>Write</A><BR><BR>")
if (announceAuth && message)
dat += text("<A href='?src=\ref[src];sendAnnouncement=1'>Announce</A><BR>");
dat += text("<BR><A href='?src=\ref[src];setScreen=0'>Back</A><BR>")
else //main menu
screen = 0
announceAuth = 0
if (newmessagepriority == 1)
dat += text("<FONT COLOR='RED'>There are new messages</FONT><BR>")
if (newmessagepriority == 2)
dat += text("<FONT COLOR='RED'><B>NEW PRIORITY MESSAGES</B></FONT><BR>")
dat += text("<A href='?src=\ref[src];setScreen=8'>View Messages</A><BR><BR>")
dat += text("<A href='?src=\ref[src];setScreen=1'>Request Assistance</A><BR>")
dat += text("<A href='?src=\ref[src];setScreen=2'>Request Supplies</A><BR>")
dat += text("<A href='?src=\ref[src];setScreen=3'>Relay Anonymous Information</A><BR><BR>")
if(announcementConsole)
dat += text("<A href='?src=\ref[src];setScreen=10'>Send station-wide announcement</A><BR><BR>")
if (silent)
dat += text("Speaker <A href='?src=\ref[src];setSilent=0'>OFF</A>")
else
dat += text("Speaker <A href='?src=\ref[src];setSilent=1'>ON</A>")
dat += text("<A href='?src=\ref[src];setScreen=[1]'>Request Assistance</A><BR>")
dat += text("<A href='?src=\ref[src];setScreen=[2]'>Request Supplies</A><BR>")
dat += text("<A href='?src=\ref[src];setScreen=[3]'>Relay Anonymous Information</A><BR><BR>")
if(announcementConsole)
dat += text("<A href='?src=\ref[src];setScreen=[10]'>Send station-wide announcement</A><BR><BR>")
//dat += text("<BR><A href='?src=\ref[src];callMailman=[1];location=[src.department]'>Call Mailman</A><BR><BR>") // This is the line to call the mailman, it's intended for it to message him on his PDA
if (src.silent)
dat += text("Speaker <A href='?src=\ref[src];setSilent=[0]'>OFF</A>")
else
dat += text("Speaker <A href='?src=\ref[src];setSilent=[1]'>ON</A>")
if (src.screen == 1)
dat += text("Which department do you need assistance from?<BR><BR>")
for(var/dpt in req_console_assistance)
if (dpt != src.department)
dat += text("[dpt] (<A href='?src=\ref[src];write=[ckey(dpt)]'>Message</A> or ")
dat += text("<A href='?src=\ref[src];write=[ckey(dpt)];priority=[2]'>High Priority</A>")
if (src.hackState == 1)
dat += text(" or <A href='?src=\ref[src];write=[ckey(dpt)];priority=[3]'>EXTREME</A>)")
dat += text(")<BR>")
dat += text("<BR><A href='?src=\ref[src];setScreen=[0]'>Back</A><BR>")
if (src.screen == 2)
dat += text("Which department do you need supplies from?<BR><BR>")
for(var/dpt in req_console_supplies)
if (dpt != src.department)
dat += text("[dpt] (<A href='?src=\ref[src];write=[ckey(dpt)]'>Message</A> or ")
dat += text("<A href='?src=\ref[src];write=[ckey(dpt)];priority=[2]'>High Priority</A>")
if (src.hackState == 1)
dat += text(" or <A href='?src=\ref[src];write=[ckey(dpt)];priority=[3]'>EXTREME</A>)")
dat += text(")<BR>")
dat += text("<BR><A href='?src=\ref[src];setScreen=[0]'>Back</A><BR>")
if (src.screen == 3)
dat += text("Which department would you like to send information to?<BR><BR>")
for(var/dpt in req_console_information)
if (dpt != src.department)
dat += text("[dpt] (<A href='?src=\ref[src];write=[ckey(dpt)]'>Message</A> or ")
dat += text("<A href='?src=\ref[src];write=[ckey(dpt)];priority=[2]'>High Priority</A>")
if (src.hackState == 1)
dat += text(" or <A href='?src=\ref[src];write=[ckey(dpt)];priority=[3]'>EXTREME</A>)")
dat += text(")<BR>")
dat += text("<BR><A href='?src=\ref[src];setScreen=[0]'>Back</A><BR>")
if (src.screen == 6)
dat += text("<FONT COLOR='GREEN'>Message sent</FONT><BR><BR>")
dat += text("<A href='?src=\ref[src];setScreen=[0]'>Continue</A><BR>")
if (src.screen == 7)
dat += text("<FONT COLOR='RED'>An error occurred. </FONT><BR><BR>")
dat += text("<A href='?src=\ref[src];setScreen=[0]'>Continue</A><BR>")
if (src.screen == 8)
for (var/obj/machinery/requests_console/CONSOLE in allConsoles)
if (CONSOLE.department == src.department)
CONSOLE.newmessagepriority = 0
CONSOLE.icon_state = "req_comp0"
CONSOLE.luminosity = 1
src.newmessagepriority = 0
icon_state = "req_comp0"
for(var/msg in src.messages)
dat += text("[msg]<BR>")
dat += text("<A href='?src=\ref[src];setScreen=[0]'>Back to main menu</A><BR>")
if (src.screen == 9)
dat += text("<B>Message Authentication</B><BR><BR>")
dat += text("<b>Message for [src.dpt]: </b>[message]<BR><BR>")
dat += text("You may authenticate your message now by scanning your ID or your stamp<BR><BR>")
dat += text("Validated by: [msgVerified]<br>");
dat += text("Stamped by: [msgStamped]<br>");
dat += text("<A href='?src=\ref[src];department=[src.dpt]'>Send</A><BR>");
dat += text("<BR><A href='?src=\ref[src];setScreen=[0]'>Back</A><BR>")
if (src.screen == 10)
dat += text("<B>Station wide announcement</B><BR><BR>")
if(announceAuth)
dat += text("<b>Authentication accepted</b><BR><BR>")
else
dat += text("Swipe your card to authenticate yourself.<BR><BR>")
dat += text("<b>Message: </b>[message] <A href='?src=\ref[src];writeAnnouncement=[1]'>Write</A><BR><BR>")
if (announceAuth && message)
dat += text("<A href='?src=\ref[src];sendAnnouncement=[1]'>Announce</A><BR>");
dat += text("<BR><A href='?src=\ref[src];setScreen=[0]'>Back</A><BR>")
user << browse("[dat]", "")
onclose(user, "req_console")
return
/obj/machinery/requests_console/Topic(href, href_list)
if(..())
return
if(..()) return
usr.machine = src
src.add_fingerprint(usr)
if(href_list["write"])
src.dpt = href_list["write"] //write contains the string of the receiving department's name
src.message = strip_html(input(usr, "Write your message", "Messanger", ""))
src.priority = href_list["priority"]
while (findtext(src.message," ") == 1)
src.message = copytext(src.message,2,lentext(src.message)+1)
if (findtext(src.message," ") == 1)
src.message = "";
if (src.message != "")
add_fingerprint(usr)
if(reject_bad_text(href_list["write"]))
dpt = ckey(href_list["write"]) //write contains the string of the receiving department's name
var/new_message = reject_bad_text(input(usr, "Write your message:", "Awaiting Input", ""))
if(new_message)
message = new_message
screen = 9
switch(href_list["priority"])
if("2") priority = 2
else priority = -1
else
dpt = "";
msgVerified = "";
msgStamped = "";
msgVerified = ""
msgStamped = ""
screen = 0
priority = -1
if(href_list["writeAnnouncement"])
src.message = input(usr, "Write your message", "Messanger", "")
src.priority = href_list["priority"]
while (findtext(src.message," ") == 1)
src.message = copytext(src.message,2,lentext(src.message)+1)
if (findtext(src.message," ") == 1)
src.message = "";
if (src.message == "")
announceAuth = 0;
var/new_message = reject_bad_text(input(usr, "Write your message:", "Awaiting Input", ""))
if(new_message)
message = new_message
switch(href_list["priority"])
if("2") priority = 2
else priority = -1
else
message = ""
announceAuth = 0
screen = 0
if(href_list["sendAnnouncement"])
world << "<b><font size = 3><font color = red>[department] announcement:</font color> [html_encode(message)]</font size></b>"
if(!announcementConsole) return
world << "<b><font size = 3><font color = red>[department] announcement:</font color> [message]</font size></b>"
announceAuth = 0
message = ""
screen = 0
if(href_list["department"] && src.message)
var/log_msg = src.message
var/message = src.message;
message += "<br>"
if (src.msgVerified)
message += src.msgVerified
message += "<br>"
if (src.msgStamped)
message += src.msgStamped
message += "<br>"
src.screen = 7 //if it's successful, this will get overrwritten (7 = unsufccessfull, 6 = successfull)
if (message)
if( href_list["department"] && message )
var/log_msg = message
var/sending = message
sending += "<br>"
if (msgVerified)
sending += msgVerified
sending += "<br>"
if (msgStamped)
sending += msgStamped
sending += "<br>"
screen = 7 //if it's successful, this will get overrwritten (7 = unsufccessfull, 6 = successfull)
if (sending)
for (var/obj/machinery/message_server/MS in world)
MS.send_rc_message(href_list["department"],src.department,log_msg,msgStamped,msgVerified,priority)
for (var/obj/machinery/requests_console/CONSOLE in allConsoles)
if (ckey(CONSOLE.department) == ckey(href_list["department"]))
if(src.priority == "2") //High priority
if(CONSOLE.newmessagepriority < 2)
CONSOLE.newmessagepriority = 2
CONSOLE.icon_state = "req_comp2"
if(!CONSOLE.silent)
playsound(CONSOLE.loc, 'twobeep.ogg', 50, 1)
for (var/mob/O in hearers(5, CONSOLE.loc))
O.show_message(text("\icon[CONSOLE] *The Requests Console beeps: 'PRIORITY Alert in [src.department]'"))
CONSOLE.messages += "<B><FONT color='red'>High Priority message from <A href='?src=\ref[CONSOLE];write=[ckey(src.department)]'>[src.department]</A></FONT></B><BR>[message]"
else if(src.priority == "3"
) //Not implemanted, but will be
if(CONSOLE.newmessagepriority < 3)
CONSOLE.newmessagepriority = 3
CONSOLE.icon_state = "req_comp3"
if(!CONSOLE.silent)
playsound(CONSOLE.loc, 'twobeep.ogg', 50, 1)
for (var/mob/O in hearers(7, CONSOLE.loc))
O.show_message(text("\icon[CONSOLE] *The Requests Console yells: 'EXTREME PRIORITY alert in [src.department]'"))
CONSOLE.messages += "<B><FONT color='red'>Extreme Priority message from [ckey(src.department)]</FONT></B><BR>[message]"
else // Normal priority
if(CONSOLE.newmessagepriority < 1)
CONSOLE.newmessagepriority = 1
CONSOLE.icon_state = "req_comp1"
if(!CONSOLE.silent)
playsound(CONSOLE.loc, 'twobeep.ogg', 50, 1)
for (var/mob/O in hearers(4, CONSOLE.loc))
O.show_message(text("\icon[CONSOLE] *The Requests Console beeps: 'Message from [src.department]'"))
CONSOLE.messages += "<B>Message from <A href='?src=\ref[CONSOLE];write=[ckey(src.department)]'>[src.department]</A></FONT></B><BR>[message]"
src.screen = 6
CONSOLE.luminosity = 2
src.messages += "<B>Message sent to [src.dpt]</B><BR>[message]"
if(href_list["setScreen"])
src.screen = text2num(href_list["setScreen"])
if (src.screen == 0)
dpt = "";
msgVerified = "";
msgStamped = "";
message = "";
priority = -1;
if(href_list["setSilent"])
src.silent = text2num(href_list["setSilent"])
src.updateUsrDialog()
MS.send_rc_message(href_list["department"],department,log_msg,msgStamped,msgVerified,priority)
for (var/obj/machinery/requests_console/Console in allConsoles)
if (ckey(Console.department) == ckey(href_list["department"]))
switch(priority)
if("2") //High priority
if(Console.newmessagepriority < 2)
Console.newmessagepriority = 2
Console.icon_state = "req_comp2"
if(!Console.silent)
playsound(Console.loc, 'twobeep.ogg', 50, 1)
for (var/mob/O in hearers(5, Console.loc))
O.show_message(text("\icon[Console] *The Requests Console beeps: 'PRIORITY Alert in [department]'"))
Console.messages += "<B><FONT color='red'>High Priority message from <A href='?src=\ref[Console];write=[ckey(department)]'>[department]</A></FONT></B><BR>[sending]"
// if("3") //Not implemanted, but will be //Removed as it doesn't look like anybody intends on implimenting it ~Carn
// if(Console.newmessagepriority < 3)
// Console.newmessagepriority = 3
// Console.icon_state = "req_comp3"
// if(!Console.silent)
// playsound(Console.loc, 'twobeep.ogg', 50, 1)
// for (var/mob/O in hearers(7, Console.loc))
// O.show_message(text("\icon[Console] *The Requests Console yells: 'EXTREME PRIORITY alert in [department]'"))
// Console.messages += "<B><FONT color='red'>Extreme Priority message from [ckey(department)]</FONT></B><BR>[message]"
else // Normal priority
if(Console.newmessagepriority < 1)
Console.newmessagepriority = 1
Console.icon_state = "req_comp1"
if(!Console.silent)
playsound(Console.loc, 'twobeep.ogg', 50, 1)
for (var/mob/O in hearers(4, Console.loc))
O.show_message(text("\icon[Console] *The Requests Console beeps: 'Message from [department]'"))
Console.messages += "<B>Message from <A href='?src=\ref[Console];write=[ckey(department)]'>[department]</A></FONT></B><BR>[message]"
screen = 6
Console.luminosity = 2
messages += "<B>Message sent to [dpt]</B><BR>[message]"
//Handle screen switching
switch(text2num(href_list["setScreen"]))
if(null) //skip
if(1) //req. assistance
screen = 1
if(2) //req. supplies
screen = 2
if(3) //relay information
screen = 3
// if(4) //write message
// screen = 4
if(5) //choose priority
screen = 5
if(6) //sent successfully
screen = 6
if(7) //unsuccessfull; not sent
screen = 7
if(8) //view messages
screen = 8
if(9) //authentication
screen = 9
if(10) //send announcement
if(!announcementConsole) return
screen = 10
else //main menu
dpt = ""
msgVerified = ""
msgStamped = ""
message = ""
priority = -1
screen = 0
//Handle silencing the console
switch( href_list["setSilent"] )
if(null) //skip
if("1") silent = 1
else silent = 0
updateUsrDialog()
return
//err... hacking code, which has no reason for existing... but anyway... it's supposed to unlock priority 3 messanging on that console (EXTREME priority...) the code for that actually exists.
/obj/machinery/requests_console/attackby(var/obj/item/weapon/O as obj, var/mob/user as mob)
/*
if (istype(O, /obj/item/weapon/crowbar))
if(src.open)
src.open = 0
src.icon_state="req_comp0"
if(open)
open = 0
icon_state="req_comp0"
else
src.open = 1
if(src.hackState == 0)
src.icon_state="req_comp_open"
else if(src.hackState == 1)
src.icon_state="req_comp_rewired"
open = 1
if(hackState == 0)
icon_state="req_comp_open"
else if(hackState == 1)
icon_state="req_comp_rewired"
if (istype(O, /obj/item/weapon/screwdriver))
if(src.open)
if(src.hackState == 0)
src.hackState = 1
src.icon_state="req_comp_rewired"
else if(src.hackState == 1)
src.hackState = 0
src.icon_state="req_comp_open"
if(open)
if(hackState == 0)
hackState = 1
icon_state="req_comp_rewired"
else if(hackState == 1)
hackState = 0
icon_state="req_comp_open"
else
user << "You can't do much with that."*/
if (istype(O, /obj/item/weapon/card/id))
if(src.screen == 9)
if(screen == 9)
var/obj/item/weapon/card/id/T = O
src.msgVerified = text("<font color='green'><b>Verified by [T.registered_name] ([T.assignment])</b></font>")
src.updateUsrDialog()
if(src.screen == 10)
msgVerified = text("<font color='green'><b>Verified by [T.registered_name] ([T.assignment])</b></font>")
updateUsrDialog()
if(screen == 10)
var/obj/item/weapon/card/id/ID = O
if (access_RC_announce in ID.access)
announceAuth = 1
else
announceAuth = 0
user << "\red You are not authorized to send announcements."
src.updateUsrDialog()
updateUsrDialog()
if (istype(O, /obj/item/weapon/stamp))
if(src.screen == 9)
if(screen == 9)
var/obj/item/weapon/stamp/T = O
src.msgStamped = text("<font color='blue'><b>Stamped with the [T.name]</b></font>")
src.updateUsrDialog()
return
msgStamped = text("<font color='blue'><b>Stamped with the [T.name]</b></font>")
updateUsrDialog()
return
@@ -103,11 +103,10 @@
if(machine.is_freq_listening(signal))
machine.traffic++
spawn()
if(copysig && copy)
machine.receive_information(copy, src)
else
machine.receive_information(signal, src)
if(copysig && copy)
machine.receive_information(copy, src)
else
machine.receive_information(signal, src)
if(send_count > 0 && is_freq_listening(signal))
traffic++
+4 -2
View File
@@ -56,8 +56,10 @@
for(var/obj/item/device/radio/beacon/R in world)
var/turf/T = get_turf(R)
if (!T) continue
if(T.z == 2) continue
if (!T)
continue
if(T.z == 2)
continue
var/tmpname = T.loc.name
if(areaindex[tmpname])
tmpname = "[tmpname] ([++areaindex[tmpname]])"
+4
View File
@@ -11,6 +11,8 @@
//TODO: make teleporting to places trigger Entered() ~Carn
// Done.
/area/turret_protected/Entered(O)
..()
if( master && master != src )
@@ -84,6 +86,7 @@
anchored = 1
layer = 3.5
density = 0
var/obj/machinery/turret/host = null
/obj/machinery/turret/proc/isPopping()
return (popping!=0)
@@ -157,6 +160,7 @@
return
if(src.cover==null)
src.cover = new /obj/machinery/turretcover(src.loc)
src.cover.host = src
protected_area = get_protected_area()
if(!enabled || !protected_area || protected_area.turretTargets.len<=0)
if(!isDown() && !isPopping())
+11 -17
View File
@@ -759,22 +759,19 @@ datum/borrowbook // Datum used to keep track of who has borrowed what when and f
B.name = ticker.Bible_name
B.deity_name = ticker.Bible_deity_name
bibledelay = 60
spawn(0)
while(bibledelay >= 1 && src)
sleep(10)
bibledelay -- // subtract one second to countdown
bibledelay = 1
spawn(60)
bibledelay = 0
else
for (var/mob/V in hearers(src))
V.show_message("<b>[src]</b>'s monitor flashes, \"[bibledelay] seconds remaining until the bible printer is ready for use.\"")
V.show_message("<b>[src]</b>'s monitor flashes, \"Bible printer currently unavailable, please wait a moment.\"")
if("7")
screenstate = 7
if(href_list["arccheckout"])
src.arcanecheckout = 1
if(src.emagged)
src.arcanecheckout = 1
src.screenstate = 0
if(href_list["increasetime"])
checkoutperiod += 1
@@ -865,22 +862,19 @@ datum/borrowbook // Datum used to keep track of who has borrowed what when and f
alert("Upload Complete.")
if(href_list["targetid"])
if(!bibledelay)//Taken from the bible code part thing
bibledelay = 60
spawn(0)
while(bibledelay >= 1 && src)
sleep(10)
bibledelay -- // subtract one second to countdown
bibledelay = 0
if(BOOKS_USE_SQL && config.sql_enabled)
var/sqlid = href_list["targetid"]
var/DBConnection/dbcon = new()
dbcon.Connect("dbi:mysql:[sqldb]:[sqladdress]:[sqlport]","[sqllogin]","[sqlpass]")
if(!dbcon.IsConnected())
alert("Connection to Archive has been severed. Aborting.")
if(bibledelay)
for (var/mob/V in hearers(src))
V.show_message("<b>[src]</b>'s monitor flashes, \"Printer unavailable. Please allow a short time before attempting to print.\"")
else
bibledelay = 1
spawn(60)
bibledelay = 0
var/DBQuery/query = dbcon.NewQuery("SELECT * FROM library WHERE id=[sqlid]")
query.Execute()
+3 -3
View File
@@ -5,9 +5,9 @@
tempo = 5
/obj/structure/device/piano
name = "space piano"
name = "space minimoog"
icon = 'musician.dmi'
icon_state = "piano"
icon_state = "minimoog"
anchored = 1
density = 1
var
@@ -500,7 +500,7 @@
if(href_list["import"])
var/t = ""
do
t = input(usr, "Please paste the entire song, formated:", text("[]", src.name), t) as message
t = input(usr, "Please paste the entire song, formatted:", text("[]", src.name), t) as message
if (!in_range(src, usr))
return
+2
View File
@@ -47,6 +47,8 @@ datum/controller/game_controller
world.tick_lag = config.Ticklag
createRandomZlevel()
// Sleep for about 5 seconds to allow background initialization procs to finish
sleep(50)
+19
View File
@@ -92,6 +92,12 @@
R.my_atom = src
R.add_reagent("water", 50)
/obj/item/weapon/extinguisher/mini/New()
var/datum/reagents/R = new/datum/reagents(30)
reagents = R
R.my_atom = src
R.add_reagent("water", 30)
/obj/item/weapon/extinguisher/examine()
set src in usr
@@ -174,6 +180,19 @@
safety = 1
return
/obj/item/weapon/extinguisher/mini/attack_self(mob/user as mob)
if (safety)
src.icon_state = "miniFE1"
src.desc = "The safety is off."
user << "The safety is off."
safety = 0
else
src.icon_state = "miniFE0"
src.desc = "The safety is on."
user << "The safety is on."
safety = 1
return
/obj/item/weapon/pen/attack(mob/M as mob, mob/user as mob)
if(!ismob(M))
return
@@ -4,6 +4,7 @@ MATCHES
MATCHBOXES
CIGARETTES
CIGARS
SMOKING PIPES
CIG PACKET
ZIPPO
*/
@@ -329,7 +330,7 @@ ZIPPO
//CIG PACK//
////////////
/obj/item/weapon/cigpacket
name = "Cigarette packet"
name = "cigarette packet"
desc = "The most popular brand of Space Cigarettes, sponsors of the Space Olympics."
icon = 'cigarettes.dmi'
icon_state = "cigpacket"
@@ -342,26 +343,30 @@ ZIPPO
update_icon()
src.icon_state = text("cigpacket[]", src.cigcount)
src.desc = text("There are [] cigs\s left!", src.cigcount)
icon_state = "[initial(icon_state)][cigcount]"
desc = "There's [cigcount] cig\s left!"
return
attack_hand(mob/user as mob)
if(user.r_hand == src || user.l_hand == src)
if(src.cigcount == 0)
if(cigcount == 0)
user << "\red You're out of cigs, shit! How you gonna get through the rest of the day..."
return
else
src.cigcount--
cigcount--
var/obj/item/clothing/mask/cigarette/W = new /obj/item/clothing/mask/cigarette(user)
user.put_in_hand(W)
else
return ..()
src.update_icon()
update_icon()
return
/obj/item/weapon/cigpacket/dromedaryco
name = "DromedaryCo packet"
desc = "A packet of six imported DromedaryCo cancer sticks. A label on the packaging reads, \"Wouldn't a slow death make a change?\""
icon_state = "Dpacket"
item_state = "Dpacket"
/////////
//ZIPPO//
+29
View File
@@ -275,4 +275,33 @@
if(!devastated)
for(var/i = 1, i <= oreAmount, i++)
new/obj/item/stack/sheet/wood(get_turf(src))
del(src)
/obj/structure/mineral_door/resin
mineralType = "resin"
hardness = 5
Open()
isSwitchingStates = 1
playsound(loc, 'attackblob.ogg', 100, 1)
flick("[mineralType]opening",src)
sleep(10)
density = 0
opacity = 0
state = 1
update_icon()
isSwitchingStates = 0
Close()
isSwitchingStates = 1
playsound(loc, 'attackblob.ogg', 100, 1)
flick("[mineralType]closing",src)
sleep(10)
density = 1
opacity = 1
state = 0
update_icon()
isSwitchingStates = 0
Dismantle(devastated = 0)
del(src)
+1 -1
View File
@@ -72,7 +72,7 @@ var/global/list/datum/stack_recipe/metal_recipes = list ( \
new/datum/stack_recipe("rack parts", /obj/item/weapon/rack_parts), \
new/datum/stack_recipe("closet", /obj/structure/closet, 2, one_per_turf = 1, on_floor = 1), \
null, \
new/datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 2, one_per_turf = 1, on_floor = 1), \
new/datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 10, one_per_turf = 1, on_floor = 1), \
null, \
new/datum/stack_recipe("floor tile", /obj/item/stack/tile/plasteel, 1, 4, 10), \
new/datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60), \
+12 -3
View File
@@ -38,9 +38,18 @@
icon_opened = "crateopen"
icon_closed = "crate"
/obj/structure/closet/crate/contraband
name = "Contraband crate"
desc = "A random assortment of items manufactured by providers NOT listed under Nanotrasen's whitelist."
/obj/structure/closet/crate/poster
name = "Poster crate"
desc = "A random assortment of posters manufactured by providers NOT listed under Nanotrasen's whitelist."
icon = 'storage.dmi'
icon_state = "crate"
density = 1
icon_opened = "crateopen"
icon_closed = "crate"
/obj/structure/closet/crate/cigarettes
name = "DromedaryCo cigarettes crate"
desc = "A crate of cigarettes manufactured by the notorious DromedaryCo company."
icon = 'storage.dmi'
icon_state = "crate"
density = 1
+1 -1
View File
@@ -1,7 +1,7 @@
/obj/item/weapon/storage/toolbox/emergency/New()
..()
new /obj/item/weapon/crowbar/red(src)
new /obj/item/weapon/extinguisher(src)
new /obj/item/weapon/extinguisher/mini(src)
if(prob(50))
new /obj/item/device/flashlight(src)
new /obj/item/device/radio(src)
+1 -1
View File
@@ -33,7 +33,7 @@
if(usr.client.holder)
usr << "[M.key] is a [M.client.holder.rank][M.client.stealth ? " <i>(as [M.client.fakekey])</i>" : ""]"
else if(!M.client.stealth && (M.client.holder.level != -3))
usr << "\t[pick(nobles)] [M.client]"
usr << "\t[pick(nobles)] [M.client] is a [M.client.holder.rank]"
var/list/nobles = list("Baron","Bookkeeper","Captain of the Guard","Chief Medical Dwarf","Count","Dungeon Master","Duke","General","Mayor","Outpost Liaison","Sheriff","Champion")
+2 -2
View File
@@ -243,7 +243,7 @@
verbs += /client/proc/cmd_admin_world_narrate
verbs += /client/proc/cmd_debug_del_all
verbs += /client/proc/cmd_debug_tog_aliens
verbs += /client/proc/mapload
// verbs += /client/proc/mapload
verbs += /client/proc/check_words
verbs += /client/proc/drop_bomb
verbs += /client/proc/kill_airgroup
@@ -347,7 +347,7 @@
verbs -= /client/proc/Cell
verbs -= /client/proc/cmd_debug_del_all
verbs -= /client/proc/cmd_debug_tog_aliens
verbs -= /client/proc/mapload
// verbs -= /client/proc/mapload
verbs -= /client/proc/check_words
verbs -= /client/proc/drop_bomb
//verbs -= /client/proc/cmd_admin_drop_everything --merged with view variables
+1 -1
View File
@@ -15,7 +15,7 @@
var/quick_create_object_html = null
var/pathtext = null
pathtext = input("Select the path of the object you wish to create.", "Path", "/obj") in list("/obj","/obj/structure","/obj/item","/obj/machinery")
pathtext = input("Select the path of the object you wish to create.", "Path", "/obj") in list("/obj","/obj/structure","/obj/item","/obj/item/weapon","/obj/machinery")
var path = text2path(pathtext)
+90 -84
View File
@@ -33,107 +33,108 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/callproc()
set category = "Debug"
set name = "Advanced ProcCall (TG Version)"
if(!holder)
src << "Only administrators may use this command."
return
var/target = null
var/lst[] // List reference
lst = new/list() // Make the list
var/returnval = null
var/class = null
switch(alert("Proc owned by something?",,"Yes","No"))
if("Yes")
class = input("Proc owned by...","Owner") in list("Obj","Mob","Area or Turf","Client","CANCEL ABORT STOP")
spawn(0)
var/target = null
var/targetselected = 0
var/lst[] // List reference
lst = new/list() // Make the list
var/returnval = null
var/class = null
switch(alert("Proc owned by something?",,"Yes","No"))
if("Yes")
targetselected = 1
class = input("Proc owned by...","Owner",null) as null|anything in list("Obj","Mob","Area or Turf","Client")
switch(class)
if("Obj")
target = input("Enter target:","Target",usr) as obj in world
if("Mob")
target = input("Enter target:","Target",usr) as mob in world
if("Area or Turf")
target = input("Enter target:","Target",usr.loc) as area|turf in world
if("Client")
var/list/keys = list()
for(var/client/C)
keys += C
target = input("Please, select a player!", "Selection", null, null) as null|anything in keys
else
return
if("No")
target = null
targetselected = 0
var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
if(!procname) return
var/argnum = input("Number of arguments","Number:",0) as num|null
if(!argnum && (argnum!=0)) return
lst.len = argnum // Expand to right length
//TODO: make a list to store whether each argument was initialised as null.
//Reason: So we can abort the proccall if say, one of our arguments was a mob which no longer exists
//this will protect us from a fair few errors ~Carn
var/i
for(i=1, i<argnum+1, i++) // Lists indexed from 1 forwards in byond
// Make a list with each index containing one variable, to be given to the proc
class = input("What kind of variable?","Variable Type") in list("text","num","type","reference","mob reference","icon","file","client","mob's area","CANCEL")
switch(class)
if("CANCEL ABORT STOP")
if("CANCEL")
return
if("Obj")
target = input("Enter target:","Target",usr) as obj in world
if("Mob")
target = input("Enter target:","Target",usr) as mob in getmobs()
if("Area or Turf")
target = input("Enter target:","Target",usr.loc) as area|turf in world
if("Client")
if("text")
lst[i] = input("Enter new text:","Text",null) as text
if("num")
lst[i] = input("Enter new number:","Num",0) as num
if("type")
lst[i] = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf)
if("reference")
lst[i] = input("Select reference:","Reference",src) as mob|obj|turf|area in world
if("mob reference")
lst[i] = input("Select reference:","Reference",usr) as mob in world
if("file")
lst[i] = input("Pick file:","File") as file
if("icon")
lst[i] = input("Pick icon:","Icon") as icon
if("client")
var/list/keys = list()
for(var/mob/M in world)
keys += M.client
target = input("Please, select a player!", "Selection", null, null) as null|anything in keys
if("No")
target = null
lst[i] = input("Please, select a player!", "Selection", null, null) as null|anything in keys
var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null)
if("mob's area")
var/mob/temp = input("Select mob", "Selection", usr) as mob in world
lst[i] = temp.loc
var/argnum = input("Number of arguments","Number:",0) as num
lst.len = argnum // Expand to right length
var/i
for(i=1, i<argnum+1, i++) // Lists indexed from 1 forwards in byond
// Make a list with each index containing one variable, to be given to the proc
class = input("What kind of variable?","Variable Type") in list("text","num","type","reference","mob reference","icon","file","client","mob's area","CANCEL")
switch(class)
if("CANCEL")
if(targetselected)
if(!target)
usr << "<font color='red'>Error: callproc(): owner of proc no longer exists.</font>"
return
if(!hascall(target,procname))
usr << "<font color='red'>Error: callproc(): target has no such call [procname].</font>"
return
if("text")
lst[i] = input("Enter new text:","Text",null) as text
if("num")
lst[i] = input("Enter new number:","Num",0) as num
if("type")
lst[i] = input("Enter type:","Type") in typesof(/obj,/mob,/area,/turf)
if("reference")
switch(alert("Would you like to enter a specific object, or search for it from the world?","Choose!","Specifc UID (Hexadecimal number)", "Search"))
if("Specifc UID (Hexadecimal number)")
var/UID = input("Type in UID, without the leading 0x","Type in UID") as text|null
if(!UID) return
if(length(UID) != 7)
usr << "ERROR. UID must be 7 digits"
var/temp_variable = locate("\[0x[UID]\]")
if(!temp_variable)
usr << "ERROR. Could not locate referenced object."
return
switch(alert("You have chosen [temp_variable], in [get_area(temp_variable)]. Are you sure?","You sure?","Yes","NONOCANCEL!"))
if("Yes")
lst[i] = temp_variable
if("NONOCANCEL!")
return
if("Search")
lst[i] = input("Select reference:","Reference") as null|mob|obj|turf|area in world
if("mob reference")
lst[i] = input("Select reference:","Reference",usr) as mob in getmobs()
if("file")
lst[i] = input("Pick file:","File") as file
if("icon")
lst[i] = input("Pick icon:","Icon") as icon
if("client")
var/list/keys = list()
for(var/mob/M in world)
keys += M.client
sortList(keys)
lst[i] = input("Please, select a player!", "Selection", null, null) as null|anything in keys
if("mob's area")
var/mob/temp = input("Select mob", "Selection", usr) as mob in getmobs()
lst[i] = temp.loc
spawn(0)
if(target)
log_admin("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
returnval = call(target,procname)(arglist(lst)) // Pass the lst as an argument list to the proc
else
//this currently has no hascall protection. wasn't able to get it working.
log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
returnval = call(procname)(arglist(lst)) // Pass the lst as an argument list to the proc
usr << "\blue Proc returned: [returnval ? returnval : "null"]"
usr << "<font color='blue'>[procname] returned: [returnval ? returnval : "null"]</font>"
//feedback_add_details("admin_verb","APC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/callprocgen()
set category = "Debug"
@@ -286,6 +287,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
t+= "CO2: [env.carbon_dioxide]\n"
usr.show_message(t, 1)
//feedback_add_details("admin_verb","ASL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_robotize(var/mob/M in world)
set category = "Fun"
@@ -327,6 +329,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
for(var/datum/paiCandidate/candidate in paiController.pai_candidates)
if(candidate.key == choice.key)
paiController.pai_candidates.Remove(candidate)
//feedback_add_details("admin_verb","MPAI") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_alienize(var/mob/M in world)
set category = "Fun"
@@ -466,6 +469,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
del(O)
log_admin("[key_name(src)] has deleted all instances of [hsbitem].")
message_admins("[key_name_admin(src)] has deleted all instances of [hsbitem].", 0)
// feedback_add_details("admin_verb","DELA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_debug_make_powernets()
set category = "Debug"
@@ -473,6 +477,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
makepowernets()
log_admin("[key_name(src)] has remade the powernet. makepowernets() called.")
message_admins("[key_name_admin(src)] has remade the powernets. makepowernets() called.", 0)
// feedback_add_details("admin_verb","MPWN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_debug_tog_aliens()
set category = "Server"
@@ -481,6 +486,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
aliens_allowed = !aliens_allowed
log_admin("[key_name(src)] has turned aliens [aliens_allowed ? "on" : "off"].")
message_admins("[key_name_admin(src)] has turned aliens [aliens_allowed ? "on" : "off"].", 0)
// feedback_add_details("admin_verb","TAL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_grantfullaccess(var/mob/M in world)
set category = "Admin"
+4
View File
@@ -143,6 +143,10 @@
proc/set_frequency(new_frequency)
if(!radio_controller)
sleep(20)
if(!radio_controller)
return
radio_controller.remove_object(src, frequency)
frequency = new_frequency
radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT)
+5 -5
View File
@@ -226,6 +226,7 @@
if(usr.stat || usr.restrained()) return
if(!in_range(src, usr)) return
src.add_fingerprint(usr)
usr.machine = src
if(!beaker) return
var/datum/reagents/R = beaker:reagents
@@ -290,9 +291,9 @@
reagents.clear_reagents()
icon_state = "mixer0"
else if (href_list["createpill"])
var/name = input(usr,"Name:","Name your pill!",reagents.get_master_reagent_name())
var/name = reject_bad_text(input(usr,"Name:","Name your pill!",reagents.get_master_reagent_name()))
var/obj/item/weapon/reagent_containers/pill/P = new/obj/item/weapon/reagent_containers/pill(src.loc)
if(!name || name == " ") name = reagents.get_master_reagent_name()
if(!name) name = reagents.get_master_reagent_name()
P.name = "[name] pill"
P.pixel_x = rand(-7, 7) //random position
P.pixel_y = rand(-7, 7)
@@ -300,9 +301,9 @@
reagents.trans_to(P,50)
else if (href_list["createbottle"])
if(!condi)
var/name = input(usr,"Name:","Name your bottle!",reagents.get_master_reagent_name())
var/name = reject_bad_text(input(usr,"Name:","Name your bottle!",reagents.get_master_reagent_name()))
var/obj/item/weapon/reagent_containers/glass/bottle/P = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc)
if(!name || name == " ") name = reagents.get_master_reagent_name()
if(!name) name = reagents.get_master_reagent_name()
P.name = "[name] bottle"
P.pixel_x = rand(-7, 7) //random position
P.pixel_y = rand(-7, 7)
@@ -334,7 +335,6 @@
else
usr << browse(null, "window=chem_master")
src.updateUsrDialog()
src.add_fingerprint(usr)
return
attack_ai(mob/user as mob)
+182 -402
View File
@@ -744,9 +744,7 @@ datum
affecting.take_damage(25, 0)
M:UpdateDamageIcon()
M:emote("scream")
M << "\red Your face has become disfigured!"
M.real_name = "Unknown"
M.warn_flavor_changed()
M:disfigure_face()
else
M.take_organ_damage(min(15, volume * 2)) // uses min() and volume to make sure they aren't being sprayed in trace amounts (1 unit != insta rape) -- Doohl
else
@@ -798,10 +796,7 @@ datum
M:UpdateDamageIcon()
M:emote("scream")
if(prob(15))
M << "\red Your face has become disfigured!"
M.real_name = "Unknown"
M.warn_flavor_changed()
affecting.disfigured = 1
M:disfigure_face()
else
if(istype(M, /mob/living/carbon/monkey) && M:wear_mask)
del (M:wear_mask)
@@ -819,10 +814,7 @@ datum
M:UpdateDamageIcon()
M:emote("scream")
if(prob(15))
M << "\red Your face has become disfigured!"
M.real_name = "Unknown"
M.warn_flavor_changed()
affecting.disfigured = 1
M:disfigure_face()
else
M.take_organ_damage(min(15, volume * 4))
@@ -2930,9 +2922,9 @@ datum
color = "#664300" // rgb: 102, 67, 0
tequilla_sunrise
name = "Tequilla Sunrise"
name = "Tequila Sunrise"
id = "tequillasunrise"
description = "Tequilla and orange juice. Much like a Screwdriver, only Mexican~"
description = "Tequila and orange juice. Much like a Screwdriver, only Mexican~"
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
@@ -3034,7 +3026,7 @@ datum
manhattan_proj
name = "Manhattan Project"
id = "manhattan_proj"
description = "A scienitst drink of choice, for thinking how to blow up the station."
description = "A scienitst's drink of choice, for pondering ways to blow up the station."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
@@ -3110,6 +3102,180 @@ datum
dizzy_adj = 15
slurr_adj = 15
sbiten
name = "Sbiten"
id = "sbiten"
description = "A spicy Vodka! Might be a little hot for the little guys!"
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
if (M.bodytemperature < 360)
M.bodytemperature = min(360, M.bodytemperature+50) //310 is the normal bodytemp. 310.055
return
devilskiss
name = "Devils Kiss"
id = "devilskiss"
description = "Creepy time!"
reagent_state = LIQUID
color = "#A68310" // rgb: 166, 131, 16
red_mead
name = "Red Mead"
id = "red_mead"
description = "The true Viking drink! Even though it has a strange red color."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
mead
name = "Mead"
id = "mead"
description = "A Vikings drink, though a cheap one."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
iced_beer
name = "Iced Beer"
id = "iced_beer"
description = "A beer which is so cold the air around it freezes."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
if (M.bodytemperature < 270)
M.bodytemperature = min(270, M.bodytemperature-40) //310 is the normal bodytemp. 310.055
return
grog
name = "Grog"
id = "grog"
description = "Watered down rum, NanoTrasen approves!"
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
aloe
name = "Aloe"
id = "aloe"
description = "So very, very, very good."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
andalusia
name = "Andalusia"
id = "andalusia"
description = "A nice, strange named drink."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
alliescocktail
name = "Allies Cocktail"
id = "alliescocktail"
description = "A drink made from your allies."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
acid_spit
name = "Acid Spit"
id = "acidspit"
description = "A drink by Nanotrasen. Made from live aliens."
reagent_state = LIQUID
color = "#365000" // rgb: 54, 80, 0
amasec
name = "Amasec"
id = "amasec"
description = "Official drink of the Imperium."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
M.stunned = 4
return
neurotoxin
name = "Neurotoxin"
id = "neurotoxin"
description = "A strong neurotoxin that puts the subject into a death-like state."
reagent_state = LIQUID
color = "#2E2E61" // rgb: 46, 46, 97
on_mob_life(var/mob/living/M as mob)
if(!M) M = holder.my_atom
M:adjustOxyLoss(0.5)
M:adjustOxyLoss(0.5)
M:weakened = max(M:weakened, 15)
M:silent = max(M:silent, 15)
return
bananahonk
name = "Banana Mama"
id = "bananahonk"
description = "A drink from Clown Heaven."
nutriment_factor = 1 * REAGENTS_METABOLISM
color = "#664300" // rgb: 102, 67, 0
silencer
name = "Silencer"
id = "silencer"
description = "A drink from Mime Heaven."
nutriment_factor = 1 * REAGENTS_METABOLISM
color = "#664300" // rgb: 102, 67, 0
changelingsting
name = "Changeling Sting"
id = "changelingsting"
description = "A stingy drink."
reagent_state = LIQUID
color = "#2E6671" // rgb: 46, 102, 113
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.dizziness +=5
if(data >= 55 && data <115)
if (!M.slurring) M.slurring = 1
M.slurring += 5
else if(data >= 115 && prob(33))
M.confused = max(M:confused+15,15)
..()
return
irishcarbomb
name = "Irish Car Bomb"
id = "irishcarbomb"
description = "Mmm, tastes like chocolate cake..."
reagent_state = LIQUID
color = "#2E6671" // rgb: 46, 102, 113
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.dizziness +=5
if(data >= 55 && data <115)
if (!M.slurring) M.slurring = 1
M.slurring += 5
else if(data >= 115 && prob(33))
M.confused = max(M:confused+15,15)
..()
return
syndicatebomb
name = "Syndicate Bomb"
id = "syndicatebomb"
description = "A Syndicate bomb"
reagent_state = LIQUID
color = "#2E6671" // rgb: 46, 102, 113
erikasurprise
name = "Erika Surprise"
id = "erikasurprise"
description = "The surprise is, it's green!"
reagent_state = LIQUID
color = "#2E6671" // rgb: 46, 102, 113
//ALCHOHOL end
tonic
@@ -3175,192 +3341,8 @@ datum
..()
return
////////////////////////// REMOVED COCKTAIL REAGENTS BELOW:: RE-ENABLE THEM IF THEY EVER GET SPRITES THAT DON'T LOOK FUCKING STUPID --Agouri ///////////////////////////
/* sbiten
name = "Sbiten"
id = "sbiten"
description = "A spicy Vodka! Might be a little hot for the little guys!"
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
if (M.bodytemperature < 360)
M.bodytemperature = min(360, M.bodytemperature+50) //310 is the normal bodytemp. 310.055
if(!data) data = 1
data++
M.dizziness +=6
if(data >= 45 && data <125)
if (!M.slurring) M.slurring = 1
M.slurring += 6
else if(data >= 125 && prob(33))
M.confused = max(M:confused+5,5)
..()
return
devilskiss
name = "Devils Kiss"
id = "devilskiss"
description = "Creepy time!"
reagent_state = LIQUID
color = "#A68310" // rgb: 166, 131, 16
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.dizziness +=4
if(data >= 55 && data <165)
if (!M.slurring) M.slurring = 1
M.slurring += 4
else if(data >= 165 && prob(33))
M.confused = max(M:confused+4,0)
..()
return
red_mead
name = "Red Mead"
id = "red_mead"
description = "The true Viking drink! Even though it has a strange red color."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.dizziness +=5
if(data >= 55 && data <115)
if (!M.slurring) M.slurring = 1
M.slurring += 4
else if(data >= 115 && prob(33))
M.confused = max(M:confused+4,4)
..()
return
mead
name = "Mead"
id = "mead"
description = "A Vikings drink, though a cheap one."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.make_dizzy(3)
M:jitteriness = max(M:jitteriness-3,0)
M:nutrition += 2
if(data >= 25)
if (!M:slurring) M:slurring = 1
M:slurring += 3
if(data >= 40 && prob(33))
if (!M:confused) M:confused = 1
M:confused += 2
..()
return
iced_beer
name = "Iced Beer"
id = "iced_beer"
description = "A beer which is so cold the air around it freezes."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
if (M.bodytemperature < 270)
M.bodytemperature = min(270, M.bodytemperature-40) //310 is the normal bodytemp. 310.055
if(!data) data = 1
data++
M.make_dizzy(3)
M:jitteriness = max(M:jitteriness-3,0)
M:nutrition += 2
if(data >= 25)
if (!M:slurring) M:slurring = 1
M:slurring += 3
if(data >= 40 && prob(33))
if (!M:confused) M:confused = 1
M:confused += 2
..()
return
grog
name = "Grog"
id = "grog"
description = "Watered down rum, Nanotrasen approves!"
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.dizziness +=2
if(data >= 90 && data <250)
if (!M.slurring) M.slurring = 1
M.slurring += 2
else if(data >= 250 && prob(33))
M.confused = max(M:confused+2,0)
..()
return
aloe
name = "Aloe"
id = "aloe"
description = "So very, very, very good."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.dizziness +=2
if(data >= 90 && data <250)
if (!M.slurring) M.slurring = 1
M.slurring += 2
else if(data >= 250 && prob(33))
M.confused = max(M:confused+2,0)
..()
return
andalusia
name = "Andalusia"
id = "andalusia"
description = "A nice, strange named drink."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.dizziness +=8
if(data >= 90 && data <250)
if (!M.slurring) M.slurring = 1
M.slurring += 1
else if(data >= 250 && prob(33))
M.confused = max(M:confused+2,0)
..()
return
alliescocktail
name = "Allies Cocktail"
id = "alliescocktail"
description = "A drink made from your allies."
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.dizziness +=4
if(data >= 90 && data <250)
if (!M.slurring) M.slurring = 1
M.slurring += 7
else if(data >= 250 && prob(60))
M.confused = max(M:confused+8,0)
..()
return
soy_latte
name = "Soy Latte"
id = "soy_latte"
@@ -3401,75 +3383,8 @@ datum
..()
return
acid_spit
name = "Acid Spit"
id = "acidspit"
description = "A drink by Nanotrasen. Made from live aliens."
reagent_state = LIQUID
color = "#365000" // rgb: 54, 80, 0
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.dizziness +=10
if(data >= 55 && data <115)
if (!M.slurring) M.slurring = 1
M.slurring += 10
else if(data >= 115 && prob(33))
M.confused = max(M:confused+10,0)
..()
return
amasec
name = "Amasec"
id = "amasec"
description = "Always before COMBAT!!!"
reagent_state = LIQUID
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
M.stunned = 4
if(!data) data = 1
data++
M.dizziness +=4
if(data >= 55 && data <165)
if (!M.slurring) M.slurring = 1
M.slurring += 4
else if(data >= 165 && prob(33))
M.confused = max(M:confused+5,0)
..()
return
neurotoxin
name = "Neurotoxin"
id = "neurotoxin"
description = "A strong neurotoxin that puts the subject into a death-like state."
reagent_state = LIQUID
color = "#2E2E61" // rgb: 46, 46, 97
on_mob_life(var/mob/living/M as mob)
if(!M) M = holder.my_atom
M:adjustOxyLoss(0.5)
M:adjustOxyLoss(0.5)
M:weakened = max(M:weakened, 15)
M:silent = max(M:silent, 15)
if(!data) data = 1
data++
M.dizziness +=6
if(data >= 15 && data <45)
if (!M.slurring) M.slurring = 1
M.slurring += 3
else if(data >= 45 && prob(50) && data <55)
M.confused = max(M:confused+3,0)
else if(data >=55)
M.druggy = max(M.druggy, 55)
..()
return
hippies_delight
name = "Hippies Delight"
name = "Hippie's Delight"
id = "hippiesdelight"
description = "A drink enjoyed by people during the 1960's."
reagent_state = LIQUID
@@ -3499,139 +3414,4 @@ datum
holder.remove_reagent(src.id, 0.2)
data++
..()
return
bananahonk
name = "Banana Honk"
id = "bananahonk"
description = "A drink from Clown Heaven."
nutriment_factor = 1 * REAGENTS_METABOLISM
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
M:nutrition += nutriment_factor
if(!data) data = 1
data++
if(istype(M, /mob/living/carbon/human) && M.job in list("Clown"))
if(!M) M = holder.my_atom
M:heal_organ_damage(1,1)
M.dizziness +=5
if(data >= 55 && data <165)
if (!M.slurring) M.slurring = 1
M.slurring += 5
else if(data >= 165 && prob(33))
M.confused = max(M:confused+5,0)
..()
return
if(istype(M, /mob/living/carbon/monkey))
if(!M) M = holder.my_atom
M:heal_organ_damage(1,1)
M.dizziness +=5
if(data >= 55 && data <165)
if (!M.slurring) M.slurring = 1
M.slurring += 5
else if(data >= 165 && prob(33))
M.confused = max(M:confused+5,0)
..()
return
silencer
name = "Silencer"
id = "silencer"
description = "A drink from Mime Heaven."
nutriment_factor = 1 * REAGENTS_METABOLISM
color = "#664300" // rgb: 102, 67, 0
on_mob_life(var/mob/living/M as mob)
M:nutrition += nutriment_factor
if(!data) data = 1
data++
if(istype(M, /mob/living/carbon/human) && M.job in list("Mime"))
if(!M) M = holder.my_atom
M:heal_organ_damage(1,1)
M.dizziness +=5
if(data >= 55 && data <165)
if (!M.slurring) M.slurring = 1
M.slurring += 5
else if(data >= 165 && prob(33))
M.confused = max(M:confused+5,0)
..()
return
changelingsting
name = "Changeling Sting"
id = "changelingsting"
description = "A stingy drink."
reagent_state = LIQUID
color = "#2E6671" // rgb: 46, 102, 113
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.dizziness +=5
if(data >= 55 && data <115)
if (!M.slurring) M.slurring = 1
M.slurring += 5
else if(data >= 115 && prob(33))
M.confused = max(M:confused+15,15)
..()
return
irishcarbomb
name = "Irish Car Bomb"
id = "irishcarbomb"
description = "An irish car bomb"
reagent_state = LIQUID
color = "#2E6671" // rgb: 46, 102, 113
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.dizziness +=5
if(data >= 55 && data <115)
if (!M.slurring) M.slurring = 1
M.slurring += 5
else if(data >= 115 && prob(33))
M.confused = max(M:confused+15,15)
..()
return
syndicatebomb
name = "Syndicate Bomb"
id = "syndicatebomb"
description = "A Syndicate bomb"
reagent_state = LIQUID
color = "#2E6671" // rgb: 46, 102, 113
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.dizziness +=10
if(data >= 55 && data <115)
if (!M.slurring) M.slurring = 1
M.slurring += 10
else if(data >= 115 && prob(33))
M.confused = max(M:confused+15,15)
..()
return
erikasurprise
name = "Erika Surprise"
id = "erikasurprise"
description = "A surprise of Erika"
reagent_state = LIQUID
color = "#2E6671" // rgb: 46, 102, 113
on_mob_life(var/mob/living/M as mob)
if(!data) data = 1
data++
M.dizziness +=30
if(data >= 55 && data <115)
if (!M.slurring) M.slurring = 1
M.slurring += 30
else if(data >= 115 && prob(60))
M.confused = max(M:confused+15,15)
..()
return*/
return
+2 -2
View File
@@ -1261,7 +1261,7 @@ datum
////DRINKS THAT REQUIRE IMPROVED SPRITES BELOW:: -Agouri/////
/* sbiten
sbiten
name = "Sbiten"
id = "sbiten"
result = "sbiten"
@@ -1415,7 +1415,7 @@ datum
id = "silencer"
result = "silencer"
required_reagents = list("nothing" = 1, "cream" = 1, "sugar" = 1)
result_amount = 3*/
result_amount = 3
+2 -3
View File
@@ -3498,8 +3498,7 @@
icon_state = "booger"
name = "Booger"
desc = "Ewww..."
/*if("snowwhite") /// Dumbly-sprited drinks below. If your drink is on the list, shame on you --Agouri
if("snowwhite")
icon_state = "snowwhite"
name = "Snow White"
desc = "A cold refreshment."
@@ -3586,7 +3585,7 @@
if("erikasurprise")
icon_state = "erikasurprise"
name = "Erika Surprise"
desc = "A surprise of Erika"*/
desc = "The surprise is, it's green!"
else
icon_state ="glass_brown"
name = "Glass of ..what?"
-3
View File
@@ -179,10 +179,7 @@
name = "botanist's leather gloves"
icon_state = "leather"
item_state = "ggloves"
siemens_coefficient = 0.50
permeability_coefficient = 0.9
protective_temperature = 400
heat_transfer_coefficient = 0.70
/obj/item/clothing/gloves/orange
name = "orange gloves"
+8
View File
@@ -39,6 +39,14 @@
gas_transfer_coefficient = 0.01
permeability_coefficient = 0.01
/obj/item/clothing/mask/balaclava
name = "balaclava"
desc = "LOADSAMONEY"
icon_state = "balaclava"
item_state = "balaclava"
flags = FPRINT|TABLEPASS|SUITSPACE|HEADSPACE|MASKCOVERSMOUTH|BLOCKHAIR
w_class = 2
/obj/item/clothing/mask/muzzle
name = "muzzle"
desc = "To stop that awful noise."
+672
View File
@@ -0,0 +1,672 @@
/*
SwapMaps library by Lummox JR
developed for digitalBYOND
http://www.digitalbyond.org
Version 2.1
The purpose of this library is to make it easy for authors to swap maps
in and out of their game using savefiles. Swapped-out maps can be
transferred between worlds for an MMORPG, sent to the client, etc.
This is facilitated by the use of a special datum and a global list.
Uses of swapmaps:
- Temporary battle arenas
- House interiors
- Individual custom player houses
- Virtually unlimited terrain
- Sharing maps between servers running different instances of the same
game
- Loading and saving pieces of maps for reusable room templates
*/
/*
User Interface:
VARS:
swapmaps_iconcache
An associative list of icon files with names, like
'player.dmi' = "player"
swapmaps_mode
This must be set at runtime, like in world/New().
SWAPMAPS_SAV 0 (default)
Uses .sav files for raw /savefile output.
SWAPMAPS_TEXT 1
Uses .txt files via ExportText() and ImportText(). These maps
are easily editable and appear to take up less space in the
current version of BYOND.
PROCS:
SwapMaps_Find(id)
Find a map by its id
SwapMaps_Load(id)
Load a map by its id
SwapMaps_Save(id)
Save a map by its id (calls swapmap.Save())
SwapMaps_Unload(id)
Save and unload a map by its id (calls swapmap.Unload())
SwapMaps_Save_All()
Save all maps
SwapMaps_DeleteFile(id)
Delete a map file
SwapMaps_CreateFromTemplate(id)
Create a new map by loading another map to use as a template.
This map has id==src and will not be saved. To make it savable,
change id with swapmap.SetID(newid).
SwapMaps_LoadChunk(id,turf/locorner)
Load a swapmap as a "chunk", at a specific place. A new datum is
created but it's not added to the list of maps to save or unload.
The new datum can be safely deleted without affecting the turfs
it loaded. The purpose of this is to load a map file onto part of
another swapmap or an existing part of the world.
locorner is the corner turf with the lowest x,y,z values.
SwapMaps_SaveChunk(id,turf/corner1,turf/corner2)
Save a piece of the world as a "chunk". A new datum is created
for the chunk, but it can be deleted without destroying any turfs.
The chunk file can be reloaded as a swapmap all its own, or loaded
via SwapMaps_LoadChunk() to become part of another map.
SwapMaps_GetSize(id)
Return a list corresponding to the x,y,z sizes of a map file,
without loading the map.
Returns null if the map is not found.
SwapMaps_AddIconToCache(name,icon)
Cache an icon file by name for space-saving storage
swapmap.New(id,x,y,z)
Create a new map; specify id, width (x), height (y), and
depth (z)
Default size is world.maxx,world.maxy,1
swapmap.New(id,turf1,turf2)
Create a new map; specify id and 2 corners
This becomes a /swapmap for one of the compiled-in maps, for
easy saving.
swapmap.New()
Create a new map datum, but does not allocate space or assign an
ID (used for loading).
swapmap.Del()
Deletes a map but does not save
swapmap.Save()
Saves to map_[id].sav
Maps with id==src are not saved.
swapmap.Unload()
Saves the map and then deletes it
Maps with id==src are not saved.
swapmap.SetID(id)
Change the map's id and make changes to the lookup list
swapmap.AllTurfs(z)
Returns a block of turfs encompassing the entire map, or on just
one z-level
z is in world coordinates; it is optional
swapmap.Contains(turf/T)
Returns nonzero if T is inside the map's boundaries.
Also works for objs and mobs, but the proc is not area-safe.
swapmap.InUse()
Returns nonzero if a mob with a key is within the map's
boundaries.
swapmap.LoCorner(z=z1)
Returns locate(x1,y1,z), where z=z1 if none is specified.
swapmap.HiCorner(z=z2)
Returns locate(x2,y2,z), where z=z2 if none is specified.
swapmap.BuildFilledRectangle(turf/corner1,turf/corner2,item)
Builds a filled rectangle of item from one corner turf to the
other, on multiple z-levels if necessary. The corners may be
specified in any order.
item is a type path like /turf/wall or /obj/barrel{full=1}.
swapmap.BuildRectangle(turf/corner1,turf/corner2,item)
Builds an unfilled rectangle of item from one corner turf to
the other, on multiple z-levels if necessary.
swapmap.BuildInTurfs(list/turfs,item)
Builds item on all of the turfs listed. The list need not
contain only turfs, or even only atoms.
*/
swapmap
var/id // a string identifying this map uniquely
var/x1 // minimum x,y,z coords
var/y1
var/z1
var/x2 // maximum x,y,z coords (also used as width,height,depth until positioned)
var/y2
var/z2
var/tmp/locked // don't move anyone to this map; it's saving or loading
var/tmp/mode // save as text-mode
var/ischunk // tells the load routine to load to the specified location
New(_id,x,y,z)
if(isnull(_id)) return
id=_id
mode=swapmaps_mode
if(isturf(x) && isturf(y))
/*
Special format: Defines a map as an existing set of turfs;
this is useful for saving a compiled map in swapmap format.
Because this is a compiled-in map, its turfs are not deleted
when the datum is deleted.
*/
x1=min(x:x,y:x);x2=max(x:x,y:x)
y1=min(x:y,y:y);y2=max(x:y,y:y)
z1=min(x:z,y:z);z2=max(x:z,y:z)
InitializeSwapMaps()
if(z2>swapmaps_compiled_maxz ||\
y2>swapmaps_compiled_maxy ||\
x2>swapmaps_compiled_maxx)
del(src)
return
x2=x?(x):world.maxx
y2=y?(y):world.maxy
z2=z?(z):1
AllocateSwapMap()
Del()
// a temporary datum for a chunk can be deleted outright
// for others, some cleanup is necessary
if(!ischunk)
swapmaps_loaded-=src
swapmaps_byname-=id
if(z2>swapmaps_compiled_maxz ||\
y2>swapmaps_compiled_maxy ||\
x2>swapmaps_compiled_maxx)
var/list/areas=new
for(var/atom/A in block(locate(x1,y1,z1),locate(x2,y2,z2)))
for(var/obj/O in A) del(O)
for(var/mob/M in A)
if(!M.key) del(M)
else M.loc=null
areas[A.loc]=null
del(A)
// delete areas that belong only to this map
for(var/area/a in areas)
if(a && !a.contents.len) del(a)
if(x2>=world.maxx || y2>=world.maxy || z2>=world.maxz) CutXYZ()
del(areas)
..()
/*
Savefile format:
map
id
x // size, not coords
y
z
areas // list of areas, not including default
[each z; 1 to depth]
[each y; 1 to height]
[each x; 1 to width]
type // of turf
AREA // if non-default; saved as a number (index into areas list)
vars // all other changed vars
*/
Write(savefile/S)
var
x;y;z;n
list/areas
area/defarea=locate(world.area)
if(!defarea) defarea=new world.area
areas=list()
for(var/turf/T in block(locate(x1,y1,z1),locate(x2,y2,z2)))
areas[T.loc]=null
for(n in areas) // quickly eliminate associations for smaller storage
areas-=n
areas+=n
areas-=defarea
InitializeSwapMaps()
locked=1
S["id"] << id
S["z"] << z2-z1+1
S["y"] << y2-y1+1
S["x"] << x2-x1+1
S["areas"] << areas
for(n in 1 to areas.len) areas[areas[n]]=n
var/oldcd=S.cd
for(z=z1,z<=z2,++z)
S.cd="[z-z1+1]"
for(y=y1,y<=y2,++y)
S.cd="[y-y1+1]"
for(x=x1,x<=x2,++x)
S.cd="[x-x1+1]"
var/turf/T=locate(x,y,z)
S["type"] << T.type
if(T.loc!=defarea) S["AREA"] << areas[T.loc]
T.Write(S)
S.cd=".."
S.cd=".."
sleep()
S.cd=oldcd
locked=0
del(areas)
Read(savefile/S,_id,turf/locorner)
var
x;y;z;n
list/areas
area/defarea=locate(world.area)
id=_id
if(locorner)
ischunk=1
x1=locorner.x
y1=locorner.y
z1=locorner.z
if(!defarea) defarea=new world.area
if(!_id)
S["id"] >> id
else
var/dummy
S["id"] >> dummy
S["z"] >> z2 // these are depth,
S["y"] >> y2 // height,
S["x"] >> x2 // width
S["areas"] >> areas
locked=1
AllocateSwapMap() // adjust x1,y1,z1 - x2,y2,z2 coords
var/oldcd=S.cd
for(z=z1,z<=z2,++z)
S.cd="[z-z1+1]"
for(y=y1,y<=y2,++y)
S.cd="[y-y1+1]"
for(x=x1,x<=x2,++x)
S.cd="[x-x1+1]"
var/tp
S["type"]>>tp
var/turf/T=locate(x,y,z)
T.loc.contents-=T
T=new tp(locate(x,y,z))
if("AREA" in S.dir)
S["AREA"]>>n
var/area/A=areas[n]
A.contents+=T
else defarea.contents+=T
// clear the turf
for(var/obj/O in T) del(O)
for(var/mob/M in T)
if(!M.key) del(M)
else M.loc=null
// finish the read
T.Read(S)
S.cd=".."
S.cd=".."
sleep()
S.cd=oldcd
locked=0
del(areas)
/*
Find an empty block on the world map in which to load this map.
If no space is found, increase world.maxz as necessary. (If the
map is greater in x,y size than the current world, expand
world.maxx and world.maxy too.)
Ignore certain operations if loading a map as a chunk. Use the
x1,y1,z1 position for it, and *don't* count it as a loaded map.
*/
proc/AllocateSwapMap()
InitializeSwapMaps()
world.maxx=max(x2,world.maxx) // stretch x/y if necessary
world.maxy=max(y2,world.maxy)
if(!ischunk)
if(world.maxz<=swapmaps_compiled_maxz)
z1=swapmaps_compiled_maxz+1
x1=1;y1=1
else
var/list/l=ConsiderRegion(1,1,world.maxx,world.maxy,swapmaps_compiled_maxz+1)
x1=l[1]
y1=l[2]
z1=l[3]
del(l)
x2+=x1-1
y2+=y1-1
z2+=z1-1
world.maxz=max(z2,world.maxz) // stretch z if necessary
if(!ischunk)
swapmaps_loaded[src]=null
swapmaps_byname[id]=src
proc/ConsiderRegion(X1,Y1,X2,Y2,Z1,Z2)
while(1)
var/nextz=0
var/swapmap/M
for(M in swapmaps_loaded)
if(M.z2<Z1 || (Z2 && M.z1>Z2) || M.z1>=Z1+z2 ||\
M.x1>X2 || M.x2<X1 || M.x1>=X1+x2 ||\
M.y1>Y2 || M.y2<Y1 || M.y1>=Y1+y2) continue
// look for sub-regions with a defined ceiling
var/nz2=Z2?(Z2):Z1+z2-1+M.z2-M.z1
if(M.x1>=X1+x2)
.=ConsiderRegion(X1,Y1,M.x1-1,Y2,Z1,nz2)
if(.) return
else if(M.x2<=X2-x2)
.=ConsiderRegion(M.x2+1,Y1,X2,Y2,Z1,nz2)
if(.) return
if(M.y1>=Y1+y2)
.=ConsiderRegion(X1,Y1,X2,M.y1-1,Z1,nz2)
if(.) return
else if(M.y2<=Y2-y2)
.=ConsiderRegion(X1,M.y2+1,X2,Y2,Z1,nz2)
if(.) return
nextz=nextz?min(nextz,M.z2+1):(M.z2+1)
if(!M)
/* If nextz is not 0, then at some point there was an overlap that
could not be resolved by using an area to the side */
if(nextz) Z1=nextz
if(!nextz || (Z2 && Z2-Z1+1<z2))
return (!Z2 || Z2-Z1+1>=z2)?list(X1,Y1,Z1):null
X1=1;X2=world.maxx
Y1=1;Y2=world.maxy
proc/CutXYZ()
var/mx=swapmaps_compiled_maxx
var/my=swapmaps_compiled_maxy
var/mz=swapmaps_compiled_maxz
for(var/swapmap/M in swapmaps_loaded) // may not include src
mx=max(mx,M.x2)
my=max(my,M.y2)
mz=max(mz,M.z2)
world.maxx=mx
world.maxy=my
world.maxz=mz
// save and delete
proc/Unload()
Save()
del(src)
proc/Save()
if(id==src) return 0
var/savefile/S=mode?(new):new("map_[id].sav")
S << src
while(locked) sleep(1)
if(mode)
fdel("map_[id].txt")
S.ExportText("/","map_[id].txt")
return 1
// this will not delete existing savefiles for this map
proc/SetID(newid)
swapmaps_byname-=id
id=newid
swapmaps_byname[id]=src
proc/AllTurfs(z)
if(isnum(z) && (z<z1 || z>z2)) return null
return block(LoCorner(z),HiCorner(z))
// this could be safely called for an obj or mob as well, but
// probably not an area
proc/Contains(turf/T)
return (T && T.x>=x1 && T.x<=x2\
&& T.y>=y1 && T.y<=y2\
&& T.z>=z1 && T.z<=z2)
proc/InUse()
for(var/turf/T in AllTurfs())
for(var/mob/M in T) if(M.key) return 1
proc/LoCorner(z=z1)
return locate(x1,y1,z)
proc/HiCorner(z=z2)
return locate(x2,y2,z)
/*
Build procs: Take 2 turfs as corners, plus an item type.
An item may be like:
/turf/wall
/obj/fence{icon_state="iron"}
*/
proc/BuildFilledRectangle(turf/T1,turf/T2,item)
if(!Contains(T1) || !Contains(T2)) return
var/turf/T=T1
// pick new corners in a block()-friendly form
T1=locate(min(T1.x,T2.x),min(T1.y,T2.y),min(T1.z,T2.z))
T2=locate(max(T.x,T2.x),max(T.y,T2.y),max(T.z,T2.z))
for(T in block(T1,T2)) new item(T)
proc/BuildRectangle(turf/T1,turf/T2,item)
if(!Contains(T1) || !Contains(T2)) return
var/turf/T=T1
// pick new corners in a block()-friendly form
T1=locate(min(T1.x,T2.x),min(T1.y,T2.y),min(T1.z,T2.z))
T2=locate(max(T.x,T2.x),max(T.y,T2.y),max(T.z,T2.z))
if(T2.x-T1.x<2 || T2.y-T1.y<2) BuildFilledRectangle(T1,T2,item)
else
//for(T in block(T1,T2)-block(locate(T1.x+1,T1.y+1,T1.z),locate(T2.x-1,T2.y-1,T2.z)))
for(T in block(T1,locate(T2.x,T1.y,T2.z))) new item(T)
for(T in block(locate(T1.x,T2.y,T1.z),T2)) new item(T)
for(T in block(locate(T1.x,T1.y+1,T1.z),locate(T1.x,T2.y-1,T2.z))) new item(T)
for(T in block(locate(T2.x,T1.y+1,T1.z),locate(T2.x,T2.y-1,T2.z))) new item(T)
/*
Supplementary build proc: Takes a list of turfs, plus an item
type. Actually the list doesn't have to be just turfs.
*/
proc/BuildInTurfs(list/turfs,item)
for(var/T in turfs) new item(T)
atom
Write(savefile/S)
for(var/V in vars-"x"-"y"-"z"-"contents"-"icon"-"overlays"-"underlays")
if(issaved(vars[V]))
if(vars[V]!=initial(vars[V])) S[V]<<vars[V]
else S.dir.Remove(V)
if(icon!=initial(icon))
if(swapmaps_iconcache && swapmaps_iconcache[icon])
S["icon"]<<swapmaps_iconcache[icon]
else S["icon"]<<icon
// do not save mobs with keys; do save other mobs
var/mob/M
for(M in src) if(M.key) break
if(overlays.len) S["overlays"]<<overlays
if(underlays.len) S["underlays"]<<underlays
if(contents.len && !isarea(src))
var/list/l=contents
if(M)
l=l.Copy()
for(M in src) if(M.key) l-=M
if(l.len) S["contents"]<<l
if(l!=contents) del(l)
Read(savefile/S)
var/list/l
if(contents.len) l=contents
..()
// if the icon was a text string, it would not have loaded properly
// replace it from the cache list
if(!icon && ("icon" in S.dir))
var/ic
S["icon"]>>ic
if(istext(ic)) icon=swapmaps_iconcache[ic]
if(l && contents!=l)
contents+=l
del(l)
// set this up (at runtime) as follows:
// list(\
// 'player.dmi'="player",\
// 'monster.dmi'="monster",\
// ...
// 'item.dmi'="item")
var/list/swapmaps_iconcache
// preferred mode; sav or text
var/const/SWAPMAPS_SAV=0
var/const/SWAPMAPS_TEXT=1
var/swapmaps_mode=SWAPMAPS_SAV
var/swapmaps_compiled_maxx
var/swapmaps_compiled_maxy
var/swapmaps_compiled_maxz
var/swapmaps_initialized
var/swapmaps_loaded
var/swapmaps_byname
proc/InitializeSwapMaps()
if(swapmaps_initialized) return
swapmaps_initialized=1
swapmaps_compiled_maxx=world.maxx
swapmaps_compiled_maxy=world.maxy
swapmaps_compiled_maxz=world.maxz
swapmaps_loaded=list()
swapmaps_byname=list()
if(swapmaps_iconcache)
for(var/V in swapmaps_iconcache)
// reverse-associate everything
// so you can look up an icon file by name or vice-versa
swapmaps_iconcache[swapmaps_iconcache[V]]=V
proc/SwapMaps_AddIconToCache(name,icon)
if(!swapmaps_iconcache) swapmaps_iconcache=list()
swapmaps_iconcache[name]=icon
swapmaps_iconcache[icon]=name
proc/SwapMaps_Find(id)
InitializeSwapMaps()
return swapmaps_byname[id]
proc/SwapMaps_Load(id)
InitializeSwapMaps()
var/swapmap/M=swapmaps_byname[id]
if(!M)
var/savefile/S
var/text=0
if(swapmaps_mode==SWAPMAPS_TEXT && fexists("map_[id].txt"))
text=1
else if(fexists("map_[id].sav"))
S=new("map_[id].sav")
else if(swapmaps_mode!=SWAPMAPS_TEXT && fexists("map_[id].txt"))
text=1
else return // no file found
if(text)
S=new
S.ImportText("/",file("map_[id].txt"))
S >> M
while(M.locked) sleep(1)
M.mode=text
return M
proc/SwapMaps_Save(id)
InitializeSwapMaps()
var/swapmap/M=swapmaps_byname[id]
if(M) M.Save()
return M
proc/SwapMaps_Save_All()
InitializeSwapMaps()
for(var/swapmap/M in swapmaps_loaded)
if(M) M.Save()
proc/SwapMaps_Unload(id)
InitializeSwapMaps()
var/swapmap/M=swapmaps_byname[id]
if(!M) return // return silently from an error
M.Unload()
return 1
proc/SwapMaps_DeleteFile(id)
fdel("map_[id].sav")
fdel("map_[id].txt")
proc/SwapMaps_CreateFromTemplate(template_id)
var/swapmap/M=new
var/savefile/S
var/text=0
if(swapmaps_mode==SWAPMAPS_TEXT && fexists("map_[template_id].txt"))
text=1
else if(fexists("map_[template_id].sav"))
S=new("map_[template_id].sav")
else if(swapmaps_mode!=SWAPMAPS_TEXT && fexists("map_[template_id].txt"))
text=1
else
world.log << "SwapMaps error in SwapMaps_CreateFromTemplate(): map_[template_id] file not found."
return
if(text)
S=new
S.ImportText("/",file("map_[template_id].txt"))
/*
This hacky workaround is needed because S >> M will create a brand new
M to fill with data. There's no way to control the Read() process
properly otherwise. The //.0 path should always match the map, however.
*/
S.cd="//.0"
M.Read(S,M)
M.mode=text
while(M.locked) sleep(1)
return M
proc/SwapMaps_LoadChunk(chunk_id,turf/locorner)
var/swapmap/M=new
var/savefile/S
var/text=0
if(swapmaps_mode==SWAPMAPS_TEXT && fexists("map_[chunk_id].txt"))
text=1
else if(fexists("map_[chunk_id].sav"))
S=new("map_[chunk_id].sav")
else if(swapmaps_mode!=SWAPMAPS_TEXT && fexists("map_[chunk_id].txt"))
text=1
else
world.log << "SwapMaps error in SwapMaps_LoadChunk(): map_[chunk_id] file not found."
return
if(text)
S=new
S.ImportText("/",file("map_[chunk_id].txt"))
/*
This hacky workaround is needed because S >> M will create a brand new
M to fill with data. There's no way to control the Read() process
properly otherwise. The //.0 path should always match the map, however.
*/
S.cd="//.0"
M.Read(S,M,locorner)
while(M.locked) sleep(1)
del(M)
return 1
proc/SwapMaps_SaveChunk(chunk_id,turf/corner1,turf/corner2)
if(!corner1 || !corner2)
world.log << "SwapMaps error in SwapMaps_SaveChunk():"
if(!corner1) world.log << " corner1 turf is null"
if(!corner2) world.log << " corner2 turf is null"
return
var/swapmap/M=new
M.id=chunk_id
M.ischunk=1 // this is a chunk
M.x1=min(corner1.x,corner2.x)
M.y1=min(corner1.y,corner2.y)
M.z1=min(corner1.z,corner2.z)
M.x2=max(corner1.x,corner2.x)
M.y2=max(corner1.y,corner2.y)
M.z2=max(corner1.z,corner2.z)
M.mode=swapmaps_mode
M.Save()
while(M.locked) sleep(1)
del(M)
return 1
proc/SwapMaps_GetSize(id)
var/savefile/S
var/text=0
if(swapmaps_mode==SWAPMAPS_TEXT && fexists("map_[id].txt"))
text=1
else if(fexists("map_[id].sav"))
S=new("map_[id].sav")
else if(swapmaps_mode!=SWAPMAPS_TEXT && fexists("map_[id].txt"))
text=1
else
world.log << "SwapMaps error in SwapMaps_GetSize(): map_[id] file not found."
return
if(text)
S=new
S.ImportText("/",file("map_[id].txt"))
/*
The //.0 path should always be the map. There's no other way to
read this data.
*/
S.cd="//.0"
var/x
var/y
var/z
S["x"] >> x
S["y"] >> y
S["z"] >> z
return list(x,y,z)
+73
View File
@@ -0,0 +1,73 @@
var/global/dmm_suite/maploader = new
dmm_suite{
/*
dmm_suite version 1.0
Released January 30th, 2011.
defines the object /dmm_suite
- Provides the proc load_map()
- Loads the specified map file onto the specified z-level.
- provides the proc write_map()
- Returns a text string of the map in dmm format
ready for output to a file.
- provides the proc save_map()
- Returns a .dmm file if map is saved
- Returns FALSE if map fails to save
The dmm_suite provides saving and loading of map files in BYOND's native DMM map
format. It approximates the map saving and loading processes of the Dream Maker
and Dream Seeker programs so as to allow editing, saving, and loading of maps at
runtime.
------------------------
To save a map at runtime, create an instance of /dmm_suite, and then call
write_map(), which accepts three arguments:
- A turf representing one corner of a three dimensional grid (Required).
- Another turf representing the other corner of the same grid (Required).
- Any, or a combination, of several bit flags (Optional, see documentation).
The order in which the turfs are supplied does not matter, the /dmm_writer will
determine the grid containing both, in much the same way as DM's block() function.
write_map() will then return a string representing the saved map in dmm format;
this string can then be saved to a file, or used for any other purose.
------------------------
To load a map at runtime, create an instance of /dmm_suite, and then call load_map(),
which accepts two arguments:
- A .dmm file to load (Required).
- A number representing the z-level on which to start loading the map (Optional).
The /dmm_suite will load the map file starting on the specified z-level. If no
z-level was specified, world.maxz will be increased so as to fit the map. Note
that if you wish to load a map onto a z-level that already has objects on it,
you will have to handle the removal of those objects. Otherwise the new map will
simply load the new objects on top of the old ones.
Also note that all type paths specified in the .dmm file must exist in the world's
code, and that the /dmm_reader trusts that files to be loaded are in fact valid
.dmm files. Errors in the .dmm format will cause runtime errors.
*/
verb/load_map(var/dmm_file as file, var/z_offset as num){
// dmm_file: A .dmm file to load (Required).
// z_offset: A number representing the z-level on which to start loading the map (Optional).
}
verb/write_map(var/turf/t1 as turf, var/turf/t2 as turf, var/flags as num){
// t1: A turf representing one corner of a three dimensional grid (Required).
// t2: Another turf representing the other corner of the same grid (Required).
// flags: Any, or a combination, of several bit flags (Optional, see documentation).
}
// save_map is included as a legacy proc. Use write_map instead.
verb/save_map(var/turf/t1 as turf, var/turf/t2 as turf, var/map_name as text, var/flags as num){
// t1: A turf representing one corner of a three dimensional grid (Required).
// t2: Another turf representing the other corner of the same grid (Required).
// map_name: A valid name for the map to be saved, such as "castle" (Required).
// flags: Any, or a combination, of several bit flags (Optional, see documentation).
}
}
+237
View File
@@ -0,0 +1,237 @@
/*
DMP to swapmap converter
version 1.0
by Lummox JR
*/
mob/verb/Convert(filename as file)
dmp2swapmap(filename)
proc/d2sm_prepmap(filename)
var/txt = file2text(filename)
if(!txt) return
var/i,j
i=findText(txt,ascii2text(13)) // eliminate carriage returns
while(i)
txt=copytext(txt,1,i)+copytext(txt,i+1)
i=findText(txt,ascii2text(13),i)
i=findText(txt,"\\\n")
while(i)
for(j=i+2,j<=length(txt),++j) if(text2ascii(txt,j)>32) break
txt=copytext(txt,1,i)+copytext(txt,j)
i=findText(txt,"\\\n",i)
return txt
proc/dmp2swapmap(filename)
//var/txt = file2text(filename)
//if(!txt) return
var/txt = d2sm_prepmap(filename)
var/mapname="[filename]"
var/i,j,k
i=findtext(mapname,".dmp")
while(i && i+4<length(mapname)) i=findtext(mapname,".dmp",i+1)
mapname=copytext(mapname,1,i)
/* i=findText(txt,ascii2text(13))
while(i)
txt=copytext(txt,1,i)+copytext(txt,i+1)
i=findText(txt,ascii2text(13),i)
i=findText(txt,"\\\n")
while(i)
for(j=i+2,j<=length(txt),++j) if(text2ascii(txt,j)>32) break
txt=copytext(txt,1,i)+copytext(txt,j)
i=findText(txt,"\\\n",i) */
var/list/codes=new
var/codelen=1
var/list/areas
var/mode=34
var/z=0
var/X=0,Y=0,Z=0
while(txt)
if(text2ascii(txt)==34)
if(mode!=34)
world << "Corrupt map file [filename]: Unexpected code found after z-level [z]"
return
// standard line:
// "a" = (/obj, /obj, /turf, /area)
i=findtext(txt,"\"",2)
var/code=copytext(txt,2,i)
codelen=length(code)
i=findtext(txt,"(",i)
if(!i)
world << "Corrupt map file [filename]: No type list follows \"[code]\""
return
k=findtext(txt,"\n",++i)
j=(k || length(txt+1))
while(--j>=i && text2ascii(txt,j)!=41)
if(j<i)
world << "Corrupt map file [filename]: Type list following \"[code]\" is incomplete"
return
var/list/L = d2sm_ParseCommaList(copytext(txt,i,j))
if(istext(L))
world << "Corrupt map file [filename]: [L]"
return
if(L.len<2)
world << "Corrupt map file [filename]: Type list following \"[code]\" has only 1 item"
return
txt=k?copytext(txt,k+1):null
if(L[L.len] == "[world.area]") L[L.len]=0
else
if(!areas) areas=list()
i=areas.Find(L[L.len])
if(i) L[L.len]=i
else
areas+=L[L.len]
L[L.len]=areas.len
var/codetrans=d2sm_ConvertType(L[L.len-1],"\t\t\t\t")
if(L[L.len]) codetrans+="\t\t\t\tAREA = [L[L.len]]\n"
if(L.len>2) codetrans+=d2sm_Contents(L,L.len-2,"\t\t\t\t")
codes[code]=copytext(codetrans,1,length(codetrans))
else if(text2ascii(txt)==40)
mode=40
// standard line (top-down, left-right symbol order):
// (1,1,1) = {"
// abcde
// bcdef
// "}
i=d2sm_MatchBrace(txt,1,40)
if(!i)
world << "Corrupt map file [filename]: No matching ) for coordinates: [copytext(txt,1,findtext(txt,"\n"))]"
return
var/list/coords=d2sm_ParseCommaList(copytext(txt,2,i))
if(istext(coords) || coords.len!=3)
world << "Corrupt map file [filename]: [istext(coords)?(coords):"[copytext(txt,1,i+1)] is not a valid (x,y,z) coordinate"]"
return
j=findtext(txt,"{",i+1)
if(!j)
world << "Corrupt map file [filename]: No braces {} following [copytext(txt,1,i+1)]"
return
k=d2sm_MatchBrace(txt,j,123)
if(!k)
world << "Corrupt map file [filename]: No closing brace } following [copytext(txt,1,i+1)]"
return
var/mtxt=copytext(txt,j+1,k)
if(findText(mtxt,"\"\n")!=1 || !findText(mtxt,"\n\"",length(mtxt)-1))
world << findText(mtxt,"\"\n")
world << findText(mtxt,"\n\"",length(mtxt)-1)
world << "Corrupt map file [filename]: No quotes in braces following [copytext(txt,1,i+1)]"
return
mtxt=copytext(mtxt,2,length(mtxt))
var/_x=0,_y=0
for(i=1,,++_y)
j=findText(mtxt,"\n",i+1)
if(!j) break
_x=max(_x,(j-i-1)/codelen)
i=j
X=max(X,_x)
Y=max(Y,_y)
z=text2num(coords[3])
Z=max(Z,z)
txt=copytext(txt,k+1)
else
i=findtext(txt,"\n")
txt=i?copytext(txt,i+1):null
world << "Map size: [X],[Y],[Z]"
//for(var/code in codes)
// world << "Code \"[code]\":\n[codes[code]]"
fdel("map_[mapname].txt")
var/F = file("map_[mapname].txt")
F << ". = object(\".0\")\n.0\n\ttype = /swapmap\n\tid = \"[mapname]\"\n\tz = [Z]\n\ty = [Y]\n\tx = [X]"
if(areas)
txt=""
for(i=0,i<areas.len,++i)
txt+="[i?", ":""]object(\".[i]\")"
F << "\tareas = list([txt])"
for(i=0,i<areas.len,++i)
F << "\t\t.[i]"
txt=d2sm_ConvertType(areas[i+1],"\t\t\t")
F << copytext(txt,1,length(txt))
// 2nd pass
txt=d2sm_prepmap(filename)
while(txt)
// skip all non-data sections
if(text2ascii(txt)!=40)
i=findText(txt,"\n")
if(i) txt=copytext(txt,i+1)
else txt=null
continue
i=d2sm_MatchBrace(txt,1,40)
var/list/coords=d2sm_ParseCommaList(copytext(txt,2,i))
j=findtext(txt,"{",i+1)
k=d2sm_MatchBrace(txt,j,123)
var/mtxt=copytext(txt,j+2,k-1)
var/_x=0,_y=0
for(i=1,,++_y)
j=findText(mtxt,"\n",i+1)
if(!j) break
_x=max(_x,(j-i-1)/codelen)
i=j
// print out this z-level now
F << "\t[coords[3]]"
i=1
for(var/y=_y,y>0,--y) // map is top-down
++i
F << "\t\t[y]"
for(var/x in 1 to _x)
F << "\t\t\t[x]"
j=i+codelen
F << codes[copytext(mtxt,i,j)]
i=j
txt=copytext(txt,k+1)
/* for(z in 1 to Z)
F << "\t[z]"
for(var/y in 1 to Y)
F << "\t\t[y]"
for(var/x in 1 to X)
F << "\t\t\t[x]"
F << codes[pick(codes)] */
proc/d2sm_ParseCommaList(txt)
var/list/L=new
var/i,ch
for(i=1,i<=length(txt),++i)
if(text2ascii(txt,i)>32) break
for(,i<=length(txt),++i)
ch=text2ascii(txt,i)
if(ch==44)
L+=copytext(txt,1,i)
for(++i,i<=length(txt),++i) if(text2ascii(txt,i)>32) break
txt=copytext(txt,i)
i=0;continue
if(ch==40 || ch==91 || ch==123)
i=d2sm_MatchBrace(txt,i,ch)
if(!i) return "No matching brace found for [ascii2text(ch)]"
if(i>1) L+=copytext(txt,1,i)
return L
proc/d2sm_MatchBrace(txt, i, which)
if(which==40) ++which
else which+=2
var/j,ch
for(j=i+1,j<=length(txt),++j)
ch=text2ascii(txt,j)
if(ch==which) return j
if(ch==40 || ch==91 || ch==123)
j=d2sm_MatchBrace(txt,j,ch)
if(!j) return 0
proc/d2sm_ConvertType(tt,tabs="")
var/i=findText(tt,"{")
if(!i) return "[tabs]type = [tt]\n"
.="[tabs]type = [copytext(tt,1,i)]\n"
var/list/L=d2sm_ParseCommaList(copytext(tt,i+1,d2sm_MatchBrace(tt,i,123)))
if(istext(L)) return
for(var/pair in L)
.="[.][tabs][pair]\n"
proc/d2sm_Contents(list/conts,n,tabs="")
.="[tabs]contents = list("
var/i
for(i=0,i<n,++i)
.+="[i?", ":""]object(\".[i]\")"
.+=")\n"
tabs+="\t"
for(i=0,i<n,++i)
.+="[tabs].[i]\n"
.+=d2sm_ConvertType(conts[i+1],tabs+"\t")
+47
View File
@@ -0,0 +1,47 @@
var/list/potentialRandomZlevels = list()
proc/createRandomZlevel()
var/text = file2text("maps/RandomZLevels/fileList.txt")
if (!text) // No random Z-levels for you.
return
world << "\red \b Reticulating Splines"
var/list/CL = dd_text2list(text, "\n")
for (var/t in CL)
if (!t)
continue
t = trim(t)
if (length(t) == 0)
continue
else if (copytext(t, 1, 2) == "#")
continue
var/pos = findtext(t, " ")
var/name = null
// var/value = null
if (pos)
name = lowertext(copytext(t, 1, pos))
// value = copytext(t, pos + 1)
else
name = lowertext(t)
if (!name)
continue
potentialRandomZlevels.Add(t)
if(potentialRandomZlevels.len)
var/map = pick(potentialRandomZlevels)
var/file = file(map)
if(isfile(file))
maploader.load_map(file)
else
return
+249
View File
@@ -0,0 +1,249 @@
dmm_suite{
load_map(var/dmm_file as file, var/z_offset as num){
if(!z_offset){
z_offset = world.maxz+1
}
var/quote = ascii2text(34)
var/tfile = file2text(dmm_file)
var/tfile_len = length(tfile)
var/list/grid_models[0]
var/key_len = length(copytext(tfile,2,findtext(tfile,quote,2,0)))
for(var/lpos=1;lpos<tfile_len;lpos=findtext(tfile,"\n",lpos,0)+1){
var/tline = copytext(tfile,lpos,findtext(tfile,"\n",lpos,0))
if(copytext(tline,1,2)!=quote){break}
var/model_key = copytext(tline,2,findtext(tfile,quote,2,0))
var/model_contents = copytext(tline,findtext(tfile,"=")+3,length(tline))
grid_models[model_key] = model_contents
sleep(-1)
}
var/zcrd=-1
var/ycrd=0
var/xcrd=0
for(var/zpos=findtext(tfile,"\n(1,1,");TRUE;zpos=findtext(tfile,"\n(1,1,",zpos+1,0)){
zcrd++
world.maxz = max(world.maxz, zcrd+z_offset)
ycrd=0
var/zgrid = copytext(tfile,findtext(tfile,quote+"\n",zpos,0)+2,findtext(tfile,"\n"+quote,zpos,0)+1)
for(var/gpos=1;gpos!=0;gpos=findtext(zgrid,"\n",gpos,0)+1){
var/grid_line = copytext(zgrid,gpos,findtext(zgrid,"\n",gpos,0)+1)
var/y_depth = length(zgrid)/(length(grid_line))
if(world.maxy<y_depth){world.maxy=y_depth}
grid_line=copytext(grid_line,1,length(grid_line))
if(!ycrd){
ycrd = y_depth
}
else{ycrd--}
xcrd=0
for(var/mpos=1;mpos<=length(grid_line);mpos+=key_len){
xcrd++
if(world.maxx<xcrd){world.maxx=xcrd}
var/model_key = copytext(grid_line,mpos,mpos+key_len)
parse_grid(grid_models[model_key],xcrd,ycrd,zcrd+z_offset)
}
if(gpos+length(grid_line)+1>length(zgrid)){break}
sleep(-1)
}
if(findtext(tfile,quote+"}",zpos,0)+2==tfile_len){break}
sleep(-1)
}
}
proc{
parse_grid(var/model as text,var/xcrd as num,var/ycrd as num,var/zcrd as num){
/*Method parse_grid()
- Accepts a text string containing a comma separated list of type paths of the
same construction as those contained in a .dmm file, and instantiates them.
*/
var/list/text_strings[0]
for(var/index=1;findtext(model,quote);index++){
/*Loop: Stores quoted portions of text in text_strings, and replaces them with an
index to that list.
- Each iteration represents one quoted section of text.
*/
text_strings.len=index
text_strings[index] = copytext(model,findtext(model,quote)+1,findtext(model,quote,findtext(model,quote)+1,0))
model = copytext(model,1,findtext(model,quote))+"~[index]"+copytext(model,findtext(model,quote,findtext(model,quote)+1,0)+1,0)
sleep(-1)
}
var/list/old_turf_underlays[0]
var/old_turf_density
var/old_turf_opacity
/*The old_turf variables store information about turfs instantiated in this location/iteration.
This is done to approximate the layered turf effect of DM's map editor.
An image of each turf is stored in old_turf_underlays[], and is later added to the new turf's underlays.
*/
for(var/dpos=1;dpos!=0;dpos=findtext(model,",",dpos,0)+1){
/*Loop: Identifies each object's data, instantiates it, and reconstitues it's fields.
- Each iteration represents one object's data, including type path and field values.
*/
var/full_def = copytext(model,dpos,findtext(model,",",dpos,0))
var/atom_def = text2path(copytext(full_def,1,findtext(full_def,"{")))
var/list/attributes[0]
if(findtext(full_def,"{")){
full_def = copytext(full_def,1,length(full_def))
for(var/apos=findtext(full_def,"{")+1;apos!=0;apos=findtext(full_def,";",apos,0)+1){
//Loop: Identifies each attribute/value pair, and stores it in attributes[].
attributes.Add(copytext(full_def,apos,findtext(full_def,";",apos,0)))
if(!findtext(copytext(full_def,apos,0),";")){break}
sleep(-1)
}
}
//Construct attributes associative list
var/list/fields = new(0)
for(var/index=1;index<=attributes.len;index++){
var/trim_left = trim_text(copytext(attributes[index],1,findtext(attributes[index],"=")))
var/trim_right = trim_text(copytext(attributes[index],findtext(attributes[index],"=")+1,0))
//Check for string
if(findtext(trim_right,"~")){
var/reference_index = copytext(trim_right,findtext(trim_right,"~")+1,0)
trim_right=text_strings[text2num(reference_index)]
}
//Check for number
else if(isnum(text2num(trim_right))){
trim_right = text2num(trim_right)
}
//Check for file
else if(copytext(trim_right,1,2) == "'"){
trim_right = file(copytext(trim_right,2,length(trim_right)))
}
fields[trim_left] = trim_right
}
//End construction
//Begin Instanciation
var/atom/instance
var/dmm_suite/preloader/_preloader = new(fields)
if(ispath(atom_def,/area)){
instance = locate(atom_def)
instance.contents.Add(locate(xcrd,ycrd,zcrd))
}
else if(ispath(atom_def,/turf)){
var/turf/old_turf = locate(xcrd,ycrd,zcrd)
if(old_turf.density){old_turf_density = 1}
if(old_turf.opacity){old_turf_opacity = 1}
if(old_turf.icon){
var/image/old_turf_image = image(old_turf.icon,null,old_turf.icon_state,old_turf.layer,old_turf.dir)
old_turf_underlays.Add(old_turf_image)
}
instance = new atom_def(old_turf, _preloader)
for(var/inverse_index=old_turf_underlays.len;inverse_index;inverse_index--){
var/image/image_underlay = old_turf_underlays[inverse_index]
image_underlay.loc = instance
instance.underlays.Add(image_underlay)
}
if(!instance.density){instance.density = old_turf_density}
if(!instance.opacity){instance.opacity = old_turf_opacity}
}
if(_preloader && instance){
_preloader.load(instance)
}
//End Instanciation
if(!findtext(copytext(model,dpos,0),",")){break}
sleep(-1)
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
for(var/dpos=1;dpos!=0;dpos=findtext(model,",",dpos,0)+1)
{
/*Loop: Identifies each object's data, instantiates it, and reconstitues it's fields.
- Each iteration represents one object's data, including type path and field values.
*/
var/full_def = copytext(model,dpos,findtext(model,",",dpos,0))
var/atom_def = text2path(copytext(full_def,1,findtext(full_def,"{")))
var/list/attributes[0]
if(findtext(full_def,"{")){
full_def = copytext(full_def,1,length(full_def))
for(var/apos=findtext(full_def,"{")+1;apos!=0;apos=findtext(full_def,";",apos,0)+1){
//Loop: Identifies each attribute/value pair, and stores it in attributes[].
attributes.Add(copytext(full_def,apos,findtext(full_def,";",apos,0)))
if(!findtext(copytext(full_def,apos,0),";")){break}
sleep(-1)
}
}
//Construct attributes associative list
var/list/fields = new(0)
for(var/index=1;index<=attributes.len;index++){
var/trim_left = trim_text(copytext(attributes[index],1,findtext(attributes[index],"=")))
var/trim_right = trim_text(copytext(attributes[index],findtext(attributes[index],"=")+1,0))
//Check for string
if(findtext(trim_right,"~")){
var/reference_index = copytext(trim_right,findtext(trim_right,"~")+1,0)
trim_right=text_strings[text2num(reference_index)]
}
//Check for number
else if(isnum(text2num(trim_right))){
trim_right = text2num(trim_right)
}
//Check for file
else if(copytext(trim_right,1,2) == "'"){
trim_right = file(copytext(trim_right,2,length(trim_right)))
}
fields[trim_left] = trim_right
}
//End construction
//Begin Instanciation
var/atom/instance
var/dmm_suite/preloader/_preloader = new(fields)
if(!ispath(atom_def,/area) && !ispath(atom_def,/turf))
{
instance = new atom_def(locate(xcrd,ycrd,zcrd), _preloader)
}
if(_preloader && instance)
{
_preloader.load(instance)
}
//End Instanciation
if(!findtext(copytext(model,dpos,0),",")){break}
sleep(-1)
}
}
trim_text(var/what as text){
while(length(what) && findtext(what," ",1,2)){
what=copytext(what,2,0)
}
while(length(what) && findtext(what," ",length(what),0)){
what=copytext(what,1,length(what))
}
return what
}
}
}
atom/New(atom/loc, dmm_suite/preloader/_dmm_preloader){
if(istype(_dmm_preloader, /dmm_suite/preloader)){
_dmm_preloader.load(src)
}
. = ..()
}
dmm_suite{
preloader{
parent_type = /datum
var{
list/attributes
}
New(list/the_attributes){
.=..()
if(!the_attributes.len){ Del()}
attributes = the_attributes
}
proc{
load(atom/what){
for(var/attribute in attributes){
what.vars[attribute] = attributes[attribute]
}
Del()
}
}
}
}
+174
View File
@@ -0,0 +1,174 @@
#define DMM_IGNORE_AREAS 1
#define DMM_IGNORE_TURFS 2
#define DMM_IGNORE_OBJS 4
#define DMM_IGNORE_NPCS 8
#define DMM_IGNORE_PLAYERS 16
#define DMM_IGNORE_MOBS 24
dmm_suite{
var{
quote = "\""
list/letter_digits = list(
"a","b","c","d","e",
"f","g","h","i","j",
"k","l","m","n","o",
"p","q","r","s","t",
"u","v","w","x","y",
"z",
"A","B","C","D","E",
"F","G","H","I","J",
"K","L","M","N","O",
"P","Q","R","S","T",
"U","V","W","X","Y",
"Z"
)
}
save_map(var/turf/t1 as turf, var/turf/t2 as turf, var/map_name as text, var/flags as num){
//Check for illegal characters in file name... in a cheap way.
if(!((ckeyEx(map_name)==map_name) && ckeyEx(map_name))){
CRASH("Invalid text supplied to proc save_map, invalid characters or empty string.")
}
//Check for valid turfs.
if(!isturf(t1) || !isturf(t2)){
CRASH("Invalid arguments supplied to proc save_map, arguments were not turfs.")
}
var/file_text = write_map(t1,t2,flags)
if(fexists("[map_name].dmm")){
fdel("[map_name].dmm")
}
var/saved_map = file("[map_name].dmm")
saved_map << file_text
return saved_map
}
write_map(var/turf/t1 as turf, var/turf/t2 as turf, var/flags as num){
//Check for valid turfs.
if(!isturf(t1) || !isturf(t2)){
CRASH("Invalid arguments supplied to proc write_map, arguments were not turfs.")
}
var/turf/nw = locate(min(t1.x,t2.x),max(t1.y,t2.y),min(t1.z,t2.z))
var/turf/se = locate(max(t1.x,t2.x),min(t1.y,t2.y),max(t1.z,t2.z))
var/list/templates[0]
var/template_buffer = {""}
var/dmm_text = {""}
for(var/pos_z=nw.z;pos_z<=se.z;pos_z++){
for(var/pos_y=nw.y;pos_y>=se.y;pos_y--){
for(var/pos_x=nw.x;pos_x<=se.x;pos_x++){
var/turf/test_turf = locate(pos_x,pos_y,pos_z)
var/test_template = make_template(test_turf, flags)
var/template_number = templates.Find(test_template)
if(!template_number){
templates.Add(test_template)
template_number = templates.len
}
template_buffer += "[template_number],"
}
template_buffer += ";"
}
template_buffer += "."
}
var/key_length = round/*floor*/(log(letter_digits.len,templates.len-1)+1)
var/list/keys[templates.len]
for(var/key_pos=1;key_pos<=templates.len;key_pos++){
keys[key_pos] = get_model_key(key_pos,key_length)
dmm_text += {""[keys[key_pos]]" = ([templates[key_pos]])\n"}
}
var/z_level = 0
for(var/z_pos=1;TRUE;z_pos=findtext(template_buffer,".",z_pos)+1){
if(z_pos>=length(template_buffer)){break}
if(z_level){dmm_text+={"\n"}}
dmm_text += {"\n(1,1,[++z_level]) = {"\n"}
var/z_block = copytext(template_buffer,z_pos,findtext(template_buffer,".",z_pos))
for(var/y_pos=1;TRUE;y_pos=findtext(z_block,";",y_pos)+1){
if(y_pos>=length(z_block)){break}
var/y_block = copytext(z_block,y_pos,findtext(z_block,";",y_pos))
for(var/x_pos=1;TRUE;x_pos=findtext(y_block,",",x_pos)+1){
if(x_pos>=length(y_block)){break}
var/x_block = copytext(y_block,x_pos,findtext(y_block,",",x_pos))
var/key_number = text2num(x_block)
var/temp_key = keys[key_number]
dmm_text += temp_key
sleep(-1)
}
dmm_text += {"\n"}
sleep(-1)
}
dmm_text += {"\"}"}
sleep(-1)
}
return dmm_text
}
proc{
make_template(var/turf/model as turf, var/flags as num){
var/template = ""
var/obj_template = ""
var/mob_template = ""
var/turf_template = ""
if(!(flags & DMM_IGNORE_TURFS)){
turf_template = "[model.type][check_attributes(model)],"
} else{ turf_template = "[world.turf],"}
var/area_template = ""
if(!(flags & DMM_IGNORE_OBJS)){
for(var/obj/O in model.contents){
obj_template += "[O.type][check_attributes(O)],"
}
}
for(var/mob/M in model.contents){
if(M.client){
if(!(flags & DMM_IGNORE_PLAYERS)){
mob_template += "[M.type][check_attributes(M)],"
}
}
else{
if(!(flags & DMM_IGNORE_NPCS)){
mob_template += "[M.type][check_attributes(M)],"
}
}
}
if(!(flags & DMM_IGNORE_AREAS)){
var/area/m_area = model.loc
area_template = "[m_area.type][check_attributes(m_area)]"
} else{ area_template = "[world.area]"}
template = "[obj_template][mob_template][turf_template][area_template]"
return template
}
check_attributes(var/atom/A){
var/attributes_text = {"{"}
for(var/V in A.vars){
sleep(-1)
if((!issaved(A.vars[V])) || (A.vars[V]==initial(A.vars[V]))){continue}
if(istext(A.vars[V])){
attributes_text += {"[V] = "[A.vars[V]]""}
}
else if(isnum(A.vars[V])||ispath(A.vars[V])){
attributes_text += {"[V] = [A.vars[V]]"}
}
else if(isicon(A.vars[V])||isfile(A.vars[V])){
attributes_text += {"[V] = '[A.vars[V]]'"}
}
else{
continue
}
if(attributes_text != {"{"}){
attributes_text+={"; "}
}
}
if(attributes_text=={"{"}){
return
}
if(copytext(attributes_text, length(attributes_text)-1, 0) == {"; "}){
attributes_text = copytext(attributes_text, 1, length(attributes_text)-1)
}
attributes_text += {"}"}
return attributes_text
}
get_model_key(var/which as num, var/key_length as num){
var/key = ""
var/working_digit = which-1
for(var/digit_pos=key_length;digit_pos>=1;digit_pos--){
var/place_value = round/*floor*/(working_digit/(letter_digits.len**(digit_pos-1)))
working_digit-=place_value*(letter_digits.len**(digit_pos-1))
key = "[key][letter_digits[place_value+1]]"
}
return key
}
}
}
@@ -11,6 +11,7 @@
src.stand_icon = new /icon('alien.dmi', "aliend_s")
src.lying_icon = new /icon('alien.dmi', "aliend_l")
src.resting_icon = new /icon('alien.dmi', "aliend_sleep")
src.running_icon = new /icon('alien.dmi', "aliend_running")
src.icon = src.stand_icon
update_clothing()
src << "\blue Your icons have been generated!"
@@ -10,6 +10,7 @@
src.stand_icon = new /icon('alien.dmi', "alienh_s")
src.lying_icon = new /icon('alien.dmi', "alienh_l")
src.resting_icon = new /icon('alien.dmi', "alienh_sleep")
src.running_icon = new /icon('alien.dmi', "alienh_running")
src.icon = src.stand_icon
update_clothing()
src << "\blue Your icons have been generated!"
@@ -10,6 +10,7 @@
src.stand_icon = new /icon('alien.dmi', "aliens_s")
src.lying_icon = new /icon('alien.dmi', "aliens_l")
src.resting_icon = new /icon('alien.dmi', "aliens_sleep")
src.running_icon = new /icon('alien.dmi', "aliens_running")
src.icon = src.stand_icon
update_clothing()
src << "\blue Your icons have been generated!"
@@ -11,6 +11,7 @@
stand_icon = new /icon('alien.dmi', "alien_s")
lying_icon = new /icon('alien.dmi', "alien_l")
resting_icon = new /icon('alien.dmi', "alienh_sleep")
running_icon = new /icon('alien.dmi', "alienh_running")
icon = stand_icon
update_clothing()
src << "\blue Your icons have been generated!"
@@ -336,6 +337,13 @@
else
icon = resting_icon
else if(!lying)
if(update_icon)
if(m_intent == "run")
icon = running_icon
else
icon = stand_icon
overlays += body_lying
if (face_lying)
@@ -12,6 +12,8 @@
src.verbs -= /mob/living/carbon/alien/humanoid/verb/ventcrawl
src.stand_icon = new /icon('alien.dmi', "queen_s")
src.lying_icon = new /icon('alien.dmi', "queen_l")
src.resting_icon = new /icon('alien.dmi', "queen_sleep")
src.running_icon = new /icon('alien.dmi', "queen_running")
src.icon = src.stand_icon
update_clothing()
src << "\blue Your icons have been generated!"
@@ -102,8 +102,11 @@
/mob/living/carbon/human/proc/ChangeToHusk()
if(mutations & HUSK)
return
var/datum/organ/external/head/head = get_organ("head")
if(head)
head.disfigured = 1
name = get_visible_name()
mutations |= HUSK
real_name = "Unknown"
update_body()
return
+24 -38
View File
@@ -1189,37 +1189,8 @@
overlays += image("icon" = 'belt.dmi', "icon_state" = text("[][]", t1, (!( lying ) ? null : "2")), "layer" = MOB_LAYER)
belt.screen_loc = ui_belt
if ((wear_mask && !(wear_mask.see_face)) || (head && !(head.see_face))) // can't see the face
if (wear_id)
if (istype(wear_id, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/id = wear_id
if (id.registered_name)
name = id.registered_name
else
name = "Unknown"
else if (istype(wear_id, /obj/item/device/pda))
var/obj/item/device/pda/pda = wear_id
if (pda.owner)
name = pda.owner
else
name = "Unknown"
else
name = "Unknown"
else
if (wear_id)
if (istype(wear_id, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/id = wear_id
if (id.registered_name != real_name)
name = "[real_name] (as [id.registered_name])"
else if (istype(wear_id, /obj/item/device/pda))
var/obj/item/device/pda/pda = wear_id
if (pda.owner)
if (pda.owner != real_name)
name = "[real_name] (as [pda.owner])"
else
name = real_name
name = get_visible_name()
if (wear_id)
wear_id.screen_loc = ui_id
@@ -2364,18 +2335,33 @@ It can still be worn/put on as normal.
return if_no_id
return
//repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a seperate proc as it'll be useful elsewhere
/mob/living/carbon/human/proc/get_visible_name()
if ((wear_mask && !(wear_mask.see_face)) || (head && !(head.see_face))) // can't see their face
return get_id_name("Unknown")
else
var/face_name = get_face_name()
var/id_name = get_id_name("")
if(id_name && (id_name != face_name))
return "[face_name] as ([id_name])"
return face_name
//Returns "Unknown" if facially disfigured and real_name if not. Useful for setting name when polyacided or when updating a human's name variable
/mob/living/carbon/human/proc/get_face_name()
var/datum/organ/external/head/head = get_organ("head")
if(!head || head.disfigured) //no face!
return "Unknown"
else
return "[real_name]"
//gets name from ID or PDA itself, ID inside PDA doesn't matter
//Useful when player is being seen by other mobs
/mob/living/carbon/human/proc/get_visible_name(var/if_no_id = "Unknown")
/mob/living/carbon/human/proc/get_id_name(var/if_no_id = "Unknown")
var/obj/item/device/pda/pda = wear_id
var/obj/item/weapon/card/id/id = wear_id
if (istype(pda))
. = pda.owner
else if (istype(id))
. = id.registered_name
else
return if_no_id
return
if(istype(pda)) return pda.owner
if(istype(id)) return id.registered_name
return if_no_id
//gets ID card object from special clothes slot or null.
/mob/living/carbon/human/proc/get_idcard()
@@ -1,3 +1,13 @@
//Instead of setting real_name = "Unknown", use this when necessary.
//It will prevent the cloned-as-unknown bug and various other derpy things.
/mob/living/carbon/human/proc/disfigure_face()
var/datum/organ/external/head/head = get_organ("head")
if(head && !head.disfigured)
head.disfigured = 1
name = get_visible_name()
src << "\red Your face has become disfigured."
warn_flavor_changed()
/mob/living/carbon/human/proc/HealDamage(zone, brute, burn)
var/datum/organ/external/E = get_organ(zone)
if(istype(E, /datum/organ/external))
@@ -37,7 +37,7 @@ emp_act
if(check_shields(P.damage, "the [P.name]"))
P.on_hit(src, 2)
return 2
return (..())
return (..(P , def_zone))
/mob/living/carbon/human/getarmor(var/def_zone, var/type)
+3 -4
View File
@@ -1021,15 +1021,14 @@
if (stuttering) stuttering--
if (slurring) slurring--
//Carn: marker 4#
var/datum/organ/external/head/head = organs["head"]
if(head && !head.disfigured)
if(head.brute_dam >= 45 || head.burn_dam >= 45)
head.disfigured = 1
emote("scream")
real_name = "Unknown"
src << "\red Your face has become disfigured."
disfigure_face()
face_op_stage = 0.0
warn_flavor_changed()
var/blood_max = 0
for(var/name in organs)
var/datum/organ/external/temp = organs[name]
@@ -20,7 +20,7 @@
var/alt_name = ""
if (istype(src, /mob/living/carbon/human) && src.name != src.real_name)
var/mob/living/carbon/human/H = src
alt_name = " (as [H.get_visible_name()])"
alt_name = " (as [H.get_id_name("Unknown")])"
// Mute disability
if (src.disabilities & 64)
return
+3 -4
View File
@@ -217,12 +217,11 @@
SetParalysis(0)
SetStunned(0)
SetWeakened(0)
src.radiation = 0
src.nutrition = 400
src.bodytemperature = initial(src.bodytemperature)
//src.health = 100
if(ishuman(src))
src.radiation = 0
//M.health = 100
src.nutrition = 400
src.bodytemperature = initial(src.bodytemperature)
src.heal_overall_damage(1000, 1000)
//M.updatehealth()
src.buckled = initial(src.buckled)
+1 -1
View File
@@ -67,7 +67,7 @@
var/alt_name = ""
if (istype(src, /mob/living/carbon/human) && name != real_name)
var/mob/living/carbon/human/H = src
alt_name = " (as [H.get_visible_name()])"
alt_name = " (as [H.get_id_name("Unknown")])"
var/italics = 0
var/message_range = null
var/message_mode = null
@@ -12,6 +12,10 @@
return 1
if (istype(other, /mob/living/silicon/decoy))
return 1
if (istype(other, /mob/living/carbon/brain))
return 1
if (istype(other, /mob/living/silicon/pai))
return 1
return ..()
/mob/living/silicon/ai/say_quote(var/text)
+12 -9
View File
@@ -205,13 +205,16 @@ var/datum/paiController/paiController // Global handler for pAI candidates
if(c.key == O.key)
hasSubmitted = 1
if(!hasSubmitted && O.client.be_pai)
spawn question(O.client, origin)
question(O.client)
proc/question(var/client/C, var/mob/origin)
asked.Add(C.key)
asked[C.key] = world.time
var/response = alert(C, "[origin] is requesting a pAI personality. Would you like to play as a personal AI?", "pAI Request", "Yes", "No", "Never for this round")
if(response == "Yes")
recruitWindow(C.mob)
else if (response == "Never for this round")
C.be_pai = 0
proc/question(var/client/C)
spawn(0)
if(!C) return
asked.Add(C.key)
asked[C.key] = world.time
var/response = alert(C, "Someone is requesting a pAI personality. Would you like to play as a personal AI?", "pAI Request", "Yes", "No", "Never for this round")
if(!C) return //handle logouts that happen whilst the alert is waiting for a response.
if(response == "Yes")
recruitWindow(C.mob)
else if (response == "Never for this round")
C.be_pai = 0
@@ -13,9 +13,10 @@
src.real_name += " "
src.real_name += "-[ident]"
src.name = src.real_name
if(!src.connected_ai)
/*if(!src.connected_ai)
for(var/mob/living/silicon/ai/A in world)
src.connected_ai = A
A.connected_robots += src
break
*/
return
@@ -5,6 +5,10 @@
return 1
if (istype(other, /mob/living/carbon/human))
return 1
if (istype(other, /mob/living/carbon/brain))
return 1
if (istype(other, /mob/living/silicon/pai))
return 1
// if (istype(other, /mob/living/silicon/hivebot))
// return 1
return ..()
+14 -16
View File
@@ -621,22 +621,7 @@
if(src:cameraFollow)
src:cameraFollow = null
/client/Topic(href, href_list)
if(href_list["priv_msg"])
var/client/C = locate(href_list["priv_msg"])
if(ismob(C)) //Old stuff can pass in mobs instead of clients
var/mob/M = C
C = M.client
cmd_admin_pm(C,null)
else
..()
/mob/Topic(href, href_list)
if(href_list["priv_msg"]) //for priv_msg references that have yet to be updated to target clients. Forwards it to client/Topic()
if(client)
client.Topic(href, href_list)
if(href_list["mach_close"])
var/t1 = text("window=[href_list["mach_close"]]")
machine = null
@@ -685,7 +670,7 @@
onclose(usr, "[name]")
if(href_list["flavor_change"])
update_flavor_text()
..()
// ..()
return
/mob/proc/get_damage()
@@ -713,6 +698,19 @@
if ( !usr || usr==src || !istype(src.loc,/turf) ) //if there's no person pulling OR the person is pulling themself OR the object being pulled is inside something: abort!
return
if(ishuman(usr))
if(usr.hand) // if he's using his left hand.
var/datum/organ/external/temp = usr:get_organ("l_hand")
if(temp.destroyed)
usr << "\blue You look at your stump."
return
else
var/datum/organ/external/temp = usr:get_organ("r_hand")
if(temp.destroyed)
usr << "\blue You look at your stump."
return
if (!( anchored ))
usr.pulling = src
if(ismob(src))
+15
View File
@@ -352,3 +352,18 @@
stat = DEAD
density = 0
return
/mob/living/simple_animal/ex_act(severity)
flick("flash", flash)
switch (severity)
if (1.0)
health -= 500
gib()
return
if (2.0)
health -= 60
if(3.0)
health -= 30
+1 -1
View File
@@ -40,7 +40,7 @@
if(mode)
usr << "\blue You turn on the hand labeler."
//Now let them chose the text.
var/str = input(usr,"Label text?","Set label","")
var/str = reject_bad_text(input(usr,"Label text?","Set label","")) //sanitize stuff! GOD DAMN THIS IS A SECURITY HOLE
if(!str || !length(str))
usr << "\red Invalid text."
return
+1 -1
View File
@@ -31,7 +31,7 @@
if(!A || !isarea(A) || !A.master)
return 0 // if not, then not powered
return A.master.powered(chan) // return power status of the area
return A.master.powered(power_channel) // return power status of the area
// increment the power usage stats for an area
+1 -1
View File
@@ -1,5 +1,5 @@
/obj/item/weapon/gun
name = "\improper Gun"
name = "gun"
desc = "Its a gun. It's pretty terrible, though."
icon = 'gun.dmi'
icon_state = "detective"
+19
View File
@@ -47,6 +47,25 @@ Stuff which is in development and not yet visible to players or just code relate
should be listed in the changelog upon commit though. Thanks. -->
<!-- To take advantage of the pretty new format (well it was new when I wrote this anyway), open the "add-to-changelog.html" file in any browser and add the stuff and then generate the html code and paste it here -->
<div class="commit sansserif">
<h2 class="date">10 May 2012</h2>
<h3 class="author">TG updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">New drinks recipes!</li>
<li class="rscadd">Different types of cigarettes added to contraband ordering.</li>
<li class="rscadd">Emergency Toolboxes now contain smaller, lighter fire extinguishers that actually fit inside them!</li>
<li class="tweak">AIs and Cyborgs can now understand PAIs and MMIs.</li>
<li class="tweak">Adminwho now shows admin ranks.</li>
<li class="tweak">You can't pull things with missing hands anymore.</li>
<li class="tweak">Nuke ops now spawn with an extended oxygen tanks.</li>
<li class="tweak">Botany leather gloves can now remove lights without burning yourself.</li>
<li class="imageadd">New xeno sprites when running.</li>
<li class="imageadd">Piano is now a Minimoog!</li>
<li class="imageadd">Switched back to oldbody bag sprites.</li>
<li class="imageadd">New Oddyseus destroyed sprites.</li>
</ul>
</div>
<div class="commit sansserif">
<h2 class="date">07 May 2012</h2>
<h3 class="author">TG updated:</h3>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 122 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 KiB

After

Width:  |  Height:  |  Size: 336 KiB

+66
View File
@@ -0,0 +1,66 @@
"a" = (/turf/space,/area)
"b" = (/turf/unsimulated/wall,/area)
"c" = (/obj/machinery/shield,/turf/simulated/wall/cult,/area/turret_protected/AssistantRoom)
"d" = (/obj/machinery/turret{dir = 8; lasers = 1; name = "Angry Turret"},/obj/machinery/light{dir = 1},/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"e" = (/obj/machinery/light{icon_state = "tube1"; dir = 8},/obj/machinery/turret{dir = 8; lasers = 1; name = "Angry Turret"},/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"f" = (/obj/item/weapon/gift,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"g" = (/obj/effect/accelerated_particle,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"h" = (/obj/item/weapon/gun/energy/gun/nuclear,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"i" = (/obj/item/device/soulstone,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"j" = (/obj/item/ammo_magazine,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"k" = (/obj/effect/rune,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"l" = (/obj/machinery/turret{dir = 8; lasers = 1; name = "Angry Turret"},/obj/machinery/light{icon_state = "tube1"; dir = 4},/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"m" = (/obj/item/weapon/mousetrap/armed,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"n" = (/obj/item/weapon/nullrod,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"o" = (/obj/item/weapon/card/id/captains_spare,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"p" = (/obj/item/weapon/gun/energy/pulse_rifle/M1911,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"q" = (/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"r" = (/obj/item/weapon/card/emag,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"s" = (/obj/item/tk_grab,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"t" = (/obj/item/device/powersink,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"u" = (/obj/item/device/radio/beacon,/obj/item/weapon/caution,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"v" = (/obj/item/brain,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"w" = (/obj/item/weapon/gun/energy/laser/captain,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"x" = (/obj/item/weapon/gun/projectile/deagle/gold,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"y" = (/obj/item/weapon/sord,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"z" = (/obj/item/weapon/gun/energy/lasercannon,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"A" = (/obj/item/weapon/gun/energy/crossbow/largecrossbow,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"B" = (/obj/item/weapon/gun/energy/pulse_rifle/destroyer,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"C" = (/obj/item/toy/spinningtoy,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"D" = (/obj/item/weapon/card/id/centcom,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"E" = (/obj/item/weapon/gun/grenadelauncher,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"F" = (/obj/item/weapon/chemsprayer,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
"G" = (/obj/machinery/turret{dir = 8; lasers = 1; name = "Angry Turret"},/obj/machinery/light,/turf/simulated/floor{icon_state = "whiteshiny"},/area/turret_protected/AssistantRoom)
(1,1,1) = {"
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaabbbbbbbbbbbbaaaaaaaaa
aaaaaaaaabccccccccccbaaaaaaaaa
aaaaaaaaabccddddddccbaaaaaaaaa
aaaaaaaaabcefghijklcbaaaaaaaaa
aaaaaaaaabcemnopqrlcbaaaaaaaaa
aaaaaaaaabcestquvqlcbaaaaaaaaa
aaaaaaaaabcewqqxqylcbaaaaaaaaa
aaaaaaaaabceqzAqBqlcbaaaaaaaaa
aaaaaaaaabceCqDqEFlcbaaaaaaaaa
aaaaaaaaabccGGGGGGccbaaaaaaaaa
aaaaaaaaabccccccccccbaaaaaaaaa
aaaaaaaaabbbbbbbbbbbbaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"}
+8
View File
@@ -0,0 +1,8 @@
#List the potential random Z-levels here.
#Maps must be the full path to them
#Maps should be 255x255 or smaller and be bounded. Falling off the edge of the map will result in undefined behavior.
#Please ensure that your maps have a minimum distnace from the edge of 10 units, due to 'seamless transition' range
#SPECIFYING AN INVALID MAP WILL RESULT IN RUNTIMES ON GAME START
#maps/RandomZLevels/assistantChamber.dmm
+70 -70
View File
@@ -4586,7 +4586,7 @@
"bKj" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/turf/simulated/wall/r_wall,/area/toxins/xenobiology)
"bKk" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/obj/structure/closet/secure_closet/scientist,/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bKl" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/obj/machinery/light{dir = 1},/obj/structure/closet/l3closet/scientist,/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bKm" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/obj/machinery/computer/operating{id = "xenobio"; name = "Xenobiology Operating Computer"},/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bKm" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/obj/machinery/computer/operating,/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bKn" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/obj/machinery/light{dir = 1},/obj/item/weapon/circular_saw,/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bKo" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/obj/item/weapon/scalpel,/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bKp" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
@@ -4647,7 +4647,7 @@
"bLs" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = "Streight"},/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/obj/effect/sign/biohazard{pixel_x = 28},/turf/simulated/floor{icon_state = "white"},/area/medical/research{name = "Research Division"})
"bLt" = (/obj/machinery/alarm{dir = 4; icon_state = "alarm0"; pixel_x = -22},/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bLu" = (/obj/effect/landmark/start{name = "Scientist"},/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bLv" = (/obj/machinery/optable{id = "xenobio"; name = "Xenobiology Operating Table"},/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bLv" = (/obj/machinery/optable,/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bLw" = (/obj/structure/table,/obj/item/clothing/suit/straight_jacket,/obj/item/clothing/mask/muzzle,/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bLx" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced,/turf/simulated/floor/plating,/area/toxins/xenobiology)
"bLy" = (/obj/machinery/door/window/southleft{name = "Monkey Pen"; req_access_txt = "55"},/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
@@ -4700,7 +4700,7 @@
"bMt" = (/obj/structure/stool/bed/chair{dir = 4},/obj/machinery/light{dir = 1},/turf/simulated/floor{icon_state = "dark"},/area/medical/surgery)
"bMu" = (/obj/structure/grille,/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id = "Observation Shutters"; name = "Observation Shutters"; opacity = 0},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor/plating,/area/medical/surgery)
"bMv" = (/obj/structure/table,/obj/item/weapon/hemostat,/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bMw" = (/obj/machinery/computer/operating{id = "medbay"},/obj/machinery/light{dir = 1},/obj/machinery/camera{c_tag = "Operating Theatre"; dir = 2; network = "Medbay"; pixel_x = 22},/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bMw" = (/obj/machinery/light{dir = 1},/obj/machinery/camera{c_tag = "Operating Theatre"; dir = 2; network = "Medbay"; pixel_x = 22},/obj/machinery/computer/operating,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bMx" = (/obj/machinery/door_control{id = "Observation Shutters"; name = "Observation Shutter Control"; pixel_y = 25},/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bMy" = (/obj/structure/table,/obj/item/clothing/glasses/hud/health,/obj/item/clothing/glasses/hud/health,/obj/item/clothing/glasses/hud/health,/obj/item/clothing/glasses/hud/health,/obj/item/clothing/glasses/hud/health,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bMz" = (/obj/machinery/atmospherics/pipe/simple,/turf/simulated/wall/r_wall,/area/toxins/server)
@@ -4762,63 +4762,63 @@
"bND" = (/obj/structure/grille,/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id = "Observation Shutters"; name = "Observation Shutters"; opacity = 0},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 4},/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor/plating,/area/medical/surgery)
"bNE" = (/obj/structure/table,/obj/machinery/atmospherics/pipe/manifold{color = "red"; icon_state = "manifold-r-f"; level = 1; name = "pipe manifold"},/obj/item/weapon/scalpel,/obj/item/weapon/autopsy_scanner,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bNF" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 4},/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bNG" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 10},/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bNH" = (/obj/structure/table,/obj/item/weapon/circular_saw,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bNI" = (/obj/machinery/r_n_d/server{id_with_download_string = "1"; id_with_upload_string = "1"; name = "Core R&D Server"; server_id = 1},/obj/machinery/atmospherics/pipe/simple,/turf/simulated/floor/grid{name = "Server Base"; nitrogen = 500; oxygen = 0; temperature = 80},/area/toxins/server)
"bNJ" = (/turf/simulated/floor/grid{name = "Server Base"; nitrogen = 500; oxygen = 0; temperature = 80},/area/toxins/server)
"bNK" = (/obj/machinery/camera{c_tag = "Server Room"; dir = 2; network = "Research"},/turf/simulated/floor/grid{name = "Server Base"; nitrogen = 500; oxygen = 0; temperature = 80},/area/toxins/server)
"bNL" = (/obj/machinery/blackbox_recorder,/obj/machinery/atmospherics/pipe/simple,/turf/simulated/floor/grid{name = "Server Base"; nitrogen = 500; oxygen = 0; temperature = 80},/area/toxins/server)
"bNM" = (/obj/structure/disposalpipe/segment{dir = 1},/obj/item/device/radio/intercom{dir = 8; name = "Station Intercom (General)"; pixel_x = -28},/obj/machinery/atmospherics/pipe/manifold{color = "blue"; dir = 8; icon_state = "manifold-b-f"; level = 1; name = "pipe manifold"},/turf/simulated/floor{icon_state = "white"},/area/medical/research{name = "Research Division"})
"bNN" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/obj/effect/sign/biohazard{pixel_x = 28},/turf/simulated/floor{icon_state = "white"},/area/medical/research{name = "Research Division"})
"bNO" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/obj/machinery/requests_console{department = "Xenobiology"; departmentType = 0; pixel_x = -30; pixel_y = 0},/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bNP" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = "Streight"},/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bNQ" = (/obj/structure/stool/bed/chair,/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bNR" = (/obj/machinery/atmospherics/valve,/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bNS" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk,/obj/machinery/light{icon_state = "tube1"; dir = 4},/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bNT" = (/obj/machinery/mass_driver{dir = 4; id = "toxinsdriver"},/turf/simulated/floor/plating,/area/toxins/observatory)
"bNU" = (/obj/machinery/light/small{dir = 1},/turf/simulated/floor/plating,/area/toxins/observatory)
"bNV" = (/turf/simulated/floor/plating,/area/toxins/observatory)
"bNW" = (/obj/machinery/door/poddoor{id = "toxinsdriver"; name = "Toxins Launcher Bay Door"},/turf/simulated/floor/plating,/area/toxins/observatory)
"bNX" = (/obj/machinery/door/poddoor{id = "toxinsdriver"; name = "Toxins Launcher Bay Door"},/turf/space,/area/toxins/test_area)
"bNY" = (/obj/item/device/radio/beacon,/turf/simulated/floor/airless{icon_state = "bot"},/area/toxins/test_area)
"bNZ" = (/obj/machinery/camera{c_tag = "East"; dir = 8; network = "Bomb Testing"; pixel_x = 0; pixel_y = -22},/obj/machinery/light/spot{dir = 4; layer = 2.8},/turf/simulated/floor/airless,/area/toxins/test_area)
"bOa" = (/obj/machinery/atmospherics/pipe/simple{dir = 4},/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bOb" = (/turf/simulated/wall,/area/assembly/chargebay)
"bOc" = (/obj/machinery/recharge_station,/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor{icon_state = "bot"},/area/assembly/chargebay)
"bOd" = (/obj/machinery/recharge_station,/turf/simulated/floor{icon_state = "bot"},/area/assembly/chargebay)
"bOe" = (/obj/machinery/door/airlock/maintenance{name = "Assembly Line Maintenance"; req_access_txt = "12;29"},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bOf" = (/obj/effect/showcase{icon_state = "showcase_3"},/turf/simulated/floor{icon_state = "showroomfloor"},/area/assembly/chargebay)
"bOg" = (/obj/machinery/light,/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/turf/simulated/floor/plating,/area/assembly/chargebay)
"bOh" = (/obj/machinery/atmospherics/portables_connector{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/machinery/portable_atmospherics/pump,/turf/simulated/floor{icon_state = "arrival"; dir = 8},/area/hallway/primary/aft)
"bOi" = (/obj/machinery/atmospherics/pipe/simple{color = "cyan"; dir = 10; icon_state = "intact-c"; initialize_directions = 10; level = 2},/turf/simulated/wall,/area/maintenance/asmaint)
"bOj" = (/obj/structure/closet/secure_closet/atmos_personal,/obj/machinery/light/small,/turf/simulated/floor,/area/atmos)
"bOk" = (/obj/structure/closet/wardrobe/atmospherics_yellow,/turf/simulated/floor,/area/atmos)
"bOl" = (/obj/machinery/vending/coffee,/turf/simulated/floor,/area/atmos)
"bOm" = (/obj/machinery/portable_atmospherics/canister/oxygen,/turf/simulated/floor{dir = 10; icon_state = "warning"},/area/atmos)
"bOn" = (/obj/machinery/portable_atmospherics/canister/carbon_dioxide,/turf/simulated/floor{icon_state = "warning"},/area/atmos)
"bOo" = (/obj/machinery/portable_atmospherics/canister/nitrogen,/turf/simulated/floor{icon_state = "warning"},/area/atmos)
"bOp" = (/obj/machinery/portable_atmospherics/canister/air,/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor{dir = 6; icon_state = "warning"},/area/atmos)
"bOq" = (/obj/machinery/light,/turf/simulated/floor,/area/atmos)
"bOr" = (/obj/machinery/atmospherics/binary/pump{dir = 1; icon_state = "intact_off"; name = "Emergency Tank Fill"; on = 0},/turf/simulated/floor,/area/atmos)
"bOs" = (/obj/machinery/atmospherics/pipe/simple{dir = 6; icon_state = "intact"; initialize_directions = 6; level = 2},/obj/machinery/meter,/turf/simulated/floor,/area/atmos)
"bOt" = (/obj/machinery/atmospherics/pipe/simple{color = "yellow"; icon_state = "intact-y"; level = 2},/obj/machinery/atmospherics/pipe/simple{dir = 4; icon_state = "intact"; level = 2},/turf/simulated/floor,/area/atmos)
"bOu" = (/obj/machinery/atmospherics/pipe/simple{color = "green"; icon_state = "intact-g"; level = 2},/obj/machinery/atmospherics/pipe/simple{dir = 4; icon_state = "intact"; level = 2},/turf/simulated/floor,/area/atmos)
"bOv" = (/obj/machinery/atmospherics/tvalve/digital{dir = 8; icon_state = "tvalve1"; state = 1; tag = "icon-tvalve0 (WEST)"},/turf/simulated/floor,/area/atmos)
"bOw" = (/obj/machinery/atmospherics/valve/digital{color = "yellow"; dir = 4; name = "Gas Mix Outlet Valve"},/turf/simulated/floor{icon_state = "green"; dir = 6},/area/atmos)
"bOx" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/atmospherics/pipe/simple{color = "yellow"; dir = 4; icon_state = "intact-y"; initialize_directions = 12; level = 2},/turf/simulated/floor/plating,/area/atmos)
"bOy" = (/obj/machinery/atmospherics/pipe/simple{color = "yellow"; dir = 4; icon_state = "intact-y"; initialize_directions = 12; level = 2},/obj/structure/grille,/turf/simulated/wall,/area)
"bOz" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 8; external_pressure_bound = 0; frequency = 1441; icon_state = "in"; id_tag = "waste_out"; initialize_directions = 1; internal_pressure_bound = 4000; on = 1; pressure_checks = 2; pump_direction = 0},/turf/simulated/floor/engine{name = "vacuum floor"; nitrogen = 0.01; oxygen = 0.01},/area/atmos)
"bOA" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden,/obj/machinery/light/small{dir = 4},/turf/simulated/wall,/area/medical/cmo)
"bOB" = (/obj/machinery/alarm{dir = 4; icon_state = "alarm0"; pixel_x = -22},/turf/simulated/floor{dir = 8; icon_state = "barber"},/area/medical/cmo)
"bOC" = (/obj/structure/stool/bed/chair{dir = 1},/turf/simulated/floor{dir = 8; icon_state = "barber"},/area/medical/cmo)
"bOD" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/turf/simulated/floor/plating,/area/medical/cmo)
"bOE" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/turf/simulated/floor{icon_state = "white"},/area/medical/medbay)
"bOF" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/medical{name = "Surgery Observation"; req_access_txt = "5"},/turf/simulated/floor{icon_state = "dark"},/area/medical/surgery)
"bOG" = (/obj/machinery/hologram/holopad,/turf/simulated/floor{icon_state = "dark"},/area/medical/surgery)
"bOH" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/floor{icon_state = "dark"},/area/medical/surgery)
"bOI" = (/obj/structure/grille,/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id = "Observation Shutters"; name = "Observation Shutters"; opacity = 0},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor/plating,/area/medical/surgery)
"bOJ" = (/obj/structure/table,/obj/item/weapon/surgicaldrill,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bOK" = (/obj/machinery/optable{id = "medbay"},/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bNG" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 4},/obj/machinery/optable,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bNH" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden{dir = 10},/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bNI" = (/obj/structure/table,/obj/item/weapon/circular_saw,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bNJ" = (/obj/machinery/r_n_d/server{id_with_download_string = "1"; id_with_upload_string = "1"; name = "Core R&D Server"; server_id = 1},/obj/machinery/atmospherics/pipe/simple,/turf/simulated/floor/grid{name = "Server Base"; nitrogen = 500; oxygen = 0; temperature = 80},/area/toxins/server)
"bNK" = (/turf/simulated/floor/grid{name = "Server Base"; nitrogen = 500; oxygen = 0; temperature = 80},/area/toxins/server)
"bNL" = (/obj/machinery/camera{c_tag = "Server Room"; dir = 2; network = "Research"},/turf/simulated/floor/grid{name = "Server Base"; nitrogen = 500; oxygen = 0; temperature = 80},/area/toxins/server)
"bNM" = (/obj/machinery/blackbox_recorder,/obj/machinery/atmospherics/pipe/simple,/turf/simulated/floor/grid{name = "Server Base"; nitrogen = 500; oxygen = 0; temperature = 80},/area/toxins/server)
"bNN" = (/obj/structure/disposalpipe/segment{dir = 1},/obj/item/device/radio/intercom{dir = 8; name = "Station Intercom (General)"; pixel_x = -28},/obj/machinery/atmospherics/pipe/manifold{color = "blue"; dir = 8; icon_state = "manifold-b-f"; level = 1; name = "pipe manifold"},/turf/simulated/floor{icon_state = "white"},/area/medical/research{name = "Research Division"})
"bNO" = (/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 4},/obj/effect/sign/biohazard{pixel_x = 28},/turf/simulated/floor{icon_state = "white"},/area/medical/research{name = "Research Division"})
"bNP" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 8; on = 1},/obj/machinery/requests_console{department = "Xenobiology"; departmentType = 0; pixel_x = -30; pixel_y = 0},/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bNQ" = (/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0; tag = "Streight"},/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bNR" = (/obj/structure/stool/bed/chair,/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bNS" = (/obj/machinery/atmospherics/valve,/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bNT" = (/obj/machinery/disposal,/obj/structure/disposalpipe/trunk,/obj/machinery/light{icon_state = "tube1"; dir = 4},/turf/simulated/floor{icon_state = "white"},/area/toxins/xenobiology)
"bNU" = (/obj/machinery/mass_driver{dir = 4; id = "toxinsdriver"},/turf/simulated/floor/plating,/area/toxins/observatory)
"bNV" = (/obj/machinery/light/small{dir = 1},/turf/simulated/floor/plating,/area/toxins/observatory)
"bNW" = (/turf/simulated/floor/plating,/area/toxins/observatory)
"bNX" = (/obj/machinery/door/poddoor{id = "toxinsdriver"; name = "Toxins Launcher Bay Door"},/turf/simulated/floor/plating,/area/toxins/observatory)
"bNY" = (/obj/machinery/door/poddoor{id = "toxinsdriver"; name = "Toxins Launcher Bay Door"},/turf/space,/area/toxins/test_area)
"bNZ" = (/obj/item/device/radio/beacon,/turf/simulated/floor/airless{icon_state = "bot"},/area/toxins/test_area)
"bOa" = (/obj/machinery/camera{c_tag = "East"; dir = 8; network = "Bomb Testing"; pixel_x = 0; pixel_y = -22},/obj/machinery/light/spot{dir = 4; layer = 2.8},/turf/simulated/floor/airless,/area/toxins/test_area)
"bOb" = (/obj/machinery/atmospherics/pipe/simple{dir = 4},/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced{dir = 1},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bOc" = (/turf/simulated/wall,/area/assembly/chargebay)
"bOd" = (/obj/machinery/recharge_station,/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor{icon_state = "bot"},/area/assembly/chargebay)
"bOe" = (/obj/machinery/recharge_station,/turf/simulated/floor{icon_state = "bot"},/area/assembly/chargebay)
"bOf" = (/obj/machinery/door/airlock/maintenance{name = "Assembly Line Maintenance"; req_access_txt = "12;29"},/turf/simulated/floor/plating,/area/maintenance/apmaint)
"bOg" = (/obj/effect/showcase{icon_state = "showcase_3"},/turf/simulated/floor{icon_state = "showroomfloor"},/area/assembly/chargebay)
"bOh" = (/obj/machinery/light,/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,/turf/simulated/floor/plating,/area/assembly/chargebay)
"bOi" = (/obj/machinery/atmospherics/portables_connector{dir = 4},/obj/structure/window/reinforced{dir = 1},/obj/machinery/portable_atmospherics/pump,/turf/simulated/floor{icon_state = "arrival"; dir = 8},/area/hallway/primary/aft)
"bOj" = (/obj/machinery/atmospherics/pipe/simple{color = "cyan"; dir = 10; icon_state = "intact-c"; initialize_directions = 10; level = 2},/turf/simulated/wall,/area/maintenance/asmaint)
"bOk" = (/obj/structure/closet/secure_closet/atmos_personal,/obj/machinery/light/small,/turf/simulated/floor,/area/atmos)
"bOl" = (/obj/structure/closet/wardrobe/atmospherics_yellow,/turf/simulated/floor,/area/atmos)
"bOm" = (/obj/machinery/vending/coffee,/turf/simulated/floor,/area/atmos)
"bOn" = (/obj/machinery/portable_atmospherics/canister/oxygen,/turf/simulated/floor{dir = 10; icon_state = "warning"},/area/atmos)
"bOo" = (/obj/machinery/portable_atmospherics/canister/carbon_dioxide,/turf/simulated/floor{icon_state = "warning"},/area/atmos)
"bOp" = (/obj/machinery/portable_atmospherics/canister/nitrogen,/turf/simulated/floor{icon_state = "warning"},/area/atmos)
"bOq" = (/obj/machinery/portable_atmospherics/canister/air,/obj/structure/window/reinforced{dir = 4},/turf/simulated/floor{dir = 6; icon_state = "warning"},/area/atmos)
"bOr" = (/obj/machinery/light,/turf/simulated/floor,/area/atmos)
"bOs" = (/obj/machinery/atmospherics/binary/pump{dir = 1; icon_state = "intact_off"; name = "Emergency Tank Fill"; on = 0},/turf/simulated/floor,/area/atmos)
"bOt" = (/obj/machinery/atmospherics/pipe/simple{dir = 6; icon_state = "intact"; initialize_directions = 6; level = 2},/obj/machinery/meter,/turf/simulated/floor,/area/atmos)
"bOu" = (/obj/machinery/atmospherics/pipe/simple{color = "yellow"; icon_state = "intact-y"; level = 2},/obj/machinery/atmospherics/pipe/simple{dir = 4; icon_state = "intact"; level = 2},/turf/simulated/floor,/area/atmos)
"bOv" = (/obj/machinery/atmospherics/pipe/simple{color = "green"; icon_state = "intact-g"; level = 2},/obj/machinery/atmospherics/pipe/simple{dir = 4; icon_state = "intact"; level = 2},/turf/simulated/floor,/area/atmos)
"bOw" = (/obj/machinery/atmospherics/tvalve/digital{dir = 8; icon_state = "tvalve1"; state = 1; tag = "icon-tvalve0 (WEST)"},/turf/simulated/floor,/area/atmos)
"bOx" = (/obj/machinery/atmospherics/valve/digital{color = "yellow"; dir = 4; name = "Gas Mix Outlet Valve"},/turf/simulated/floor{icon_state = "green"; dir = 6},/area/atmos)
"bOy" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/atmospherics/pipe/simple{color = "yellow"; dir = 4; icon_state = "intact-y"; initialize_directions = 12; level = 2},/turf/simulated/floor/plating,/area/atmos)
"bOz" = (/obj/machinery/atmospherics/pipe/simple{color = "yellow"; dir = 4; icon_state = "intact-y"; initialize_directions = 12; level = 2},/obj/structure/grille,/turf/simulated/wall,/area)
"bOA" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 8; external_pressure_bound = 0; frequency = 1441; icon_state = "in"; id_tag = "waste_out"; initialize_directions = 1; internal_pressure_bound = 4000; on = 1; pressure_checks = 2; pump_direction = 0},/turf/simulated/floor/engine{name = "vacuum floor"; nitrogen = 0.01; oxygen = 0.01},/area/atmos)
"bOB" = (/obj/machinery/atmospherics/pipe/simple/supply/hidden,/obj/machinery/light/small{dir = 4},/turf/simulated/wall,/area/medical/cmo)
"bOC" = (/obj/machinery/alarm{dir = 4; icon_state = "alarm0"; pixel_x = -22},/turf/simulated/floor{dir = 8; icon_state = "barber"},/area/medical/cmo)
"bOD" = (/obj/structure/stool/bed/chair{dir = 1},/turf/simulated/floor{dir = 8; icon_state = "barber"},/area/medical/cmo)
"bOE" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/structure/window/reinforced,/turf/simulated/floor/plating,/area/medical/cmo)
"bOF" = (/obj/machinery/atmospherics/unary/vent_pump{on = 1},/turf/simulated/floor{icon_state = "white"},/area/medical/medbay)
"bOG" = (/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/medical{name = "Surgery Observation"; req_access_txt = "5"},/turf/simulated/floor{icon_state = "dark"},/area/medical/surgery)
"bOH" = (/obj/machinery/hologram/holopad,/turf/simulated/floor{icon_state = "dark"},/area/medical/surgery)
"bOI" = (/obj/structure/stool/bed/chair{dir = 4},/turf/simulated/floor{icon_state = "dark"},/area/medical/surgery)
"bOJ" = (/obj/structure/grille,/obj/machinery/door/poddoor{density = 0; icon_state = "pdoor0"; id = "Observation Shutters"; name = "Observation Shutters"; opacity = 0},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/atmospherics/pipe/simple/supply/hidden,/turf/simulated/floor/plating,/area/medical/surgery)
"bOK" = (/obj/structure/table,/obj/item/weapon/surgicaldrill,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bOL" = (/obj/machinery/atmospherics/unary/vent_scrubber{dir = 1; on = 1; scrub_N2O = 1; scrub_Toxins = 0},/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bOM" = (/obj/structure/table,/obj/item/weapon/surgical_tool/bonegel,/obj/item/weapon/surgical_tool/bonesetter,/turf/simulated/floor{icon_state = "white"},/area/medical/surgery)
"bON" = (/obj/machinery/atmospherics/unary/vent_pump{dir = 1; on = 1},/obj/machinery/light{icon_state = "tube1"; dir = 8},/turf/simulated/floor{icon_state = "dark"},/area/toxins/server)
@@ -5368,7 +5368,7 @@
"bZl" = (/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plating/airless,/area)
"bZm" = (/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/floor/plating,/area)
"bZn" = (/obj/structure/disposalpipe/trunk{dir = 8},/obj/structure/disposaloutlet{dir = 4},/turf/simulated/floor/plating/airless,/area)
"bZo" = (/obj/machinery/computer/operating{id = "robotics"; name = "Robotics Operating Computer"},/turf/simulated/floor,/area/assembly/assembly_line)
"bZo" = (/obj/machinery/computer/operating,/turf/simulated/floor,/area/assembly/assembly_line)
"bZp" = (/obj/structure/table,/obj/item/weapon/circular_saw,/obj/item/weapon/scalpel,/obj/structure/disposalpipe/segment{dir = 1; icon_state = "pipe-c"},/turf/simulated/floor,/area/assembly/assembly_line)
"bZq" = (/obj/structure/disposalpipe/segment{dir = 4},/turf/simulated/wall,/area/assembly/assembly_line)
"bZr" = (/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"; tag = "90Curve"},/obj/structure/cable{d1 = 2; d2 = 4; icon_state = "2-4"; tag = "90Curve"},/obj/machinery/atmospherics/pipe/simple/supply/hidden,/obj/structure/disposalpipe/segment{dir = 4},/obj/machinery/door/firedoor/border_only,/obj/machinery/door/airlock/maintenance{name = "Assembly Line Maintenance"; req_access_txt = "12;29"},/turf/simulated/floor/plating,/area/assembly/assembly_line)
@@ -5414,7 +5414,7 @@
"caf" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 1},/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/turf/simulated/floor/plating/airless,/area/maintenance/portsolar)
"cag" = (/turf/simulated/wall/r_wall,/area/maintenance/portsolar)
"cah" = (/turf/simulated/wall,/area/maintenance/portsolar)
"cai" = (/obj/machinery/optable{id = "robotics"; name = "Robotics Operating Table"},/turf/simulated/floor,/area/assembly/assembly_line)
"cai" = (/obj/machinery/optable,/turf/simulated/floor,/area/assembly/assembly_line)
"caj" = (/obj/structure/table,/obj/item/device/mmi,/obj/item/device/mmi,/obj/item/device/mmi,/turf/simulated/floor,/area/assembly/assembly_line)
"cak" = (/obj/structure/cable{tag = "Streight"; icon_state = "4-8"; pixel_x = 1; d1 = 4; d2 = 8},/turf/simulated/floor/plating,/area/maintenance/aft)
"cal" = (/obj/structure/cable{d1 = 1; d2 = 8; icon_state = "1-8"; tag = "90Curve"},/obj/machinery/atmospherics/pipe/simple/supply/hidden{dir = 5},/turf/simulated/floor/plating,/area/maintenance/aft)
@@ -8775,16 +8775,16 @@ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabJebATbJfbATbJgaaaaaeaaaaaabwSbwSbFfbJhbJhbJhbJhbFgbJiaaaaaaaaabthbJjbJkbJlbJmbJnbJobJpbJqbJqbJrbJsbJtbJubJqbJvbJvbJwbJxbJybJzbyMbJAbIjbJBbIkbJCbJDbIjbIjbJEbIjbIrbIsbIjbJFbJGbJHbIjbJIbJJbIzbJKbJLbJMaaaaaaaaaaaaaaaaaeaaaaaaaaaaaabwjbJNbJObJPbJQbJQbJQbJRbJQbJSbpnbJTbJUbJVbJWbJXbJYbJZbEAbKabKabKbbKcbKdbKebKfbKgbKhbKibKjbKkbKlbKmbKnbKobKjbKpbKqbKrbKqbHDbKsbKtbdLbHGbKubKvbKwbKxbKwbKyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarYaaaaaaaaeaaaaaabDCbDCbKzbFabFabFabFabKAbFabFabFabFabFabFabDCbDCaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaaaaaaaaaaeaaeaaeaaeaaaaaaaaabthbthbJkbKBbKCbIbbthbthbthbthbKDbKEbIdbKEbKFbKGbKHbKIbKJbtGbKKbwjbKLbIjbIjbKMbIjbIjbIjbIjbKNbKObKPbKQbKRbKSbKTbKUbKVbKWbKXbKYbKZbIBaaebLabLabLabLabLaaaeaaeaaeaaeaaebwjbwdbLbbLcbLdbLebLfbLgbLhbLibLjbBNbBNbBNbLkbLlbLmbBNbBNbBNbEAbLnbLobLpbLqbLrbKgbsWbLsbHDbLtbLubLvbKrbLwbHDbLxbLybLzbLAbHDbLBbLCbLDbLEbLFbLGbLHbKvbKwbLIaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabDCbFabFabFabFabFabFabLJbFabLKbFabFabFabFabFabDCbDCaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaeaaaaaaaaaaaeaaeaaeaaaaaaaaaaaebthbJkbLLbLMbLNbLMbLMbLObthbLPbLQbLRbLQbLSbKGbLTbLUbLVbLWbLXbwjbLYbIjbIjbIkbLZbIjbIjbIjbIsbIjbIrbIjbKRbMabMbbMcbMdbJIbKWbMebMfbMgbMhbMibMjbMkbMkbLaaaeaaaaaaaaaaaebMlbwdbLbbLcbMmbMnbMobMobMpbMqbMrbBNbMsbMtbMubMvbFYbMwbMxbMybEAbMzbKgbMAbKgbMzbKgbsWbMBbMCbMDbMEbMFbMFbMFbMGbMFbISbMHbMIbHDbHDbMJbMKbHGbMLbHGbMMbMNbMObHGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabDCbMPbMQbMRbMRbMRbMRbMSbFabMTbMRbLKbFabFabFabFabDCaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeachaaaaaaaaaaaeaaeaaeaaeaaeaaeaaebthbMUbMVbthbIbbthbthbMWbMXbLMbLMbMYbuAbuAbKGbMZbLUbtxbtGbtxbNabIjbIjbNbbNcbNdbNebNfbNgbNhbIjbIrbIjbKRbKSbNibNjbIjbJIbNkbNlbNmbIBaaebNnbNobMkbNpbLaaaeaaaaaaaaaaaebNqbwdbNrbNsbNtbNubNvbNwbNxbNybNzbNAbNBbNCbNDbNEbNFbNFbNGbNHbEAbNIbNJbLpbNKbNLbKgbNMbNNbKjbNObNPbKrbNQbKrbNPbKrbKrbNRbNRbNSbHDbMJbMKbHGbNTbNUbNVbNVbNVbNWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabNXbEYbEYbEYbEYbEYbEYbEYbNYbFbbFabFabFabFabNZbFbbDCaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaeaaaaaaaaeaaeaaeaaeaaaaaaaaabOabJkbKBbObbOcbOdbthbthbthbthbthbthbOebthbKGbOfbOgbtxbtGbOhbOibOjbOkbOlbNcbOmbOnbOobOpbNhbIjbIrbIjbOqbOrbNibNjbOsbOtbOubOvbOwbOxbOybMibOzbMkbMkbLaaaeaaeaaeaaeaaebNqbwdbLbbOAbOBbOCbOCbMobODbxubOEbOFbOGbOHbOIbOJbFYbOKbOLbOMbEAbONbLpbOObLpbOPbKgbOQbORbHDbOSbOTbOUbOVbOWbOXbOYbOZbPabPbbPcbPdbPebMKbHGbHGbHGbHGbHGbHGbHGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaabDCbPfbPgbPhbJdbJdbJdbPibFabJcbJdbPjbFabFabFabFabDCaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaaaaeaaeaaeaaaaaeaaaaaaaaabPkbJkbPlbObbPmbPnbPobPnbPpbPnbPobPnbPqbObbKGbKGbPrbPsbPtbPubPvbPwbHdbHdbIkbHdbHdbHdbHdbPxbIjbIrbPybPzbPAbPBbNjbPCbPDbNkbIjbIjbPEaaebLabLabLabLabLaaaeaaaaaaaaaaaebNqbwdbLbbPFbPGbPHbPIbPJbPKbPLbvibPMbPNbPObPPbPQbFVbFVbFWbPRbEAbPSbNJbPTbNJbPUbKgbPVbPWbHDbPXbPYbPZbQabQbbQcbQdbQabQebQbbPXbHDbQfbMKbccaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaebDCbFabFabFabFabFabFabLJbFabPjbFabFabFabFabFabDCbDCaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeachaaaaaaaaaaaeaaeaaeaaeaaeaaeaaebthbMUbMVbthbIbbthbthbMWbMXbLMbLMbMYbuAbuAbKGbMZbLUbtxbtGbtxbNabIjbIjbNbbNcbNdbNebNfbNgbNhbIjbIrbIjbKRbKSbNibNjbIjbJIbNkbNlbNmbIBaaebNnbNobMkbNpbLaaaeaaaaaaaaaaaebNqbwdbNrbNsbNtbNubNvbNwbNxbNybNzbNAbNBbNCbNDbNEbNFbNGbNHbNIbEAbNJbNKbLpbNLbNMbKgbNNbNObKjbNPbNQbKrbNRbKrbNQbKrbKrbNSbNSbNTbHDbMJbMKbHGbNUbNVbNWbNWbNWbNXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabNYbEYbEYbEYbEYbEYbEYbEYbNZbFbbFabFabFabFabOabFbbDCaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaeaaaaaaaaeaaeaaeaaeaaaaaaaaabObbJkbKBbOcbOdbOebthbthbthbthbthbthbOfbthbKGbOgbOhbtxbtGbOibOjbOkbOlbOmbNcbOnbOobOpbOqbNhbIjbIrbIjbOrbOsbNibNjbOtbOubOvbOwbOxbOybOzbMibOAbMkbMkbLaaaeaaeaaeaaeaaebNqbwdbLbbOBbOCbODbODbMobOEbxubOFbOGbOHbOIbOJbOKbFYbFYbOLbOMbEAbONbLpbOObLpbOPbKgbOQbORbHDbOSbOTbOUbOVbOWbOXbOYbOZbPabPbbPcbPdbPebMKbHGbHGbHGbHGbHGbHGbHGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaabDCbPfbPgbPhbJdbJdbJdbPibFabJcbJdbPjbFabFabFabFabDCaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaaaaeaaeaaeaaaaaeaaaaaaaaabPkbJkbPlbOcbPmbPnbPobPnbPpbPnbPobPnbPqbOcbKGbKGbPrbPsbPtbPubPvbPwbHdbHdbIkbHdbHdbHdbHdbPxbIjbIrbPybPzbPAbPBbNjbPCbPDbNkbIjbIjbPEaaebLabLabLabLabLaaaeaaaaaaaaaaaebNqbwdbLbbPFbPGbPHbPIbPJbPKbPLbvibPMbPNbPObPPbPQbFVbFVbFWbPRbEAbPSbNKbPTbNKbPUbKgbPVbPWbHDbPXbPYbPZbQabQbbQcbQdbQabQebQbbPXbHDbQfbMKbccaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaebDCbFabFabFabFabFabFabLJbFabPjbFabFabFabFabFabDCbDCaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaeaaeaaeaaaaaabthbthbthbthbthbQgbQhbQibQjbQkbQlbQmbPqbQkbQlbQmbPqbQnbQobQpbQqbtxbtGbQrbQsbQtbQubQvbQwbQxbQybQzbQAbQBbQCbQDbQEbQFbQGbQHbQIbMdbJIbQJbKYbQKbQLbMhbMibQMbQNbQNbLaaaeaaaaaaaaaaaebNqbwdbLbbLcbQObQPbQQbQRbQSbxubQTbBNbQUbQVbQWbQXbFYbQYbQZbRabEAbRbbRbbRbbRbbKgbKgbPVbRcbHDbHDbHDbRdbRebRebRebRfbRebRebHDbHDbHDbMJbMKbccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaaaaaaaaaaeaaaaaaaaaaaeaaaaaabDCbDCbKzbFabFabFabFabRgbFabFabFabFabFabFabDCbDCaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaeaaeaaeaaeaaabOabRhbuAbRibRjbRkbRlbRmbRnbPqbPqbPqbPqbPqbPqbPqbPqbQnbQobtxbQqbtxbtGbRobRpbPwbIjbIjbRqbRrbKNbRsbRtbRubRvbRwbRwbRwbRwbRwbRxbIjbJIbNkbNlbRybRzaaebNnbRAbRBbRCbLaaaeaaeaaeaaeaaebFHbwdbLbbxhbJQbJQbJQbJQbJQbxubdsbBNbBNbBNbBNbBNbLmbRbbRbbRbbRbbRDbREbRFbRbbRGbRHbRIbRJbRKbRLbHDbRebRebRebRebRMbRebRebHDbRNbRObRPbMKbccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaebDCbDCbMTbMRbMRbFabFabFabFabFabFabFabFabDCbDCaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaeaaaaaaaaeaaabPkbuzbuAbRQbuAbJkbthbObbRRbPnbPnbPnbPqbPnbPnbPnbRSbObbObbObbRTbRUbtGbRVbRWbRXbRYbMebRZbSabSbbScbSdbSebNibSfbNbbNbbIjbSgbShbSibSjbSkbOvbSlbSmbSnbMibSobQNbQNbLaaaeaaaaaaaaaaaebwjbwdbLbbEebSpbSqbSrbSsbdsbxubdsbStbSubSvbSwbSxbFYbSybSzbSAbSBbSCbSDbSEbSFbSGbSHbSIbSJbSKbSLbHDbSMbSNbRebRebRebSNbSObHDbMJbMKbMKbMKbSPbccbccaaaaaeaaaaaaayoayoayoaaaaaaaaeaaaaaaaaeayoayoayoaaaaaaaaeaaaaaaaaeaaaaaaaaeaaaaaabDCbDCbGAbDCbDCbFabFabFabFabFabFabFabDCbDCaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaaaaaaaabSQbSQbSQbthbuAbSRbthbMUbthbOdbPqbQkbQlbSSbPqbQkbQlbQmbPqbPqbSTbPqbSUbtxbtGbSVbsqbsqbHdbSWbSXbSYbSZbTabHdbTbbNibTcbTdbIjbTebTfbTgbThbJIbNkbIjbTibRzaaebLabLabLabLabLaaaeaaaaaaaaaaaebwjbwdbLbbEebwjbdqbTjbqrbpnbTkbdsbTlbFYbFYbTmbFYbFYbTnbTobTpbTqbTrbTobTsbRbbTtbTtbTubTvbTtbTtbHDbRebRebRebTwbRebRebRebHDbTxbLDbLDbLDbTybTzbTybTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTBbTCbTDbTEbDCbDCbFabFabTFbFabFabDCbDCaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaaaaaaaaaaabSQbTGbTHbthbuAbRQbthbTIbTJbOdbPqbPqbTKbPqbTLbPqbTMbPqbPqbPqbTMbPqbSUbtxbtGbtxbxcbTNbsqbTObHdbLZbTPbTQbHdbTRbNibTcbTSbIjbIjbTTbTUbTVbJIbTWbKYbTXbQLbMhbMibTYbTZbUabLaaaeaaeaaeaaeaaebwjbwjbUbbUcbUdbjBbjBbjBbUebxubUfbStbUgbUhbUibUjbUhbSybUkbUlbRbbUmbTobUnbRbbUobUpbUpbUpbUpbUqbRbbHDbHDbHDbHDbHDbHDbHDbHDbQfbUrbUsbUtbccbccbccaaaaaeaaaaaaayoayoayoaaaaaaachaaaaaaaaeayoayoayoaaaaaaaaeaaaaaaaaeaaaaaaaaeaaeaaebUubUvbUwbUxbDCbDCbDCbFabFbbFabDCbDCaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaeaaeaaeaaeaaabObbRhbuAbRibRjbRkbRlbRmbRnbPqbPqbPqbPqbPqbPqbPqbPqbQnbQobtxbQqbtxbtGbRobRpbPwbIjbIjbRqbRrbKNbRsbRtbRubRvbRwbRwbRwbRwbRwbRxbIjbJIbNkbNlbRybRzaaebNnbRAbRBbRCbLaaaeaaeaaeaaeaaebFHbwdbLbbxhbJQbJQbJQbJQbJQbxubdsbBNbBNbBNbBNbBNbLmbRbbRbbRbbRbbRDbREbRFbRbbRGbRHbRIbRJbRKbRLbHDbRebRebRebRebRMbRebRebHDbRNbRObRPbMKbccaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaebDCbDCbMTbMRbMRbFabFabFabFabFabFabFabFabDCbDCaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaeaaaaaaaaeaaabPkbuzbuAbRQbuAbJkbthbOcbRRbPnbPnbPnbPqbPnbPnbPnbRSbOcbOcbOcbRTbRUbtGbRVbRWbRXbRYbMebRZbSabSbbScbSdbSebNibSfbNbbNbbIjbSgbShbSibSjbSkbOwbSlbSmbSnbMibSobQNbQNbLaaaeaaaaaaaaaaaebwjbwdbLbbEebSpbSqbSrbSsbdsbxubdsbStbSubSvbSwbSxbFYbSybSzbSAbSBbSCbSDbSEbSFbSGbSHbSIbSJbSKbSLbHDbSMbSNbRebRebRebSNbSObHDbMJbMKbMKbMKbSPbccbccaaaaaeaaaaaaayoayoayoaaaaaaaaeaaaaaaaaeayoayoayoaaaaaaaaeaaaaaaaaeaaaaaaaaeaaaaaabDCbDCbGAbDCbDCbFabFabFabFabFabFabFabDCbDCaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaarYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaaaaaaaabSQbSQbSQbthbuAbSRbthbMUbthbOebPqbQkbQlbSSbPqbQkbQlbQmbPqbPqbSTbPqbSUbtxbtGbSVbsqbsqbHdbSWbSXbSYbSZbTabHdbTbbNibTcbTdbIjbTebTfbTgbThbJIbNkbIjbTibRzaaebLabLabLabLabLaaaeaaaaaaaaaaaebwjbwdbLbbEebwjbdqbTjbqrbpnbTkbdsbTlbFYbFYbTmbFYbFYbTnbTobTpbTqbTrbTobTsbRbbTtbTtbTubTvbTtbTtbHDbRebRebRebTwbRebRebRebHDbTxbLDbLDbLDbTybTzbTybTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTAbTBbTCbTDbTEbDCbDCbFabFabTFbFabFabDCbDCaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaaaaaaaaaaabSQbTGbTHbthbuAbRQbthbTIbTJbOebPqbPqbTKbPqbTLbPqbTMbPqbPqbPqbTMbPqbSUbtxbtGbtxbxcbTNbsqbTObHdbLZbTPbTQbHdbTRbNibTcbTSbIjbIjbTTbTUbTVbJIbTWbKYbTXbQLbMhbMibTYbTZbUabLaaaeaaeaaeaaeaaebwjbwjbUbbUcbUdbjBbjBbjBbUebxubUfbStbUgbUhbUibUjbUhbSybUkbUlbRbbUmbTobUnbRbbUobUpbUpbUpbUpbUqbRbbHDbHDbHDbHDbHDbHDbHDbHDbQfbUrbUsbUtbccbccbccaaaaaeaaaaaaayoayoayoaaaaaaachaaaaaaaaeayoayoayoaaaaaaaaeaaaaaaaaeaaaaaaaaeaaeaaebUubUvbUwbUxbDCbDCbDCbFabFbbFabDCbDCaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaaaaaaaaaaaaaabSQbTGbUybUzbLMbUAbthbUBbUBbUCbUCbUCbUCbUCbUCbUCbUCbUDbUDbUCbUCbUCbUEbUFbUGbtxbUHbtxbtxbUIbUJbIjbTPbIjbUJbNjbNibUKbPzbNbbIjbIjbIjbIxbULbNkbNlbUMbRzaaebNnbUNbUObUPbLaaaeaaaaaaaaaaaeaaebwjbUQbURbUSbUTbUUbgLbgLbUVbUWbBNbBNbBNbBNbBNbBNbRbbRbbUXbUYbUZbVabVbbUpbVcbVdbVebVfbVebVgbRbbVhbVibVjbVkbVkbVkbVkbVkbRPbVlaaaaaaaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaeaaebVmbDAbDAbDBbDCbDCbDCbDCbDCbDCbDCaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaagaagaadaadaagaadaadaadajIaadaadaadaagaagaaaaaaaaeaaeaaaaaaaaaaaaaaaaaabSQbTGbVnbUCbUCbVobUCbVpbVqbUCbVrbVsbVtbUCbVubVvbVwbVxbVxbVybVzbVAbVBbtxbtGbVCbLVbVDbVEbVFbVGbHdbSXbVHbHdbVIbNibVJbVKbNbbIjbIjbIxbVLbVMbSkbOvbVNbSmbSnbMibVObTZbTZbLaaaeaaaaaaaaaaaaaaebwjbwjbwjbwjbwjbCObCPbCPbVPbAcbAcbAcbAcbAcbVQbAcbAcbAcbVRbVSbVTbTobVUbVVbVWbTobVXbVWbVYbTobRbbpEbVZbUrbWabccbccbccbccbccbccaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaagaagaadaadaagaadaadaadajIaadaadaadaagaagaaaaaaaaeaaeaaaaaaaaaaaaaaaaaabSQbTGbVnbUCbUCbVobUCbVpbVqbUCbVrbVsbVtbUCbVubVvbVwbVxbVxbVybVzbVAbVBbtxbtGbVCbLVbVDbVEbVFbVGbHdbSXbVHbHdbVIbNibVJbVKbNbbIjbIjbIxbVLbVMbSkbOwbVNbSmbSnbMibVObTZbTZbLaaaeaaaaaaaaaaaaaaebwjbwjbwjbwjbwjbCObCPbCPbVPbAcbAcbAcbAcbAcbVQbAcbAcbAcbVRbVSbVTbTobVUbVVbVWbTobVXbVWbVYbTobRbbpEbVZbUrbWabccbccbccbccbccbccaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaeaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaaaaaaaeaaeaaaaaeaaeaaaaaaaaeaaeaaeaaaaagaaaaaeaaeaaaaaaaaaaaaaaaaaaaaabSQbTGbVnbWbbWcbVxbWdbWebVxbWfbWgbWhbVxbWibVxbWhbVxbVxbVxbWjbWkbtxbWlbWmbtGbWnbWobsqbsqbsqbsqbWpbWqbWrbHdbWsbNibIxbWtbIybWubIybWvbWwbKWbWxbIjbIjbRzaaebLabLabLabLabLaaaeaaaaaaaaaaaaaaaaaeaaeaaaaaebwjbwjbwjbwdbwdbwdbWybWzbWzbWzbWAbWzbWzbWzbpEbVSbWBbTobWCbWDbVWbWEbWFbWGbWHbWIbRbbpEbVZbrYaaaaaaaaaaaaaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaabWJbWKbWLaaabWJbWKbWLaaabWJbWKbWLaaebWMaaeaaeaaaaaaaaaaaaaaaaaaaaaaaabSQbTGbVnbWNbWObVxbWgbWebVxbWPbWQbWQbWQbWQbWQbWQbWRbWQbWSbWjbWTbtxbQqbtxbtGbWUbWVbWWbWXbWYbWZbXabXbbXcbHdbXdbXebXfbXgbXgbXfbXgbXhbXibJIbXjbKYbXkbQLbMhbMibXlbXmbXmbLaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaeaaebwjbXnbXobFCbFBbWzbXpbXqbXrbXsbXtbWzbpEbVSbXubXvbXwbXxbXybXzbXAbXBbXCbXDbRbbpEbXEbrYaaaaaaaaeaaeaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaagaaabWJbXFbWLaaabWJbXFbWLaaabWJbXFbWLaaeaaeaaeaaeaaaaaaaaaaaaaaaaaaaaaaaabSQbTGbVnbUCbUCbXGbVxbWebXHbXIbXIbXJbXKbVxbVxbXLbVxbVxbXMbXNbXObtxbXPbtxbtGbVCbsrbXQbXRbXSbXTbXUbXVbXWbHdbNjbIjbKWbXgbXgbXXbXYbXZbXebYabYbbYcbYdbRzaaebNnbYebYfbYgbLaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaebWzbWzbWzbWzbWzbWzbYhbYhbXrbYhbYibWzbqIbYjbYkbTobXwbTobYlbTobTobTobTobYmbRbbpEbVZbrYaaaaaaaaaaaeaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa