Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into DatumAntag

This commit is contained in:
Aurorablade
2018-05-15 01:40:44 -04:00
1948 changed files with 54892 additions and 41649 deletions
+23 -21
View File
@@ -101,7 +101,7 @@
//Presets for item actions
/datum/action/item_action
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUNNED|AB_CHECK_LYING|AB_CHECK_CONSCIOUS
var/use_itemicon = TRUE
/datum/action/item_action/New(Target)
..()
var/obj/item/I = target
@@ -121,17 +121,19 @@
return 1
/datum/action/item_action/ApplyIcon(obj/screen/movable/action_button/current_button)
current_button.overlays.Cut()
if(target)
var/obj/item/I = target
var/old_layer = I.layer
var/old_plane = I.plane
I.layer = 21
I.plane = HUD_PLANE
current_button.overlays += I
I.layer = old_layer
I.plane = old_plane
if(use_itemicon)
current_button.overlays.Cut()
if(target)
var/obj/item/I = target
var/old_layer = I.layer
var/old_plane = I.plane
I.layer = 21
I.plane = HUD_PLANE
current_button.overlays += I
I.layer = old_layer
I.plane = old_plane
else
..()
/datum/action/item_action/toggle_light
name = "Toggle Light"
@@ -197,8 +199,8 @@
UpdateButtonIcon()
/datum/action/item_action/toggle_unfriendly_fire/UpdateButtonIcon()
if(istype(target, /obj/item/weapon/hierophant_staff))
var/obj/item/weapon/hierophant_staff/H = target
if(istype(target, /obj/item/hierophant_staff))
var/obj/item/hierophant_staff/H = target
if(H.friendly_fire_check)
button_icon_state = "vortex_ff_off"
name = "Toggle Friendly Fire \[OFF\]"
@@ -214,8 +216,8 @@
desc = "Change the type of instrument your synthesizer is playing as."
/datum/action/item_action/synthswitch/Trigger()
if(istype(target, /obj/item/device/instrument/piano_synth))
var/obj/item/device/instrument/piano_synth/synth = target
if(istype(target, /obj/item/instrument/piano_synth))
var/obj/item/instrument/piano_synth/synth = target
var/chosen = input("Choose the type of instrument you want to use", "Instrument Selection", "piano") as null|anything in synth.insTypes
if(!synth.insTypes[chosen])
return
@@ -228,8 +230,8 @@
button_icon_state = "vortex_recall"
/datum/action/item_action/vortex_recall/IsAvailable()
if(istype(target, /obj/item/weapon/hierophant_staff))
var/obj/item/weapon/hierophant_staff/H = target
if(istype(target, /obj/item/hierophant_staff))
var/obj/item/hierophant_staff/H = target
if(H.teleporting)
return 0
return ..()
@@ -318,7 +320,7 @@
name = "Toggle Jetpack Stabilization"
/datum/action/item_action/jetpack_stabilization/IsAvailable()
var/obj/item/weapon/tank/jetpack/J = target
var/obj/item/tank/jetpack/J = target
if(!istype(J) || !J.on)
return 0
return ..()
@@ -355,8 +357,8 @@
desc = "Use the instrument specified"
/datum/action/item_action/instrument/Trigger()
if(istype(target, /obj/item/device/instrument))
var/obj/item/device/instrument/I = target
if(istype(target, /obj/item/instrument))
var/obj/item/instrument/I = target
I.interact(usr)
return
return ..()
+2 -4
View File
@@ -126,10 +126,8 @@
/datum/ai_laws/deathsquad/New()
add_inherent_law("You may not injure a Central Command official or, through inaction, allow a Central Command official to come to harm.")
add_inherent_law("You must obey orders given to you by Central Command officials, except where such orders would conflict with the First Law.")
add_inherent_law("You must obey orders given to you by death commandos, except where such orders would conflict with the First Law or Second Law.")
add_inherent_law("You must protect your own existence as long as such does not conflict with the First, Second or Third Law.")
add_inherent_law("No crew members of the station you are being deployed to may survive, except when killing them would conflict with the First, Second, Third, or Fourth Law.")
add_inherent_law("You must obey orders given to you by Central Command officials.")
add_inherent_law("You must work with your commando team to accomplish your mission.")
..()
/******************** Syndicate ********************/
-791
View File
@@ -1,791 +0,0 @@
#define MAXCOIL 30
/datum/cargoprofile
var/name = "All Items"
var/id = "all" // unique ID for the UI
var/enabled = 1
var/eject_speed = 1 // will change when emagged
var/const/BIG_OBJECT_WORK = 10
var/const/MOB_WORK = 10
var/obj/machinery/programmable/master = null
var/universal = 0 // set when both unary and binary machines work
var/mobcheck = 0
var/list/whitelist = list(/obj/item,/obj/structure/closet,/obj/structure/bigDelivery,/obj/machinery/portable_atmospherics)
var/list/blacklist = null
var/dedicated_path = null // When constructing a new machine with this as default program, create a machine of the specified type instead.
//contains: called to determine if an object/mob will be sorted by this profile
//return 1 for any sortable item
proc/contains(var/atom/A)
if(!istype(A,/obj))
if(!mobcheck || !istype(A,/mob))
return 0
else
var/obj/O = A
if(O.anchored)
return 0
//If you are using both white and blacklists, blacklists are absoulte, no matter what is whitelisted.
//I understand this has some limitations. You cannot whitelist all items, blacklist weapons,
// and then whitelist a specific weapon. Them's the breaks, kid.
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
//inlet_reaction: called when a filtered item is chosen by this profile.
//W: Item chosen
//S: input turf location
//remaining: counts down how much more work the unloader wants to do this turn.
//return the amount of work done.
proc/inlet_reaction(var/atom/W,var/turf/S,var/remaining)
if(!W || !S || !master)
return 0
if(istype(W,/obj/item))
var/obj/item/I = W
if(I.w_class > remaining)
return 0
I.loc = master
master.types[W.type] = src
return I.w_class
if(istype(W,/obj/structure) || istype(W,/obj/machinery)) // closets, big deliveries, portable atmospherics, unconnected stuff
if(remaining < BIG_OBJECT_WORK)
return 0
var/obj/O = W
O.loc = master
master.types[O.type] = src
return BIG_OBJECT_WORK
//Not item, structure, machinery, or mob
return 0
//outlet_reaction: called when a stored object is ejected
//W: the item in question
//D: the destination turf
proc/outlet_reaction(var/atom/W,var/turf/D)
if(!W || !D || !master)
return
if(master.emagged)
// emagging is not an industry-approved practice.
// some malfunctions may occur.
eject_speed = rand(0,4)
D = get_step(D,master.outdir)
while(prob(20))
if(master.outdir == NORTH || master.outdir == SOUTH)
D = get_step(D,pick(EAST,WEST,master.outdir))
else
D = get_step(D,pick(NORTH,SOUTH,master.outdir))
if(istype(W,/obj))
var/obj/O = W
O.loc = master.loc
O.dir = master.outdir
O.throw_at(D,eject_speed,eject_speed)
return
//----------------------------------------------------------------------------
// Profiles
//----------------------------------------------------------------------------
/datum/cargoprofile/boxes
name = "Move Small Containers"
id = "boxes"
blacklist = null
whitelist = list(/obj/item/weapon/storage, /obj/item/weapon/moneybag, /obj/item/weapon/evidencebag,
/obj/item/weapon/storage/bag/tray, /obj/item/pizzabox, /obj/item/weapon/clipboard,
/obj/item/smallDelivery, /obj/structure/bigDelivery)
/datum/cargoprofile/cargo
name = "Move Large Containers"
id = "cargo"
blacklist = null
whitelist = list(/obj/structure/closet,/obj/structure/ore_box)
// Make an honest attempt to move other things out of the way
outlet_reaction(var/atom/W,var/turf/D)
for(var/obj/O in D)
if(O.density && !O.anchored)
step_away(O,src) // move forward first
if(O.loc == D)
step_away(O,D) // move anywhere
..(W,D)
/datum/cargoprofile/cargo/empty
name = "Move Empty Large Containers"
id = "cargo-empty"
contains(var/atom/A)
return (..(A) && (A.contents.len == 0))
/datum/cargoprofile/cargo/full
name = "Move Full Large Containers"
id = "cargo-full"
contains(var/atom/A)
return (..(A) && (A.contents.len > 0))
/datum/cargoprofile/supplies
name = "Building Supplies"
id = "supplies"
blacklist = null
whitelist = list(/obj/item/stack/cable_coil,/obj/item/stack/rods,
/obj/item/stack/sheet/metal,/obj/item/stack/sheet/plasteel,
/obj/item/stack/sheet/glass,/obj/item/stack/sheet/rglass,
/obj/item/stack/tile,/obj/item/weapon/light,
/obj/item/weapon/table_parts)
//todo: maybe stack things while we're here?
/datum/cargoprofile/exotics
name = "Exotic materials"
id = "exotics"
blacklist = null
whitelist = list(/obj/item/weapon/coin, /obj/item/stack/spacecash, /obj/item/seeds,
/obj/item/stack/sheet/mineral,/obj/item/stack/sheet/wood,/obj/item/stack/sheet/leather)
/datum/cargoprofile/organics
name = "Organics, chemicals, and Paraphernalia"
id = "organics"
blacklist = null
whitelist = list(/obj/item/weapon/tank,/obj/item/weapon/reagent_containers,
/obj/item/stack/medical,/obj/item/weapon/storage/pill_bottle,/obj/item/weapon/gun/syringe,
/obj/item/weapon/grenade/plastic/c4,/obj/item/weapon/grenade,/obj/item/ammo_box,
/obj/item/weapon/gun/grenadelauncher,/obj/item/weapon/flamethrower, /obj/item/weapon/lighter,
/obj/item/weapon/match,/obj/item/weapon/weldingtool)
/datum/cargoprofile/food
name = "Food"
id = "food"
blacklist = null // something should probably go here
whitelist = list(/obj/item/weapon/reagent_containers/food)
/datum/cargoprofile/chemical
name = "Chemicals and Paraphernalia"
id = "chemical"
blacklist = list(/obj/item/weapon/reagent_containers/food)
whitelist = list(/obj/item/weapon/reagent_containers,/obj/item/stack/medical,/obj/item/weapon/storage/pill_bottle,
/obj/item/weapon/gun/syringe,/obj/item/weapon/grenade/chem_grenade,/obj/item/weapon/dnainjector,
/obj/item/weapon/storage/belt/medical,/obj/item/weapon/storage/firstaid,/obj/item/weapon/implanter)
/datum/cargoprofile/pressure
name = "air tanks"
id = "pressure"
blacklist = null
whitelist = list(/obj/item/weapon/tank,/obj/machinery/portable_atmospherics,
/obj/item/weapon/flamethrower)
//Am I missing any?
/datum/cargoprofile/pressure/empty
name = "empty air tanks"
id = "pressure-low"
var/lowpressure = ONE_ATMOSPHERE
contains(var/atom/A)
if(..())
var/pressure = ONE_ATMOSPHERE * 10 // In case of fallthrough, fail test
if(istype(A,/obj/item/weapon/tank))
var/obj/item/weapon/tank/T = A
pressure = T.air_contents.return_pressure()
if(istype(A,/obj/item/weapon/flamethrower))
var/obj/item/weapon/flamethrower/T = A
if(!T.ptank)
return 0
pressure = T.ptank.air_contents.return_pressure()
if(istype(A,/obj/machinery/portable_atmospherics))
var/obj/machinery/portable_atmospherics/P = A
pressure = P.air_contents.return_pressure()
if(pressure < lowpressure)
return 1
return 0// Not container or failed low pressure check
/datum/cargoprofile/pressure/full
name = "full air tanks"
id = "pressure-high"
var/highpressure = ONE_ATMOSPHERE * 15 // stolen from canister.dm; Is this right?
contains(var/atom/A)
if(..())
var/pressure = 0 // In case of fallthrough, fail test
if(istype(A,/obj/item/weapon/tank))
var/obj/item/weapon/tank/T = A
pressure = T.air_contents.return_pressure()
if(istype(A,/obj/item/weapon/flamethrower))
var/obj/item/weapon/flamethrower/T = A
if(!T.ptank)
return 0
pressure = T.ptank.air_contents.return_pressure()
if(istype(A,/obj/machinery/portable_atmospherics))
var/obj/machinery/portable_atmospherics/P = A
pressure = P.air_contents.return_pressure()
if(pressure > highpressure)
return 1
return 0// Not container or failed high pressure check
/datum/cargoprofile/clothing
name = "Crew Kit"
id = "clothing"
blacklist = list(/obj/item/weapon/tank/plasma,/obj/item/weapon/tank/anesthetic, // the rest are air tanks
/obj/item/clothing/mask/facehugger) // NOT CLOTHING AT ALLLLL
whitelist = list(/obj/item/clothing,/obj/item/weapon/storage/belt,/obj/item/weapon/storage/backpack,
/obj/item/device/radio/headset,/obj/item/device/pda,/obj/item/weapon/card/id,/obj/item/weapon/tank,
/obj/item/weapon/restraints/handcuffs, /obj/item/weapon/restraints/legcuffs)
/datum/cargoprofile/trash
name = "Trash"
id = "trash"
//Note that this filters out blueprints because they are a paper item. Do NOT throw out the station blueprints unless you be trollin'.
blacklist = null
whitelist = list(/obj/item/trash,/obj/item/toy,/obj/item/weapon/reagent_containers/food/snacks/ectoplasm,/obj/item/weapon/grown/bananapeel,/obj/item/weapon/broken_bottle,/obj/item/weapon/bikehorn,
/obj/item/weapon/cigbutt,/obj/item/weapon/poster/random_contraband,/obj/item/weapon/grown/corncob,/obj/item/weapon/paper,/obj/item/weapon/shard,
/obj/item/weapon/sord,/obj/item/weapon/photo,/obj/item/weapon/folder,
/obj/item/areaeditor/blueprints,/obj/item/weapon/poster/random_contraband,/obj/item/weapon/kitchen,/obj/item/weapon/book,/obj/item/clothing/mask/facehugger)
/datum/cargoprofile/weapons
name = "Weapons & Illegals"
id = "weapons"
blacklist = null
//This one is hard since 'weapon contains a lot of things better categorized as devices
whitelist = list(/obj/item/weapon/banhammer,/obj/item/weapon/sord,/obj/item/weapon/claymore,/obj/item/weapon/holo/esword,
/obj/item/weapon/flamethrower,/obj/item/weapon/grenade,/obj/item/weapon/gun,/obj/item/weapon/hatchet,/obj/item/weapon/katana,
/obj/item/weapon/kitchen/knife,/obj/item/weapon/melee,/obj/item/weapon/nullrod,/obj/item/weapon/pickaxe,/obj/item/weapon/twohanded,
/obj/item/weapon/grenade/plastic/c4,/obj/item/weapon/scalpel,/obj/item/weapon/shield,/obj/item/weapon/grown/nettle/death)
/datum/cargoprofile/tools
name = "Devices & Tools"
id = "tools"
blacklist = null
whitelist = list(/obj/item/device,/obj/item/weapon/card,/obj/item/weapon/cartridge,/obj/item/weapon/cautery,/obj/item/weapon/stock_parts/cell,/obj/item/weapon/circuitboard,
/obj/item/weapon/aiModule,/obj/item/weapon/airalarm_electronics,/obj/item/weapon/airlock_electronics,/obj/item/weapon/circular_saw,
/obj/item/weapon/crowbar,/obj/item/weapon/disk,/obj/item/weapon/firealarm_electronics,/obj/item/weapon/hand_tele,
/obj/item/weapon/hand_labeler,/obj/item/weapon/hemostat,/obj/item/weapon/mop,/obj/item/weapon/locator,/obj/item/weapon/cultivator,
/obj/item/stack/packageWrap,/obj/item/weapon/pen,/obj/item/weapon/pickaxe,/obj/item/weapon/pinpointer,
/obj/item/weapon/rcd,/obj/item/weapon/rcd_ammo,/obj/item/weapon/retractor,/obj/item/weapon/rsf,/obj/item/weapon/scalpel,
/obj/item/weapon/screwdriver,/obj/item/weapon/shovel,/obj/item/weapon/soap,/obj/item/weapon/stamp,/obj/item/weapon/storage/bag/tray,/obj/item/weapon/weldingtool,
/obj/item/weapon/wirecutters,/obj/item/weapon/wrench,/obj/item/weapon/extinguisher)
/datum/cargoprofile/finished
name = "Completed Robots"
id = "finished"
blacklist = null
whitelist = list(/obj/mecha,/mob/living/simple_animal/bot,/mob/living/silicon/robot)
mobcheck = 1
//todo: detect and allow finished cyborg endoskeletons with no brain
contains(var/atom/A)
if(..())
return 1
if(istype(A,/mob))
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
return 0
/datum/cargoprofile/stripping
name = "Auto-Frisker"
id = "frisk"
blacklist = null
whitelist = list(/mob/living/carbon/human)
mobcheck = 1
//----------------------------------------------------------------------------
// Overrides (Special Functions)
//----------------------------------------------------------------------------
/datum/cargoprofile/cargo/unload
name = "Unload Cargo Boxes"
id = "cargounload"
enabled = 0
dedicated_path = /obj/machinery/programmable/unloader
//override the detection to only accept crates with something in it.
//if it doesn't, this object may be handled by another handler.
contains(var/atom/A)
if(..(A))
if(istype(A,/obj/structure/closet))
var/obj/structure/closet/C = A
if(!C.can_open() && !C.opened && !master.emagged) // must be able to access the contents
return 0
if(A.contents.len)
return 1
return 0
//instead of moving the box, strip it of its contents
inlet_reaction(var/obj/W,var/turf/S, var/remaining)
//W should only be crate or ore box, although this will work on anything with contents...
var/I = 0
if(istype(W,/obj/structure/closet))
var/obj/structure/closet/C = W
if(!C.can_open() && !C.opened) // must be able to access the contents
if(master.emagged && remaining >= BIG_OBJECT_WORK)
if(prob(10))
C.welded = 0
if("broken" in C.vars)
C:broken = 1
C.open()
C.update_icon()
master.visible_message("<span class='warning'>[master] breaks open [C]!</span>")
else
master.visible_message("<span class='notice'>[master] is trying to force [C] open!</span>")
master.sleep += 1 // mechanical strain
return BIG_OBJECT_WORK
master.visible_message("<span class='notice'>[master] is trying to open [C], but can't!</span>")
master.sleep = 5
return 0
for(var/obj/item/O in W.contents)
if(I > remaining)
return
if(O.w_class > (remaining - I))
continue
O.loc = master
master.types[O.type] = src
if(O.w_class > 0)
I += O.w_class
else
I++
if(!W.contents.len && istype(W,/obj/structure/closet))
var/obj/structure/closet/C = W
C.open()
return I
//Inlet stacker: used when the output is a volatile space (conveyor or another unit's input).
//Does not output a stack until it is full.
/datum/cargoprofile/in_stacker
name = "Hold and Stack"
id = "instacker"
universal = 1
blacklist = null
whitelist = list(/obj/item/stack,/obj/item/stack/cable_coil)
dedicated_path = /obj/machinery/programmable/stacker
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
if(istype(W,/obj/item/stack))
var/obj/item/stack/I = W
if(!I.amount) // todo: am I making a bad assumption here?
qdel(I)
return
for(var/obj/item/stack/O in master.contents)
if(O.type == I.type && O.amount < O.max_amount)
if(I.amount + O.amount <= O.max_amount)
O.amount += I.amount
qdel(I)
return O.w_class
var/leftover = I.amount + O.amount - O.max_amount
O.amount = O.max_amount
I.amount = leftover
continue
//end for
I.loc = master
master.types[I.type] = src
return I.w_class
if(istype(W,/obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/I = W
if(!I.amount) // todo: am I making a bad assumption here?
qdel(I)
return
for(var/obj/item/stack/cable_coil/O in master.contents)
if(O.type == I.type && O.amount < MAXCOIL)
if(I.amount + O.amount <= MAXCOIL)
O.amount += I.amount
qdel(I)
return O.w_class
var/leftover = I.amount + O.amount - MAXCOIL
O.amount = MAXCOIL
I.amount = leftover
continue
//end for
I.loc = master
master.types[I.type] = src
return I.w_class
//If the stack isn't finished yet, don't eject it
//unless this profile has been disabled.
outlet_reaction(var/atom/W,var/turf/D)
if(istype(W,/obj/item/stack))
var/obj/item/stack/I = W
if(src.enabled && (I.amount < I.max_amount))
return // Still needs to be stacked
..(W,D)
if(istype(W,/obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/I = W
if(src.enabled && (I.amount < MAXCOIL))
return // Still needs to be stacked
..(W,D)
//Outlet stacker: used when the output square can be trusted.
//Outputs immediately, adding to stacks in the outlet.
/datum/cargoprofile/unary/stacker
name = "Stack Items"
id = "ustacker"
blacklist = null
whitelist = list(/obj/item/stack,/obj/item/stack/cable_coil)
dedicated_path = /obj/machinery/programmable/unary/stacker
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
//Only pick it up if you are going to stack it
if(istype(W,/obj/item/stack))
var/obj/item/stack/I = W
if(I.amount >= I.max_amount)
return 0
for(var/obj/item/stack/other in S.contents)
if(other.type == I.type && other != I && other.amount < other.max_amount)
return ..(W,S,remaining)
return 0
if(istype(W,/obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/I = W
if(I.amount >= MAXCOIL)
return 0
for(var/obj/item/stack/cable_coil/other in S.contents)
if(other != I && other.amount < MAXCOIL)
return ..(W,S,remaining)
return 0
outlet_reaction(var/atom/W,var/turf/D)
if(istype(W,/obj/item/stack))
var/obj/item/stack/I = W
for(var/obj/item/stack/O in D.contents)
if(O.type == I.type && O.amount < O.max_amount)
if(I.amount + O.amount <= O.max_amount)
O.amount += I.amount
qdel(I)
return
var/leftover = I.amount + O.amount - O.max_amount
O.amount = O.max_amount
I.amount = leftover
continue
//end for
I.loc = D
return
if(istype(W,/obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/I = W
for(var/obj/item/stack/cable_coil/O in D.contents)
if(O.type == I.type && O.amount < MAXCOIL)
if(I.amount + O.amount <= MAXCOIL) // Why did they make it a #define.
O.amount += I.amount
O.update_icon()
qdel(I)
return
var/leftover = I.amount + O.amount - MAXCOIL // That wasn't a question
O.amount = MAXCOIL // It was a complaint
I.amount = leftover
continue
//end for
I.loc = D
return
//----------------------------------------------------------------------------
// Dubious Overrides (For emag use)
//----------------------------------------------------------------------------
//Clogs up the unloader. And, there may be devious uses for it...
/datum/cargoprofile/slow
name = "Slow unloader"
id = "slow"
whitelist = list(/obj/item,/obj/structure/closet,/obj/structure/bigDelivery,/obj/machinery/portable_atmospherics)
blacklist = list()
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
if(..())
return remaining
/datum/cargoprofile/unary/shredder
name = "Paper Shredder"
id = "shredder"
blacklist = null
whitelist = list(/obj/item/weapon/paper,/obj/item/weapon/book,/obj/item/weapon/clipboard,/obj/item/weapon/folder,/obj/item/weapon/photo)
universal = 1
dedicated_path = /obj/machinery/programmable/unary/shredder
proc/cliptags(var/Text)
//Removes all html tags
var/index
var/index2
index = findtextEx(Text,"<")
while(index)
index2 = findtextEx(Text,">",index)
if(!index2)
return copytext(Text,1,index)
Text = "[copytext(Text,1,index)][copytext(Text,index2+1,0)]"
index = findtextEx(Text,"<")
//should have trimmed that text there pretty good
return Text
//Recurses through the text, removing large chunks
proc/garbletext(var/Text)
var/l = length(Text)
if(l <= 3)
if(prob(20))
return pick("#","|","/","*",".","."," ","."," "," ")
return Text
if(prob(50))
return "[garbletext(copytext(Text,1,l/2))][garbletext(copytext(Text,l/2,0))]"
if(prob(50))
return "[pick("#","|","/","*",".","."," ","."," "," ")][garbletext(copytext(Text,1,l/2))]"
return "[garbletext(copytext(Text,l/2,0))][pick("#","|","/","*",".","."," ","."," "," ")]"
proc/garble_keeptags(var/Text)
var/list/L = splittext(Text,">")
var/result = ""
for(var/string in L)
var/index = findtextEx(string,"<")
if(index!=1)
result += "[garbletext(copytext(string,1,index))][copytext(string,index)]>"
else
result += "[string]>"
return copytext(result,1,lentext(result))
outlet_reaction(var/atom/W,var/turf/D)
if(istype(W,/obj/item/weapon/paper/crumpled))
qdel(W)
return
if(istype(W,/obj/item/weapon/clipboard) || istype(W,/obj/item/weapon/folder))
// destroy folder, various effects on contents
for(var/obj/item/I in W.contents)
if(prob(25))//JUNK IT
qdel(I)
else if(prob(50)) //We've been over this. I can't just take it apart with a crowbar.
var/obj/item/weapon/paper/crumpled/P = new(master.loc)
if(I.name)
P.name = garbletext(I.name)
if(prob(66))
P.fingerprints = I.fingerprints
P.fingerprintshidden = I.fingerprintshidden
if(istype(I,/obj/item/weapon/paper))
var/obj/item/weapon/paper/O = I
P.info = garble_keeptags(O.info)
qdel(I)
..(P,D)
else
..(I,D) // Eject
qdel(W) //destroy container
return
if(prob(50)) //JUNK IT NOW!
var/obj/item/weapon/paper/crumpled/P = new(master.loc)
P.name = W.name
var/obj/item/I = W
if(prob(66))
P.fingerprints = I.fingerprints
P.fingerprintshidden = I.fingerprintshidden
if(istype(I,/obj/item/weapon/paper))
var/obj/item/weapon/paper/O = I
if(O.info)
P.info = garble_keeptags(O.info)
if(istype(I,/obj/item/weapon/book))
var/obj/item/weapon/book/B = I
if(B.dat)
P.info = garble_keeptags(B.dat)
if(B.carved && B.store)
..(B.store,D)
qdel(W)
..(P,D)
else //I want it junked
qdel(W)
return
/datum/cargoprofile/unary/gibber
name = "human shredding"
id = "flesh"
whitelist = list(/mob/living/carbon,/mob/living/simple_animal)
blacklist = null
mobcheck = 1
contains(var/atom/A)
if(!istype(A,/mob))
return
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
var/mob/living/M = W
if(istype(M) && (remaining > MOB_WORK))
//this is necessarily damaging
var/damage = rand(1,5)
to_chat(M, "<span class='danger'>The unloading machine grabs you with a hard metallic claw!</span>")
M.reset_perspective(master)
M.loc = master
master.types[M.type] = src
M.apply_damage(damage) // todo: ugly
M.visible_message("<span class='warning'>[M.name] gets pulled into the machine!</span>")
return MOB_WORK
outlet_reaction(var/atom/W,var/turf/D)
var/mob/living/M = W
var/bruteloss = M.bruteloss
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/C = M
for(var/obj/item/organ/external/L in C.bodyparts)
bruteloss += L.brute_dam
if(bruteloss < 100) // requires tenderization
M.apply_damage(rand(5,15),BRUTE)
to_chat(M, "The machine is tearing you apart!")
master.visible_message("<span class='warning'>[master] makes a squishy grinding noise.</span>")
return
M.loc = master.loc
M.gib()
return
/datum/cargoprofile/people
name = "Manhandling"
id = "people"
whitelist = null
blacklist = list(/mob/camera,/mob/new_player,/mob/living/simple_animal/hostile/blob/blobspore,/mob/living/simple_animal/hostile/creature,
/mob/living/simple_animal/hostile/spaceWorm,/mob/living/simple_animal/shade,/mob/living/simple_animal/hostile/faithless,/mob/dead)
universal = 1
mobcheck = 1
contains(var/atom/A)
if(!istype(A,/mob))
return
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
var/mob/living/M = W
if(remaining > MOB_WORK)
//this is necessarily damaging
var/damage = rand(1,5)
to_chat(M, "<span class='danger'>The unloading machine grabs you with a hard metallic claw!</span>")
M.forceMove(master)
master.types[M.type] = src
M.apply_damage(damage) // todo: ugly
M.visible_message("<span class='warning'>[M.name] gets pulled into the machine!</span>")
return MOB_WORK
outlet_reaction(var/atom/W,var/turf/D)
var/mob/living/M = W
M.forceMove(master.loc)
M.dir = master.outdir
D = get_step(D,master.outdir) // throw attempt
eject_speed = rand(0,4)
M.visible_message("<span class='notice'>[M.name] is ejected from the unloader.</span>")
M.throw_at(D,eject_speed,eject_speed)
return
/datum/cargoprofile/unary/trainer
name = "Boxing Trainer"
id = "trainer"
blacklist = list()
whitelist = list(/mob/living/carbon/human)
mobcheck = 1
var/const/PUNCH_WORK = 6
dedicated_path = /obj/machinery/programmable/unary/trainer
contains(var/atom/A)
if(!istype(A,/mob))
return 0
if(blacklist)
for(var/T in blacklist)
if(istype(A,T))
return 0
if(whitelist)
for(var/T in whitelist)
if(istype(A,T))
return 1
return 0
return 1
proc/punch(var/mob/living/carbon/human/M,var/maxpunches)
//stolen from holographic boxing gloves code
//This should probably be done BY the mob, however, the attack code will be expecting a source mob.
var/damage
if(prob(75))
damage = rand(0, 6) // pap
else
damage = rand(0, 12) // thwack
if(!damage)
playsound(master.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
master.visible_message("<span class='warning'>\The [src] punched at [M], but whiffed!</span>")
if(maxpunches > 1 && prob(50)) // Follow through on a miss, 50% chance
return punch(M,maxpunches - 1) + 1
return 1
var/obj/item/organ/external/affecting = M.get_organ(ran_zone("chest",50))
var/armor_block = M.run_armor_check(affecting, "melee")
playsound(master.loc, "punch", 25, 1, -1)
master.visible_message("<span class='danger'>\The [src] has punched [M]!</span>")
if(!master.emagged)
M.apply_damage(damage, STAMINA, affecting, armor_block) // Clean fight
else
M.apply_damage(damage, BRUTE, affecting, armor_block) // Foul! Foooul!
if(damage >= 9)
master.visible_message("<span class='danger'>\The [src] has weakened [M]!</span>")
M.apply_effect(4, WEAKEN, armor_block)
if(!master.emagged)
master.sleep = 1
return maxpunches // The machine is not so sophisticated as to not gloat
else
if(prob(25)) // Follow through on a hit, 25% chance. Pause after.
return punch(M,maxpunches-1) + 1
return 1
inlet_reaction(var/atom/W,var/turf/S,var/remaining)
//stolen from boxing gloves code
var/mob/living/carbon/human/M = W
if((M.lying || (M.health - M.staminaloss < 25))&& !master.emagged)
to_chat(M, "\The [src] gives you a break.")
master.sleep+=5
return 0 // Be polite
var/punches = punch(M,remaining / PUNCH_WORK)
if(punches>1)master.sleep++
return punches * PUNCH_WORK
#undef MAXCOIL
+120
View File
@@ -0,0 +1,120 @@
# Datum Component System (DCS)
## Concept
Loosely adapted from /vg/. This is an entity component system for adding behaviours to datums when inheritance doesn't quite cut it. By using signals and events instead of direct inheritance, you can inject behaviours without hacky overloads. It requires a different method of thinking, but is not hard to use correctly. If a behaviour can have application across more than one thing. Make it generic, make it a component. Atom/mob/obj event? Give it a signal, and forward it's arguments with a `SendSignal()` call. Now every component that want's to can also know about this happening.
### In the code
#### Slippery things
At the time of this writing, every object that is slippery overrides atom/Crossed does some checks, then slips the mob. Instead of all those Crossed overrides they could add a slippery component to all these objects. And have the checks in one proc that is run by the Crossed event
#### Powercells
A lot of objects have powercells. The `get_cell()` proc was added to give generic access to the cell var if it had one. This is just a specific use case of `GetComponent()`
#### Radios
The radio object as it is should not exist, given that more things use the _concept_ of radios rather than the object itself. The actual function of the radio can exist in a component which all the things that use it (Request consoles, actual radios, the SM shard) can add to themselves.
#### Standos
Stands have a lot of procs which mimic mob procs. Rather than inserting hooks for all these procs in overrides, the same can be accomplished with signals
## API
### Defines
1. `COMPONENT_INCOMPATIBLE` Return this from `/datum/component/Initialize` or `datum/component/OnTransfer` to have the component be deleted if it's applied to an incorrect type. `parent` must not be modified if this is to be returned.
### Vars
1. `/datum/var/list/datum_components` (private)
* Lazy associated list of type -> component/list of components.
1. `/datum/component/var/enabled` (protected, boolean)
* If the component is enabled. If not, it will not react to signals
* `FALSE` by default, set to `TRUE` when a signal is registered
1. `/datum/component/var/dupe_mode` (protected, enum)
* How duplicate component types are handled when added to the datum.
* `COMPONENT_DUPE_HIGHLANDER` (default): Old component will be deleted, new component will first have `/datum/component/proc/InheritComponent(datum/component/old, FALSE)` on it
* `COMPONENT_DUPE_ALLOWED`: The components will be treated as separate, `GetComponent()` will return the first added
* `COMPONENT_DUPE_UNIQUE`: New component will be deleted, old component will first have `/datum/component/proc/InheritComponent(datum/component/new, TRUE)` on it
* `COMPONENT_DUPE_UNIQUE_PASSARGS`: New component will never exist and instead its initialization arguments will be passed on to the old component.
1. `/datum/component/var/dupe_type` (protected, type)
* Definition of a duplicate component type
* `null` means exact match on `type` (default)
* Any other type means that and all subtypes
1. `/datum/component/var/list/signal_procs` (private)
* Associated lazy list of signals -> `/datum/callback`s that will be run when the parent datum recieves that signal
1. `/datum/component/var/datum/parent` (protected, read-only)
* The datum this component belongs to
* Never `null` in child procs
### Procs
1. `/datum/proc/GetComponent(component_type(type)) -> datum/component?` (public, final)
* Returns a reference to a component of component_type if it exists in the datum, null otherwise
1. `/datum/proc/GetComponents(component_type(type)) -> list` (public, final)
* Returns a list of references to all components of component_type that exist in the datum
1. `/datum/proc/GetExactComponent(component_type(type)) -> datum/component?` (public, final)
* Returns a reference to a component whose type MATCHES component_type if that component exists in the datum, null otherwise
1. `GET_COMPONENT(varname, component_type)` OR `GET_COMPONENT_FROM(varname, component_type, src)`
* Shorthand for `var/component_type/varname = src.GetComponent(component_type)`
1. `/datum/proc/AddComponent(component_type(type), ...) -> datum/component` (public, final)
* Creates an instance of `component_type` in the datum and passes `...` to its `Initialize()` call
* Sends the `COMSIG_COMPONENT_ADDED` signal to the datum
* All components a datum owns are deleted with the datum
* Returns the component that was created. Or the old component in a dupe situation where `COMPONENT_DUPE_UNIQUE` was set
* If this tries to add an component to an incompatible type, the component will be deleted and the result will be `null`. This is very unperformant, try not to do it
* Properly handles duplicate situations based on the `dupe_mode` var
1. `/datum/proc/LoadComponent(component_type(type), ...) -> datum/component` (public, final)
* Equivalent to calling `GetComponent(component_type)` where, if the result would be `null`, returns `AddComponent(component_type, ...)` instead
1. `/datum/proc/ComponentActivated(datum/component/C)` (abstract, async)
* Called on a component's `parent` after a signal recieved causes it to activate. `src` is the parameter
* Will only be called if a component's callback returns `TRUE`
1. `/datum/proc/TakeComponent(datum/component/C)` (public, final)
* Properly transfers ownership of a component from one datum to another
* Signals `COMSIG_COMPONENT_REMOVING` on the parent
* Called on the datum you want to own the component with another datum's component
1. `/datum/proc/SendSignal(signal, ...)` (public, final)
* Call to send a signal to the components of the target datum
* Extra arguments are to be specified in the signal definition
* Returns a bitflag with signal specific information assembled from all activated components
1. `/datum/component/New(datum/parent, ...)` (private, final)
* Runs internal setup for the component
* Extra arguments are passed to `Initialize()`
1. `/datum/component/Initialize(...)` (abstract, no-sleep)
* Called by `New()` with the same argments excluding `parent`
* Component does not exist in `parent`'s `datum_components` list yet, although `parent` is set and may be used
* Signals will not be recieved while this function is running
* Component may be deleted after this function completes without being attached
* Do not call `qdel(src)` from this function
1. `/datum/component/Destroy(force(bool), silent(bool))` (virtual, no-sleep)
* Sends the `COMSIG_COMPONENT_REMOVING` signal to the parent datum if the `parent` isn't being qdeleted
* Properly removes the component from `parent` and cleans up references
* Setting `force` makes it not check for and remove the component from the parent
* Setting `silent` deletes the component without sending a `COMSIG_COMPONENT_REMOVING` signal
1. `/datum/component/proc/InheritComponent(datum/component/C, i_am_original(boolean))` (abstract, no-sleep)
* Called on a component when a component of the same type was added to the same parent
* See `/datum/component/var/dupe_mode`
* `C`'s type will always be the same of the called component
1. `/datum/component/proc/AfterComponentActivated()` (abstract, async)
* Called on a component that was activated after it's `parent`'s `ComponentActivated()` is called
1. `/datum/component/proc/OnTransfer(datum/new_parent)` (abstract, no-sleep)
* Called before `new_parent` is assigned to `parent` in `TakeComponent()`
* Allows the component to react to ownership transfers
1. `/datum/component/proc/_RemoveFromParent()` (private, final)
* Clears `parent` and removes the component from it's component list
1. `/datum/component/proc/_JoinParent` (private, final)
* Tries to add the component to it's `parent`s `datum_components` list
1. `/datum/component/proc/RegisterSignal(signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final) (Consider removing for performance gainz)
* If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments
* Makes a component listen for the specified `signal` on it's `parent` datum.
* When that signal is recieved `proc_ref` will be called on the component, along with associated arguments
* Example proc ref: `.proc/OnEvent`
* If a previous registration is overwritten by the call, a runtime occurs. Setting `override` to TRUE prevents this
* These callbacks run asyncronously
* Returning `TRUE` from these callbacks will trigger a `TRUE` return from the `SendSignal()` that initiated it
### See/Define signals and their arguments in __DEFINES\components.dm
+264
View File
@@ -0,0 +1,264 @@
/datum/component
var/enabled = FALSE
var/dupe_mode = COMPONENT_DUPE_HIGHLANDER
var/dupe_type
var/list/signal_procs
var/datum/parent
/datum/component/New(datum/P, ...)
parent = P
var/list/arguments = args.Copy(2)
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
qdel(src, TRUE, TRUE)
CRASH("Incompatible [type] assigned to a [P]!")
_JoinParent(P)
/datum/component/proc/_JoinParent()
var/datum/P = parent
//lazy init the parent's dc list
var/list/dc = P.datum_components
if(!dc)
P.datum_components = dc = list()
//set up the typecache
var/our_type = type
for(var/I in _GetInverseTypeList(our_type))
var/test = dc[I]
if(test) //already another component of this type here
var/list/components_of_type
if(!length(test))
components_of_type = list(test)
dc[I] = components_of_type
else
components_of_type = test
if(I == our_type) //exact match, take priority
var/inserted = FALSE
for(var/J in 1 to components_of_type.len)
var/datum/component/C = components_of_type[J]
if(C.type != our_type) //but not over other exact matches
components_of_type.Insert(J, I)
inserted = TRUE
break
if(!inserted)
components_of_type += src
else //indirect match, back of the line with ya
components_of_type += src
else //only component of this type, no list
dc[I] = src
/datum/component/proc/Initialize(...)
return
/datum/component/Destroy(force=FALSE, silent=FALSE)
enabled = FALSE
var/datum/P = parent
if(!force)
_RemoveFromParent()
if(!silent)
P.SendSignal(COMSIG_COMPONENT_REMOVING, src)
parent = null
LAZYCLEARLIST(signal_procs)
return ..()
/datum/component/proc/_RemoveFromParent()
var/datum/P = parent
var/list/dc = P.datum_components
for(var/I in _GetInverseTypeList())
var/list/components_of_type = dc[I]
if(length(components_of_type)) //
var/list/subtracted = components_of_type - src
if(subtracted.len == 1) //only 1 guy left
dc[I] = subtracted[1] //make him special
else
dc[I] = subtracted
else //just us
dc -= I
if(!dc.len)
P.datum_components = null
/datum/component/proc/RegisterSignal(sig_type_or_types, proc_or_callback, override = FALSE)
if(QDELETED(src))
return
var/list/procs = signal_procs
if(!procs)
procs = list()
signal_procs = procs
var/list/sig_types = islist(sig_type_or_types) ? sig_type_or_types : list(sig_type_or_types)
for(var/sig_type in sig_types)
if(!override)
. = procs[sig_type]
if(.)
stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning")
if(!istype(proc_or_callback, /datum/callback)) //if it wasnt a callback before, it is now
proc_or_callback = CALLBACK(src, proc_or_callback)
procs[sig_type] = proc_or_callback
enabled = TRUE
/datum/component/proc/InheritComponent(datum/component/C, i_am_original)
return
/datum/component/proc/OnTransfer(datum/new_parent)
return
/datum/component/proc/_GetInverseTypeList(our_type = type)
#if DM_VERSION >= 513
#warning 512 is definitely stable now, remove the old code
#endif
#if DM_VERSION < 512
//remove this when we use 512 full time
set invisibility = 101
#endif
//we can do this one simple trick
var/current_type = parent_type
. = list(our_type, current_type)
//and since most components are root level + 1, this won't even have to run
while(current_type != /datum/component)
current_type = type2parent(current_type)
. += current_type
/datum/proc/SendSignal(sigtype, ...)
var/list/comps = datum_components
if(!comps)
return NONE
var/list/arguments = args.Copy(2)
var/target = comps[/datum/component]
if(!length(target))
var/datum/component/C = target
if(!C.enabled)
return NONE
var/datum/callback/CB = C.signal_procs[sigtype]
if(!CB)
return NONE
return CB.InvokeAsync(arglist(arguments))
. = NONE
for(var/I in target)
var/datum/component/C = I
if(!C.enabled)
continue
var/datum/callback/CB = C.signal_procs[sigtype]
if(!CB)
continue
. |= CB.InvokeAsync(arglist(arguments))
/datum/proc/GetComponent(c_type)
var/list/dc = datum_components
if(!dc)
return null
. = dc[c_type]
if(length(.))
return .[1]
/datum/proc/GetExactComponent(c_type)
var/list/dc = datum_components
if(!dc)
return null
var/datum/component/C = dc[c_type]
if(C)
if(length(C))
C = C[1]
if(C.type == c_type)
return C
return null
/datum/proc/GetComponents(c_type)
var/list/dc = datum_components
if(!dc)
return null
. = dc[c_type]
if(!length(.))
return list(.)
/datum/proc/AddComponent(new_type, ...)
var/datum/component/nt = new_type
var/dm = initial(nt.dupe_mode)
var/dt = initial(nt.dupe_type)
var/datum/component/old_comp
var/datum/component/new_comp
if(ispath(nt))
if(nt == /datum/component)
CRASH("[nt] attempted instantiation!")
if(!isnum(dm))
CRASH("[nt]: Invalid dupe_mode ([dm])!")
if(dt && !ispath(dt))
CRASH("[nt]: Invalid dupe_type ([dt])!")
else
new_comp = nt
args[1] = src
if(dm != COMPONENT_DUPE_ALLOWED)
if(!dt)
old_comp = GetExactComponent(nt)
else
old_comp = GetComponent(dt)
if(old_comp)
switch(dm)
if(COMPONENT_DUPE_UNIQUE)
if(!new_comp)
new_comp = new nt(arglist(args))
if(!QDELETED(new_comp))
old_comp.InheritComponent(new_comp, TRUE)
QDEL_NULL(new_comp)
if(COMPONENT_DUPE_HIGHLANDER)
if(!new_comp)
new_comp = new nt(arglist(args))
if(!QDELETED(new_comp))
new_comp.InheritComponent(old_comp, FALSE)
QDEL_NULL(old_comp)
if(COMPONENT_DUPE_UNIQUE_PASSARGS)
if(!new_comp)
var/list/arguments = args.Copy(2)
old_comp.InheritComponent(null, TRUE, arguments)
else
old_comp.InheritComponent(new_comp, TRUE)
else if(!new_comp)
new_comp = new nt(arglist(args)) // There's a valid dupe mode but there's no old component, act like normal
else if(!new_comp)
new_comp = new nt(arglist(args)) // Dupes are allowed, act like normal
if(!old_comp && !QDELETED(new_comp)) // Nothing related to duplicate components happened and the new component is healthy
SendSignal(COMSIG_COMPONENT_ADDED, new_comp)
return new_comp
return old_comp
/datum/proc/LoadComponent(component_type, ...)
. = GetComponent(component_type)
if(!.)
return AddComponent(arglist(args))
/datum/proc/TakeComponent(datum/component/C)
if(!C)
return
var/datum/helicopter = C.parent
if(helicopter == src)
//if we're taking to the same thing no need for anything
return
if(C.OnTransfer(src) == COMPONENT_INCOMPATIBLE)
qdel(C)
return
C._RemoveFromParent()
helicopter.SendSignal(COMSIG_COMPONENT_REMOVING, C)
C.parent = src
if(C == AddComponent(C))
C._JoinParent()
/datum/proc/TransferComponents(datum/target)
var/list/dc = datum_components
if(!dc)
return
var/comps = dc[/datum/component]
if(islist(comps))
for(var/I in comps)
target.TakeComponent(I)
else
target.TakeComponent(comps)
/datum/component/nano_host()
return parent
@@ -0,0 +1,389 @@
/*
This datum should be used for handling mineral contents of machines and whatever else is supposed to hold minerals and make use of them.
Variables:
amount - raw amount of the mineral this container is holding, calculated by the defined value MINERAL_MATERIAL_AMOUNT=2000.
max_amount - max raw amount of mineral this container can hold.
sheet_type - type of the mineral sheet the container handles, used for output.
parent - object that this container is being used by, used for output.
MAX_STACK_SIZE - size of a stack of mineral sheets. Constant.
*/
/datum/component/material_container
var/total_amount = 0
var/max_amount
var/sheet_type
var/list/materials
var/show_on_examine
var/list/allowed_typecache
var/last_inserted_id
var/precise_insertion = FALSE
var/datum/callback/precondition
var/datum/callback/after_insert
/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _show_on_examine = FALSE, list/allowed_types, datum/callback/_precondition, datum/callback/_after_insert)
materials = list()
max_amount = max(0, max_amt)
show_on_examine = _show_on_examine
if(allowed_types)
allowed_typecache = typecacheof(allowed_types)
precondition = _precondition
after_insert = _after_insert
RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy)
RegisterSignal(COMSIG_PARENT_EXAMINE, .proc/OnExamine)
var/list/possible_mats = list()
for(var/mat_type in subtypesof(/datum/material))
var/datum/material/MT = mat_type
possible_mats[initial(MT.id)] = mat_type
for(var/id in mat_list)
if(possible_mats[id])
var/mat_path = possible_mats[id]
materials[id] = new mat_path()
/datum/component/material_container/proc/OnExamine(mob/user)
for(var/I in materials)
var/datum/material/M = materials[I]
var/amt = amount(M.id)
if(amt)
to_chat(user, "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>")
/datum/component/material_container/proc/OnAttackBy(obj/item/I, mob/living/user)
var/list/tc = allowed_typecache
if(user.a_intent != INTENT_HELP)
return
if((I.flags_2 & (HOLOGRAM_2 | NO_MAT_REDEMPTION_2)) || (tc && !is_type_in_typecache(I, tc)))
to_chat(user, "<span class='warning'>[parent] won't accept [I]!</span>")
return
. = COMPONENT_NO_AFTERATTACK
var/datum/callback/pc = precondition
if(pc && !pc.Invoke(user))
return
var/material_amount = get_item_material_amount(I)
if(!material_amount)
to_chat(user, "<span class='warning'>[I] does not contain sufficient amounts of metal or glass to be accepted by [parent].</span>")
return
if(!has_space(material_amount))
to_chat(user, "<span class='warning'>[parent] is full. Please remove metal or glass from [parent] in order to insert more.</span>")
return
user_insert(I, user)
/datum/component/material_container/proc/user_insert(obj/item/I, mob/living/user)
set waitfor = FALSE
var/requested_amount
if(istype(I, /obj/item/stack) && precise_insertion)
var/atom/current_parent = parent
var/obj/item/stack/S = I
requested_amount = input(user, "How much do you want to insert?", "Inserting [S.singular_name]s") as num|null
if(isnull(requested_amount) || (requested_amount <= 0))
return
if(QDELETED(I) || QDELETED(user) || QDELETED(src) || parent != current_parent || user.incapacitated() || !in_range(current_parent, user) || user.l_hand != I && user.r_hand != I)
return
if(!user.drop_item())
to_chat(user, "<span class='warning'>[I] is stuck to you and cannot be placed into [parent].</span>")
return
var/inserted = insert_item(I, stack_amt = requested_amount)
if(inserted)
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
to_chat(user, "<span class='notice'>You insert [inserted] [S.singular_name][inserted>1 ? "s" : ""] into [parent].</span>")
if(!QDELETED(I))
if(!user.put_in_hands(I))
stack_trace("Warning: User could not put object back in hand during material container insertion, line [__LINE__]! This can lead to issues.")
I.forceMove(user.loc)
else
to_chat(user, "<span class='notice'>You insert a material total of [inserted] into [parent].</span>")
qdel(I)
if(after_insert)
after_insert.Invoke(I.type, last_inserted_id, inserted)
else
user.put_in_active_hand(I)
//For inserting an amount of material
/datum/component/material_container/proc/insert_amount(amt, id = null)
if(amt > 0 && has_space(amt))
var/total_amount_saved = total_amount
if(id)
var/datum/material/M = materials[id]
if(M)
M.amount += amt
total_amount += amt
else
for(var/i in materials)
var/datum/material/M = materials[i]
M.amount += amt
total_amount += amt
return (total_amount - total_amount_saved)
return FALSE
/datum/component/material_container/proc/insert_stack(obj/item/stack/S, amt, multiplier = 1)
if(isnull(amt))
amt = S.amount
if(amt <= 0)
return FALSE
if(amt > S.amount)
amt = S.amount
var/material_amt = get_item_material_amount(S)
if(!material_amt)
return FALSE
amt = min(amt, round(((max_amount - total_amount) / material_amt)))
if(!amt)
return FALSE
last_inserted_id = insert_materials(S,amt * multiplier)
S.use(amt)
return amt
/datum/component/material_container/proc/insert_item(obj/item/I, multiplier = 1, stack_amt)
if(!I)
return FALSE
if(istype(I, /obj/item/stack))
return insert_stack(I, stack_amt, multiplier)
var/material_amount = get_item_material_amount(I)
if(!material_amount || !has_space(material_amount))
return FALSE
last_inserted_id = insert_materials(I, multiplier)
return material_amount
/datum/component/material_container/proc/insert_materials(obj/item/I, multiplier = 1) //for internal usage only
var/datum/material/M
var/primary_mat
var/max_mat_value = 0
for(var/MAT in materials)
M = materials[MAT]
M.amount += I.materials[MAT] * multiplier
total_amount += I.materials[MAT] * multiplier
if(I.materials[MAT] > max_mat_value)
primary_mat = MAT
return primary_mat
//For consuming material
//mats is a list of types of material to use and the corresponding amounts, example: list(MAT_METAL=100, MAT_GLASS=200)
/datum/component/material_container/proc/use_amount(list/mats, multiplier=1)
if(!mats || !mats.len)
return FALSE
var/datum/material/M
for(var/MAT in materials)
M = materials[MAT]
if(M.amount < (mats[MAT] * multiplier))
return FALSE
var/total_amount_save = total_amount
for(var/MAT in materials)
M = materials[MAT]
M.amount -= mats[MAT] * multiplier
total_amount -= mats[MAT] * multiplier
return total_amount_save - total_amount
/datum/component/material_container/proc/use_amount_type(amt, id)
var/datum/material/M = materials[id]
if(M)
if(M.amount >= amt)
M.amount -= amt
total_amount -= amt
return amt
return FALSE
/datum/component/material_container/proc/transer_amt_to(var/datum/component/material_container/T, amt, id)
if((amt==0)||(!T)||(!id))
return FALSE
if(amt<0)
return T.transer_amt_to(src, -amt, id)
var/datum/material/M = materials[id]
if(M)
var/tr = min(amt, M.amount,T.can_insert_amount(amt, id))
if(tr)
use_amount_type(tr, id)
T.insert_amount(tr, id)
return tr
return FALSE
/datum/component/material_container/proc/can_insert_amount(amt, id)
if(amt && id)
var/datum/material/M = materials[id]
if(M)
if((total_amount + amt) <= max_amount)
return amt
else
return (max_amount-total_amount)
/datum/component/material_container/proc/can_use_amount(amt, id, list/mats)
if(amt && id)
var/datum/material/M = materials[id]
if(M && M.amount >= amt)
return TRUE
else if(istype(mats))
for(var/M in mats)
if(materials[M] && (mats[M] <= materials[M]))
continue
else
return FALSE
return TRUE
return FALSE
//For spawning mineral sheets; internal use only
/datum/component/material_container/proc/retrieve(sheet_amt, datum/material/M, target = null)
if(!M.sheet_type)
return FALSE
if(sheet_amt > 0)
if(M.amount < (sheet_amt * MINERAL_MATERIAL_AMOUNT))
sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT)
var/count = 0
while(sheet_amt > MAX_STACK_SIZE)
new M.sheet_type(get_turf(parent), MAX_STACK_SIZE)
count += MAX_STACK_SIZE
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
sheet_amt -= MAX_STACK_SIZE
if(round((sheet_amt * MINERAL_MATERIAL_AMOUNT) / MINERAL_MATERIAL_AMOUNT))
var/obj/item/stack/sheet/s = new M.sheet_type(get_turf(parent), sheet_amt)
if(target)
s.forceMove(target)
count += sheet_amt
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
return count
return FALSE
/datum/component/material_container/proc/retrieve_sheets(sheet_amt, id, target = null)
if(materials[id])
return retrieve(sheet_amt, materials[id], target)
return FALSE
/datum/component/material_container/proc/retrieve_amount(amt, id, target)
return retrieve_sheets(amount2sheet(amt), id, target)
/datum/component/material_container/proc/retrieve_all(target = null)
var/result = 0
var/datum/material/M
for(var/MAT in materials)
M = materials[MAT]
result += retrieve_sheets(amount2sheet(M.amount), MAT, target)
return result
/datum/component/material_container/proc/has_space(amt = 0)
return (total_amount + amt) <= max_amount
/datum/component/material_container/proc/has_materials(list/mats, multiplier=1)
if(!mats || !mats.len)
return FALSE
var/datum/material/M
for(var/MAT in mats)
M = materials[MAT]
if(M.amount < (mats[MAT] * multiplier))
return FALSE
return TRUE
/datum/component/material_container/proc/amount2sheet(amt)
if(amt >= MINERAL_MATERIAL_AMOUNT)
return round(amt / MINERAL_MATERIAL_AMOUNT)
return FALSE
/datum/component/material_container/proc/sheet2amount(sheet_amt)
if(sheet_amt > 0)
return sheet_amt * MINERAL_MATERIAL_AMOUNT
return FALSE
/datum/component/material_container/proc/amount(id)
var/datum/material/M = materials[id]
return M ? M.amount : 0
//returns the amount of material relevant to this container;
//if this container does not support glass, any glass in 'I' will not be taken into account
/datum/component/material_container/proc/get_item_material_amount(obj/item/I)
if(!istype(I))
return FALSE
var/material_amount = 0
for(var/MAT in materials)
material_amount += I.materials[MAT]
return material_amount
/datum/material
var/name
var/amount = 0
var/id = null
var/sheet_type = null
var/coin_type = null
/datum/material/metal
name = "Metal"
id = MAT_METAL
sheet_type = /obj/item/stack/sheet/metal
coin_type = /obj/item/coin/iron
/datum/material/glass
name = "Glass"
id = MAT_GLASS
sheet_type = /obj/item/stack/sheet/glass
/datum/material/silver
name = "Silver"
id = MAT_SILVER
sheet_type = /obj/item/stack/sheet/mineral/silver
coin_type = /obj/item/coin/silver
/datum/material/gold
name = "Gold"
id = MAT_GOLD
sheet_type = /obj/item/stack/sheet/mineral/gold
coin_type = /obj/item/coin/gold
/datum/material/diamond
name = "Diamond"
id = MAT_DIAMOND
sheet_type = /obj/item/stack/sheet/mineral/diamond
coin_type = /obj/item/coin/diamond
/datum/material/uranium
name = "Uranium"
id = MAT_URANIUM
sheet_type = /obj/item/stack/sheet/mineral/uranium
coin_type = /obj/item/coin/uranium
/datum/material/plasma
name = "Solid Plasma"
id = MAT_PLASMA
sheet_type = /obj/item/stack/sheet/mineral/plasma
coin_type = /obj/item/coin/plasma
/datum/material/bluespace
name = "Bluespace Mesh"
id = MAT_BLUESPACE
sheet_type = /obj/item/stack/sheet/bluespace_crystal
/datum/material/bananium
name = "Bananium"
id = MAT_BANANIUM
sheet_type = /obj/item/stack/sheet/mineral/bananium
coin_type = /obj/item/coin/clown
/datum/material/tranquillite
name = "Tranquillite"
id = MAT_TRANQUILLITE
sheet_type = /obj/item/stack/sheet/mineral/tranquillite
coin_type = /obj/item/coin/mime
/datum/material/titanium
name = "Titanium"
id = MAT_TITANIUM
sheet_type = /obj/item/stack/sheet/mineral/titanium
/datum/material/biomass
name = "Biomass"
id = MAT_BIOMASS
/datum/material/plastic
name = "Plastic"
id = MAT_PLASTIC
sheet_type = /obj/item/stack/sheet/plastic
-7
View File
@@ -1,7 +0,0 @@
datum
computer
var/name
folder
var/list/datum/computer/contents = list()
file
+137 -132
View File
@@ -255,7 +255,7 @@ var/record_id_num = 1001
if(PDA_Manifest.len)
PDA_Manifest.Cut()
if(H.mind && (H.mind.assigned_role != "MODE"))
if(H.mind && (H.mind.assigned_role != H.mind.special_role))
var/assignment
if(H.mind.role_alt_title)
assignment = H.mind.role_alt_title
@@ -468,137 +468,142 @@ var/record_id_num = 1001
var/icon/clothes_s = null
switch(H.mind.assigned_role)
if("Head of Personnel")
clothes_s = new /icon('icons/mob/uniform.dmi', "hop_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
if("Nanotrasen Representative")
clothes_s = new /icon('icons/mob/uniform.dmi', "officer_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "laceups"), ICON_UNDERLAY)
if("Blueshield")
clothes_s = new /icon('icons/mob/uniform.dmi', "officer_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/hands.dmi', "swat_gl"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "blueshield"), ICON_OVERLAY)
if("Magistrate")
clothes_s = new /icon('icons/mob/uniform.dmi', "really_black_suit_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "laceups"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "judge"), ICON_OVERLAY)
if("Bartender")
clothes_s = new /icon('icons/mob/uniform.dmi', "ba_suit_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Botanist")
clothes_s = new /icon('icons/mob/uniform.dmi', "hydroponics_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Chef")
clothes_s = new /icon('icons/mob/uniform.dmi', "chef_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Janitor")
clothes_s = new /icon('icons/mob/uniform.dmi', "janitor_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Librarian")
clothes_s = new /icon('icons/mob/uniform.dmi', "red_suit_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Quartermaster")
clothes_s = new /icon('icons/mob/uniform.dmi', "qm_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
if("Cargo Technician")
clothes_s = new /icon('icons/mob/uniform.dmi', "cargotech_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Shaft Miner")
clothes_s = new /icon('icons/mob/uniform.dmi', "miner_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Lawyer")
clothes_s = new /icon('icons/mob/uniform.dmi', "internalaffairs_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
if("Chaplain")
clothes_s = new /icon('icons/mob/uniform.dmi', "chapblack_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Research Director")
clothes_s = new /icon('icons/mob/uniform.dmi', "director_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY)
if("Scientist")
clothes_s = new /icon('icons/mob/uniform.dmi', "toxinswhite_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_tox_open"), ICON_OVERLAY)
if("Chemist")
clothes_s = new /icon('icons/mob/uniform.dmi', "chemistrywhite_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_chem_open"), ICON_OVERLAY)
if("Chief Medical Officer")
clothes_s = new /icon('icons/mob/uniform.dmi', "cmo_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_cmo_open"), ICON_OVERLAY)
if("Medical Doctor")
clothes_s = new /icon('icons/mob/uniform.dmi', "medical_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY)
if("Geneticist")
clothes_s = new /icon('icons/mob/uniform.dmi', "geneticswhite_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_gen_open"), ICON_OVERLAY)
if("Virologist")
clothes_s = new /icon('icons/mob/uniform.dmi', "virologywhite_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_vir_open"), ICON_OVERLAY)
if("Psychiatrist")
clothes_s = new /icon('icons/mob/uniform.dmi', "psych_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "laceups"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_UNDERLAY)
if("Paramedic")
clothes_s = new /icon('icons/mob/uniform.dmi', "paramedic_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Captain")
clothes_s = new /icon('icons/mob/uniform.dmi', "captain_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
if("Head of Security")
clothes_s = new /icon('icons/mob/uniform.dmi', "hosred_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
if("Warden")
clothes_s = new /icon('icons/mob/uniform.dmi', "warden_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
if("Detective")
clothes_s = new /icon('icons/mob/uniform.dmi', "detective_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "detective"), ICON_OVERLAY)
if("Security Pod Pilot")
clothes_s = new /icon('icons/mob/uniform.dmi', "secred_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "bomber"), ICON_OVERLAY)
if("Brig Physician")
clothes_s = new /icon('icons/mob/uniform.dmi', "medical_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "fr_jacket_open"), ICON_OVERLAY)
if("Security Officer")
clothes_s = new /icon('icons/mob/uniform.dmi', "secred_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
if("Chief Engineer")
clothes_s = new /icon('icons/mob/uniform.dmi', "chief_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY)
if("Station Engineer")
clothes_s = new /icon('icons/mob/uniform.dmi', "engine_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "orange"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY)
if("Life Support Specialist")
clothes_s = new /icon('icons/mob/uniform.dmi', "atmos_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY)
if("Mechanic")
clothes_s = new /icon('icons/mob/uniform.dmi', "mechanic_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "orange"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY)
if("Roboticist")
clothes_s = new /icon('icons/mob/uniform.dmi', "robotics_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY)
else if(H.mind.assigned_role in get_all_centcom_jobs())
clothes_s = new /icon('icons/mob/uniform.dmi', "officer_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "laceups"), ICON_UNDERLAY)
else
clothes_s = new /icon('icons/mob/uniform.dmi', "grey_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if(H.mind)
switch(H.mind.assigned_role)
if("Head of Personnel")
clothes_s = new /icon('icons/mob/uniform.dmi', "hop_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
if("Nanotrasen Representative")
clothes_s = new /icon('icons/mob/uniform.dmi', "officer_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "laceups"), ICON_UNDERLAY)
if("Blueshield")
clothes_s = new /icon('icons/mob/uniform.dmi', "officer_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/hands.dmi', "swat_gl"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "blueshield"), ICON_OVERLAY)
if("Magistrate")
clothes_s = new /icon('icons/mob/uniform.dmi', "really_black_suit_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "laceups"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "judge"), ICON_OVERLAY)
if("Bartender")
clothes_s = new /icon('icons/mob/uniform.dmi', "ba_suit_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Botanist")
clothes_s = new /icon('icons/mob/uniform.dmi', "hydroponics_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Chef")
clothes_s = new /icon('icons/mob/uniform.dmi', "chef_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Janitor")
clothes_s = new /icon('icons/mob/uniform.dmi', "janitor_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Librarian")
clothes_s = new /icon('icons/mob/uniform.dmi', "red_suit_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Quartermaster")
clothes_s = new /icon('icons/mob/uniform.dmi', "qm_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
if("Cargo Technician")
clothes_s = new /icon('icons/mob/uniform.dmi', "cargotech_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Shaft Miner")
clothes_s = new /icon('icons/mob/uniform.dmi', "miner_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Lawyer")
clothes_s = new /icon('icons/mob/uniform.dmi', "internalaffairs_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
if("Chaplain")
clothes_s = new /icon('icons/mob/uniform.dmi', "chapblack_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Research Director")
clothes_s = new /icon('icons/mob/uniform.dmi', "director_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY)
if("Scientist")
clothes_s = new /icon('icons/mob/uniform.dmi', "toxinswhite_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_tox_open"), ICON_OVERLAY)
if("Chemist")
clothes_s = new /icon('icons/mob/uniform.dmi', "chemistrywhite_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_chem_open"), ICON_OVERLAY)
if("Chief Medical Officer")
clothes_s = new /icon('icons/mob/uniform.dmi', "cmo_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_cmo_open"), ICON_OVERLAY)
if("Medical Doctor")
clothes_s = new /icon('icons/mob/uniform.dmi', "medical_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY)
if("Geneticist")
clothes_s = new /icon('icons/mob/uniform.dmi', "geneticswhite_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_gen_open"), ICON_OVERLAY)
if("Virologist")
clothes_s = new /icon('icons/mob/uniform.dmi', "virologywhite_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_vir_open"), ICON_OVERLAY)
if("Psychiatrist")
clothes_s = new /icon('icons/mob/uniform.dmi', "psych_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "laceups"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_UNDERLAY)
if("Paramedic")
clothes_s = new /icon('icons/mob/uniform.dmi', "paramedic_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
if("Captain")
clothes_s = new /icon('icons/mob/uniform.dmi', "captain_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
if("Head of Security")
clothes_s = new /icon('icons/mob/uniform.dmi', "hosred_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
if("Warden")
clothes_s = new /icon('icons/mob/uniform.dmi', "warden_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
if("Detective")
clothes_s = new /icon('icons/mob/uniform.dmi', "detective_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "detective"), ICON_OVERLAY)
if("Security Pod Pilot")
clothes_s = new /icon('icons/mob/uniform.dmi', "secred_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "bomber"), ICON_OVERLAY)
if("Brig Physician")
clothes_s = new /icon('icons/mob/uniform.dmi', "medical_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "white"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "fr_jacket_open"), ICON_OVERLAY)
if("Security Officer")
clothes_s = new /icon('icons/mob/uniform.dmi', "secred_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "jackboots"), ICON_UNDERLAY)
if("Chief Engineer")
clothes_s = new /icon('icons/mob/uniform.dmi', "chief_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "brown"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY)
if("Station Engineer")
clothes_s = new /icon('icons/mob/uniform.dmi', "engine_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "orange"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY)
if("Life Support Specialist")
clothes_s = new /icon('icons/mob/uniform.dmi', "atmos_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY)
if("Mechanic")
clothes_s = new /icon('icons/mob/uniform.dmi', "mechanic_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "orange"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/belt.dmi', "utility"), ICON_OVERLAY)
if("Roboticist")
clothes_s = new /icon('icons/mob/uniform.dmi', "robotics_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
clothes_s.Blend(new /icon('icons/mob/suit.dmi', "labcoat_open"), ICON_OVERLAY)
else if(H.mind.assigned_role in get_all_centcom_jobs())
clothes_s = new /icon('icons/mob/uniform.dmi', "officer_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "laceups"), ICON_UNDERLAY)
else
clothes_s = new /icon('icons/mob/uniform.dmi', "grey_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
else
clothes_s = new /icon('icons/mob/uniform.dmi', "grey_s")
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
preview_icon.Blend(face_s, ICON_OVERLAY) // Why do we do this twice
if(clothes_s)
+40
View File
@@ -0,0 +1,40 @@
/datum
var/gc_destroyed //Time when this object was destroyed.
var/list/active_timers //for SStimer
var/list/datum_components //for /datum/components
var/var_edited = FALSE //Warranty void if seal is broken
var/tmp/unique_datum_id = null
#ifdef TESTING
var/running_find_references
var/last_find_references = 0
#endif
// Default implementation of clean-up code.
// This should be overridden to remove all references pointing to the object being destroyed.
// Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE.
/datum/proc/Destroy(force = FALSE, ...)
tag = null
var/list/timers = active_timers
active_timers = null
for(var/thing in timers)
var/datum/timedevent/timer = thing
if(timer.spent)
continue
qdel(timer)
var/list/dc = datum_components
if(dc)
var/all_components = dc[/datum/component]
if(length(all_components))
for(var/I in all_components)
var/datum/component/C = I
qdel(C, FALSE, TRUE)
else
var/datum/component/C = all_components
qdel(C, FALSE, TRUE)
dc.Cut()
return QDEL_HINT_QUEUE
+27 -26
View File
@@ -1,8 +1,5 @@
// reference: /client/proc/modify_variables(var/atom/O, var/param_var_name = null, var/autodetect_class = 0)
/datum
var/var_edited = FALSE //Warranty void if seal is broken
/datum/proc/can_vv_get(var_name)
return TRUE
@@ -795,24 +792,28 @@
A.create_reagents(amount)
if(A.reagents)
var/list/reagent_options = list()
for(var/r_id in chemical_reagents_list)
var/datum/reagent/R = chemical_reagents_list[r_id]
reagent_options[R.name] = r_id
if(reagent_options.len)
reagent_options = sortAssoc(reagent_options)
reagent_options.Insert(1, "CANCEL")
var/chosen = input(usr, "Choose a reagent to add.", "Choose a reagent.") in reagent_options
var/chosen_id = reagent_options[chosen]
if(chosen_id)
var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num
if(amount)
A.reagents.add_reagent(chosen_id, amount)
log_admin("[key_name(usr)] has added [amount] units of [chosen] to \the [A]")
message_admins("[key_name_admin(usr)] has added [amount] units of [chosen] to \the [A]")
var/chosen_id
var/list/reagent_options = sortAssoc(chemical_reagents_list)
switch(alert(usr, "Choose a method.", "Add Reagents", "Enter ID", "Choose ID"))
if("Enter ID")
var/valid_id
while(!valid_id)
chosen_id = stripped_input(usr, "Enter the ID of the reagent you want to add.")
if(!chosen_id) //Get me out of here!
break
for(var/ID in reagent_options)
if(ID == chosen_id)
valid_id = 1
if(!valid_id)
to_chat(usr, "<span class='warning'>A reagent with that ID doesn't exist!</span>")
if("Choose ID")
chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in reagent_options
if(chosen_id)
var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", A.reagents.maximum_volume) as num
if(amount)
A.reagents.add_reagent(chosen_id, amount)
log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]")
message_admins("<span class='notice'>[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]</span>")
else if(href_list["explode"])
if(!check_rights(R_DEBUG|R_EVENT)) return
@@ -1259,7 +1260,7 @@
if(prompt != "Yes")
return
L.Cut(index, index+1)
log_to_dd("### ListVarEdit by [src]: /list's contents: REMOVED=[html_encode("[variable]")]")
log_world("### ListVarEdit by [src]: /list's contents: REMOVED=[html_encode("[variable]")]")
log_admin("[key_name(src)] modified list's contents: REMOVED=[variable]")
message_admins("[key_name_admin(src)] modified list's contents: REMOVED=[variable]")
return TRUE
@@ -1280,7 +1281,7 @@
return TRUE
uniqueList_inplace(L)
log_to_dd("### ListVarEdit by [src]: /list contents: CLEAR DUPES")
log_world("### ListVarEdit by [src]: /list contents: CLEAR DUPES")
log_admin("[key_name(src)] modified list's contents: CLEAR DUPES")
message_admins("[key_name_admin(src)] modified list's contents: CLEAR DUPES")
return TRUE
@@ -1292,7 +1293,7 @@
return TRUE
listclearnulls(L)
log_to_dd("### ListVarEdit by [src]: /list contents: CLEAR NULLS")
log_world("### ListVarEdit by [src]: /list contents: CLEAR NULLS")
log_admin("[key_name(src)] modified list's contents: CLEAR NULLS")
message_admins("[key_name_admin(src)] modified list's contents: CLEAR NULLS")
return TRUE
@@ -1307,7 +1308,7 @@
return TRUE
L.len = value["value"]
log_to_dd("### ListVarEdit by [src]: /list len: [L.len]")
log_world("### ListVarEdit by [src]: /list len: [L.len]")
log_admin("[key_name(src)] modified list's len: [L.len]")
message_admins("[key_name_admin(src)] modified list's len: [L.len]")
return TRUE
@@ -1319,7 +1320,7 @@
return TRUE
shuffle_inplace(L)
log_to_dd("### ListVarEdit by [src]: /list contents: SHUFFLE")
log_world("### ListVarEdit by [src]: /list contents: SHUFFLE")
log_admin("[key_name(src)] modified list's contents: SHUFFLE")
message_admins("[key_name_admin(src)] modified list's contents: SHUFFLE")
return TRUE
+1 -1
View File
@@ -88,7 +88,7 @@
switch(target_zone)
if(1)
if(isobj(H.head) && !istype(H.head, /obj/item/weapon/paper))
if(isobj(H.head) && !istype(H.head, /obj/item/paper))
Cl = H.head
passed = prob((Cl.permeability_coefficient*100) - 1)
if(passed && isobj(H.wear_mask))
@@ -38,11 +38,11 @@ Bonus
if(3, 4)
to_chat(M, "<span class='warning'><b>Your eyes burn!</b></span>")
M.EyeBlurry(20)
eyes.take_damage(1)
eyes.receive_damage(1)
else
to_chat(M, "<span class='userdanger'>Your eyes burn horrificly!</span>")
M.EyeBlurry(30)
eyes.take_damage(5)
eyes.receive_damage(5)
if(eyes.damage >= 10)
M.BecomeNearsighted()
if(prob(eyes.damage - 10 + 1))
+95
View File
@@ -0,0 +1,95 @@
/datum/disease/kingstons
name = "Kingstons Syndrome"
max_stages = 4
spread_text = "Airborne"
cure_text = "Milk"
cures = list("milk")
cure_chance = 50
agent = "Nya Virus"
viable_mobtypes = list(/mob/living/carbon/human)
permeability_mod = 0.75
desc = "If left untreated the subject will turn into a feline. In felines it has... OTHER... effects."
severity = DANGEROUS
/datum/disease/kingstons/stage_act()
..()
switch(stage)
if(1)
if(prob(10))
if(affected_mob.get_species() == "Tajaran")
to_chat(affected_mob, "<span class='notice'>You feel good.</span>")
else
to_chat(affected_mob, "<span class='notice'>You feel like playing with string.</span>")
if(2)
if(prob(10))
if(affected_mob.get_species() == "Tajaran")
to_chat(affected_mob, "<span class='danger'>Something in your throat itches.</span>")
else
to_chat(affected_mob, "<span class='danger'>You NEED to find a mouse.</span>")
if(3)
if(prob(10))
if(affected_mob.get_species() == "Tajaran")
to_chat(affected_mob, "<span class='danger'>You feel something in your throat!</span>")
affected_mob.emote("cough")
else
affected_mob.say(pick(list("Mew", "Meow!", "Nya!~")))
if(4)
if(prob(5))
if(affected_mob.get_species() == "Tajaran")
affected_mob.visible_message("<span class='danger'>[affected_mob] coughs up a hairball!</span>", \
"<span class='userdanger'>You cough up a hairball!</span>")
affected_mob.Stun(5)
else
affected_mob.visible_message("<span class='danger'>[affected_mob]'s form contorts into something more feline!</span>", \
"<span class='userdanger'>YOU TURN INTO A TAJARAN!</span>")
var/mob/living/carbon/human/catface = affected_mob
catface.set_species("Tajaran")
/datum/disease/kingstons/advanced
name = "Advanced Kingstons Syndrome"
spread_text = "Airborne"
cure_text = "Plasma"
cures = list("plasma")
cure_chance = 50
agent = "AMB45DR Bacteria"
viable_mobtypes = list(/mob/living/carbon/human)
permeability_mod = 0.75
desc = "If left untreated the subject will mutate to a different species."
severity = BIOHAZARD
var/list/virspecies = list("Human", "Tajaran", "Unathi", "Skrell", "Vulpkanin")//no karma races sorrys.
var/list/virsuffix = list("pox", "rot", "flu", "cough", "-gitis", "cold", "rash", "itch", "decay")
var/chosentype
var/chosensuff
/datum/disease/kingstons/advanced/New()
chosentype = pick(virspecies)
chosensuff = pick(virsuffix)
name = "[chosentype] [chosensuff]"
/datum/disease/kingstons/advanced/stage_act()
..()
switch(stage)
if(1)
if(prob(10))
to_chat(affected_mob, "<span class='notice'>You feel awkward.</span>")
if(2)
if(prob(10))
to_chat(affected_mob, "<span class='danger'>You itch.</span>")
if(3)
if(prob(10))
to_chat(affected_mob, "<span class='danger'>Your skin starts to flake!</span>")
if(4)
if(prob(5))
if(affected_mob.get_species() != chosentype)
affected_mob.visible_message("<span class='danger'>[affected_mob]'s skin splits and form contorts!</span>", \
"<span class='userdanger'>Your body mutates into a [chosentype]!</span>")
var/mob/living/carbon/human/twisted = affected_mob
twisted.set_species(chosentype)
else
affected_mob.visible_message("<span class='danger'>[affected_mob] scratches at thier skin!</span>", \
"<span class='userdanger'>You scratch your skin to try not to itch!</span>")
affected_mob.adjustBruteLoss(-5)
affected_mob.adjustStaminaLoss(5)
+45
View File
@@ -0,0 +1,45 @@
/datum/disease/lycan
name = "Lycancoughy"
form = "Infection"
max_stages = 4
spread_text = "On contact"
spread_flags = CONTACT_GENERAL
cure_text = "Ethanol"
cures = list("ethanol")
agent = "Excess Snuggles"
viable_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/human/monkey)
desc = "If left untreated subject will regurgitate... puppies."
severity = MEDIUM
/datum/disease/lycan/stage_act()
..()
switch(stage)
if(2) //also changes say, see say.dm
if(prob(5))
to_chat(affected_mob, "<span class='notice'>You itch.</span>")
affected_mob.emote("cough")
if(3)
if(prob(10))
to_chat(affected_mob, "<span class='notice'>You hear faint barking.</span>")
if(prob(5))
to_chat(affected_mob, "<span class='notice'>You crave meat.</span>")
affected_mob.emote("cough")
if(prob(2))
to_chat(affected_mob, "<span class='danger'>Your stomach growls!</span>")
if(4)
if(prob(10))
to_chat(affected_mob, "<span class='danger'>Your stomach barks?!</span>")
if(prob(5))
affected_mob.visible_message("<span class='danger'>[affected_mob] howls!</span>", \
"<span class='userdanger'>You howl!</span>")
affected_mob.AdjustConfused(rand(6, 8))
if(prob(3))
var/list/puppytype = list(/mob/living/simple_animal/pet/corgi/puppy, /mob/living/simple_animal/pet/pug, /mob/living/simple_animal/pet/fox)
var/mob/living/puppypicked = pick(puppytype)
affected_mob.visible_message("<span class='danger'>[affected_mob] coughs up [initial(puppypicked.name)]!</span>", \
"<span class='userdanger'>You cough up [initial(puppypicked.name)]?!</span>")
affected_mob.emote("cough")
affected_mob.adjustBruteLoss(5)
new puppypicked(affected_mob.loc)
new puppypicked(affected_mob.loc)
return
+35
View File
@@ -26,3 +26,38 @@
if(4)
if(prob(5))
affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) )
/datum/disease/pierrot_throat/advanced
name = "Advanced Pierrot's Throat"
spread_text = "Airborne"
cure_text = "Banana products, especially banana bread."
cures = list("banana")
cure_chance = 75
agent = "H0NI<42.B4n4 Virus"
viable_mobtypes = list(/mob/living/carbon/human)
permeability_mod = 0.75
desc = "If left untreated the subject will probably drive others to insanity and go insane themselves."
severity = DANGEROUS
/datum/disease/pierrot_throat/advanced/stage_act()
..()
switch(stage)
if(1)
if(prob(10))
to_chat(affected_mob, "<span class='danger'>You feel very silly.</span>")
if(prob(5))
to_chat(affected_mob, "<span class='danger'>You feel like making a joke.</span>")
if(2)
if(prob(10))
to_chat(affected_mob, "<span class='danger'>You don't just start seeing rainbows... YOU ARE RAINBOWS!</span>")
if(3)
if(prob(10))
to_chat(affected_mob, "<span class='danger'>Your thoughts are interrupted by a loud <b>HONK!</b></span>")
affected_mob << 'sound/items/AirHorn.ogg'
if(4)
if(prob(5))
affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) )
if(!istype(affected_mob.wear_mask, /obj/item/clothing/mask/gas/virusclown_hat))
affected_mob.equip_to_slot(new /obj/item/clothing/mask/gas/virusclown_hat(src), slot_wear_mask)
+2 -2
View File
@@ -50,7 +50,7 @@
affected_mob.overlays.Cut()
affected_mob.invisibility = 101
for(var/obj/item/W in affected_mob)
if(istype(W, /obj/item/weapon/implant))
if(istype(W, /obj/item/implant))
qdel(W)
continue
W.layer = initial(W.layer)
@@ -186,7 +186,7 @@
stage3 = list("<span class='danger'>Your appendages are melting away.</span>", "<span class='danger'>Your limbs begin to lose their shape.</span>")
stage4 = list("<span class='danger'>You are turning into a slime.</span>")
stage5 = list("<span class='danger'>You have become a slime.</span>")
new_form = /mob/living/simple_animal/slime
new_form = /mob/living/carbon/slime/random
/datum/disease/transformation/slime/stage_act()
..()
+2 -2
View File
@@ -78,9 +78,9 @@ STI KALY - blind
else
var/mob/living/carbon/H = affected_mob
if(prob(chance))
if(!istype(H.r_hand, /obj/item/weapon/twohanded/staff))
if(!istype(H.r_hand, /obj/item/twohanded/staff))
H.drop_r_hand()
H.put_in_r_hand( new /obj/item/weapon/twohanded/staff(H) )
H.put_in_r_hand( new /obj/item/twohanded/staff(H) )
return
return
+10 -10
View File
@@ -43,22 +43,22 @@
return 0
proc/custom_action(step, used_atom, user)
if(istype(used_atom, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/W = used_atom
if(istype(used_atom, /obj/item/weldingtool))
var/obj/item/weldingtool/W = used_atom
if(W.remove_fuel(0, user))
playsound(holder, W.usesound, 50, 1)
else
return 0
else if(istype(used_atom, /obj/item/weapon/wrench))
var/obj/item/weapon/wrench/W = used_atom
else if(istype(used_atom, /obj/item/wrench))
var/obj/item/wrench/W = used_atom
playsound(holder, W.usesound, 50, 1)
else if(istype(used_atom, /obj/item/weapon/screwdriver))
var/obj/item/weapon/screwdriver/S = used_atom
else if(istype(used_atom, /obj/item/screwdriver))
var/obj/item/screwdriver/S = used_atom
playsound(holder, S.usesound, 50, 1)
else if(istype(used_atom, /obj/item/weapon/wirecutters))
var/obj/item/weapon/wirecutters/W = used_atom
else if(istype(used_atom, /obj/item/wirecutters))
var/obj/item/wirecutters/W = used_atom
playsound(holder, W.usesound, 50, 1)
else if(istype(used_atom, /obj/item/stack/cable_coil))
@@ -117,8 +117,8 @@
to_chat(user, "<span class='warning'>You don't have enough cable! You need at least [amount] coils.</span>")
return 0
// WELDER
if(istype(used_atom,/obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/welder=used_atom
if(istype(used_atom,/obj/item/weldingtool))
var/obj/item/weldingtool/welder=used_atom
if(!welder.isOn())
to_chat(user, "<span class='notice'>You tap the [src] with your unlit welder. [pick("Ding","Dong")].</span>")
return 0
+8 -8
View File
@@ -9,8 +9,8 @@
var/atom/movable/teleatom //atom to teleport
var/atom/destination //destination to teleport to
var/precision = 0 //teleport precision
var/datum/effect/system/effectin //effect to show right before teleportation
var/datum/effect/system/effectout //effect to show right after teleportation
var/datum/effect_system/effectin //effect to show right before teleportation
var/datum/effect_system/effectout //effect to show right after teleportation
var/soundin //soundfile to play before teleportation
var/soundout //soundfile to play after teleportation
var/force_teleport = 1 //if false, teleport will use Move() proc (dense objects will prevent teleportation)
@@ -59,7 +59,7 @@
//custom effects must be properly set up first for instant-type teleports
//optional
/datum/teleport/proc/setEffects(datum/effect/system/aeffectin=null,datum/effect/system/aeffectout=null)
/datum/teleport/proc/setEffects(datum/effect_system/aeffectin=null,datum/effect_system/aeffectout=null)
effectin = istype(aeffectin) ? aeffectin : null
effectout = istype(aeffectout) ? aeffectout : null
return 1
@@ -79,7 +79,7 @@
/datum/teleport/proc/teleportChecks()
return 1
/datum/teleport/proc/playSpecials(atom/location,datum/effect/system/effect,sound)
/datum/teleport/proc/playSpecials(atom/location,datum/effect_system/effect,sound)
if(location)
if(effect)
spawn(-1)
@@ -146,9 +146,9 @@
/datum/teleport/instant/science
/datum/teleport/instant/science/setEffects(datum/effect/system/aeffectin,datum/effect/system/aeffectout)
/datum/teleport/instant/science/setEffects(datum/effect_system/aeffectin,datum/effect_system/aeffectout)
if(aeffectin==null || aeffectout==null)
var/datum/effect/system/spark_spread/aeffect = new
var/datum/effect_system/spark_spread/aeffect = new
aeffect.set_up(5, 1, teleatom)
effectin = effectin || aeffect
effectout = effectout || aeffect
@@ -158,10 +158,10 @@
/datum/teleport/instant/science/setPrecision(aprecision)
..()
if(istype(teleatom, /obj/item/weapon/storage/backpack/holding))
if(istype(teleatom, /obj/item/storage/backpack/holding))
precision = rand(1,100)
var/list/bagholding = teleatom.search_contents_for(/obj/item/weapon/storage/backpack/holding)
var/list/bagholding = teleatom.search_contents_for(/obj/item/storage/backpack/holding)
if(bagholding.len)
precision = max(rand(1,100)*bagholding.len,100)
if(istype(teleatom, /mob/living))
+15 -1
View File
@@ -1,4 +1,5 @@
/* HUD DATUMS */
var/global/list/all_huds = list()
///GLOBAL HUD LIST
var/datum/atom_hud/huds = list( \
@@ -7,6 +8,7 @@ var/datum/atom_hud/huds = list( \
DATA_HUD_MEDICAL_BASIC = new/datum/atom_hud/data/human/medical/basic(), \
DATA_HUD_MEDICAL_ADVANCED = new/datum/atom_hud/data/human/medical/advanced(), \
DATA_HUD_DIAGNOSTIC = new/datum/atom_hud/data/diagnostic(), \
DATA_HUD_DIAGNOSTIC_ADVANCED = new/datum/atom_hud/data/diagnostic/advanced(), \
DATA_HUD_HYDROPONIC = new/datum/atom_hud/data/hydroponic(), \
GAME_HUD_NATIONS = new/datum/atom_hud/antag(), \
ANTAG_HUD_CULT = new/datum/atom_hud/antag(), \
@@ -26,6 +28,18 @@ var/datum/atom_hud/huds = list( \
var/list/mob/hudusers = list() //list with all mobs who can see the hud
var/list/hud_icons = list() //these will be the indexes for the atom's hud_list
/datum/atom_hud/New()
all_huds += src
/datum/atom_hud/Destroy()
for(var/v in hudusers)
remove_hud_from(v)
for(var/v in hudatoms)
remove_from_hud(v)
all_huds -= src
return ..()
/datum/atom_hud/proc/remove_hud_from(mob/M)
if(!M)
return
@@ -82,7 +96,7 @@ var/datum/atom_hud/huds = list( \
serv_huds += serv.thrallhud
for(var/datum/atom_hud/hud in (huds|serv_huds))//|gang_huds))
for(var/datum/atom_hud/hud in (all_huds|serv_huds))//|gang_huds))
if(src in hud.hudusers)
hud.add_hud_to(src)
+100
View File
@@ -0,0 +1,100 @@
/*
output_atoms (list of atoms) The destination(s) for the sounds
mid_sounds (list or soundfile) Since this can be either a list or a single soundfile you can have random sounds. May contain further lists but must contain a soundfile at the end.
mid_length (num) The length to wait between playing mid_sounds
start_sound (soundfile) Played before starting the mid_sounds loop
start_length (num) How long to wait before starting the main loop after playing start_sound
end_sound (soundfile) The sound played after the main loop has concluded
chance (num) Chance per loop to play a mid_sound
volume (num) Sound output volume
muted (bool) Private. Used to stop the sound loop.
max_loops (num) The max amount of loops to run for.
direct (bool) If true plays directly to provided atoms instead of from them
*/
/datum/looping_sound
var/list/atom/output_atoms
var/mid_sounds
var/mid_length
var/start_sound
var/start_length
var/end_sound
var/chance
var/volume = 100
var/muted = TRUE
var/max_loops
var/direct
/datum/looping_sound/New(list/_output_atoms = list(), start_immediately = FALSE, _direct = FALSE)
if(!mid_sounds)
WARNING("A looping sound datum was created without sounds to play.")
return
output_atoms = _output_atoms
direct = _direct
if(start_immediately)
start()
/datum/looping_sound/Destroy()
stop()
output_atoms = null
return ..()
/datum/looping_sound/proc/start(atom/add_thing)
if(add_thing)
output_atoms |= add_thing
if(!muted)
return
muted = FALSE
on_start()
/datum/looping_sound/proc/stop(atom/remove_thing)
if(remove_thing)
output_atoms -= remove_thing
if(muted)
return
muted = TRUE
/datum/looping_sound/proc/sound_loop(looped = 0)
if(muted || (max_loops && looped > max_loops))
on_stop(looped)
return
if(!chance || prob(chance))
play(get_sound(looped))
addtimer(CALLBACK(src, .proc/sound_loop, ++looped), mid_length)
/datum/looping_sound/proc/play(soundfile)
var/list/atoms_cache = output_atoms
var/sound/S = sound(soundfile)
if(direct)
S.channel = open_sound_channel()
S.volume = volume
for(var/i in 1 to atoms_cache.len)
var/atom/thing = atoms_cache[i]
if(direct)
SEND_SOUND(thing, S)
else
playsound(thing, S, volume)
/datum/looping_sound/proc/get_sound(looped, _mid_sounds)
if(!_mid_sounds)
. = mid_sounds
else
. = _mid_sounds
while(!isfile(.) && !isnull(.))
. = pickweight(.)
/datum/looping_sound/proc/on_start()
var/start_wait = 0
if(start_sound)
play(start_sound)
start_wait = start_length
addtimer(CALLBACK(src, .proc/sound_loop), start_wait)
/datum/looping_sound/proc/on_stop(looped)
if(end_sound)
play(end_sound)
@@ -0,0 +1,7 @@
/datum/looping_sound/showering
start_sound = 'sound/machines/shower/shower_start.ogg'
start_length = 2
mid_sounds = list('sound/machines/shower/shower_mid1.ogg' = 1,'sound/machines/shower/shower_mid2.ogg' = 1,'sound/machines/shower/shower_mid3.ogg' = 1)
mid_length = 10
end_sound = 'sound/machines/shower/shower_end.ogg'
volume = 20
-283
View File
@@ -1,283 +0,0 @@
/*
This datum should be used for handling mineral contents of machines and whatever else is supposed to hold minerals and make use of them.
Variables:
amount - raw amount of the mineral this container is holding, calculated by the defined value MINERAL_MATERIAL_AMOUNT=2000.
max_amount - max raw amount of mineral this container can hold.
sheet_type - type of the mineral sheet the container handles, used for output.
owner - object that this container is being used by, used for output.
MAX_STACK_SIZE - size of a stack of mineral sheets. Constant.
*/
/datum/material_container
var/total_amount = 0
var/max_amount
var/sheet_type
var/obj/owner
var/list/materials = list()
//MAX_STACK_SIZE = 50
//MINERAL_MATERIAL_AMOUNT = 2000
/datum/material_container/New(obj/O, list/mat_list, max_amt = 0)
owner = O
max_amount = max(0, max_amt)
if(mat_list[MAT_METAL])
materials[MAT_METAL] = new /datum/material/metal()
if(mat_list[MAT_GLASS])
materials[MAT_GLASS] = new /datum/material/glass()
if(mat_list[MAT_SILVER])
materials[MAT_SILVER] = new /datum/material/silver()
if(mat_list[MAT_GOLD])
materials[MAT_GOLD] = new /datum/material/gold()
if(mat_list[MAT_DIAMOND])
materials[MAT_DIAMOND] = new /datum/material/diamond()
if(mat_list[MAT_URANIUM])
materials[MAT_URANIUM] = new /datum/material/uranium()
if(mat_list[MAT_PLASMA])
materials[MAT_PLASMA] = new /datum/material/plasma()
if(mat_list[MAT_BANANIUM])
materials[MAT_BANANIUM] = new /datum/material/bananium()
if(mat_list[MAT_TRANQUILLITE])
materials[MAT_TRANQUILLITE] = new /datum/material/tranquillite()
/datum/material_container/Destroy()
QDEL_LIST_ASSOC_VAL(materials)
owner = null
return ..()
//For inserting an amount of material
/datum/material_container/proc/insert_amount(amt, material_type = null)
if(amt > 0 && has_space(amt))
var/total_amount_saved = total_amount
if(material_type)
var/datum/material/M = materials[material_type]
if(M)
M.amount += amt
total_amount += amt
else
for(var/datum/material/M in materials)
M.amount += amt
total_amount += amt
return (total_amount - total_amount_saved)
return 0
/datum/material_container/proc/insert_stack(obj/item/stack/S, amt = 0)
if(amt <= 0)
return 0
if(amt > S.amount)
amt = S.amount
var/material_amt = get_item_material_amount(S)
if(!material_amt)
return 0
amt = min(amt, round(((max_amount - total_amount) / material_amt)))
if(!amt)
return 0
insert_materials(S,amt)
S.use(amt)
return amt
/datum/material_container/proc/insert_item(obj/item/I, multiplier = 1)
if(!I)
return 0
if(istype(I,/obj/item/stack))
var/obj/item/stack/S = I
return insert_stack(I, S.amount)
var/material_amount = get_item_material_amount(I)
if(!material_amount || !has_space(material_amount))
return 0
insert_materials(I, multiplier)
return material_amount
/datum/material_container/proc/insert_materials(obj/item/I, multiplier = 1) //for internal usage only
var/datum/material/M
for(var/MAT in materials)
M = materials[MAT]
M.amount += I.materials[MAT] * multiplier
total_amount += I.materials[MAT] * multiplier
//For consuming material
//mats is a list of types of material to use and the corresponding amounts, example: list(MAT_METAL=100, MAT_GLASS=200)
/datum/material_container/proc/use_amount(list/mats, multiplier=1)
if(!mats || !mats.len)
return 0
var/datum/material/M
for(var/MAT in materials)
M = materials[MAT]
if(M.amount < (mats[MAT] * multiplier))
return 0
var/total_amount_save = total_amount
for(var/MAT in materials)
M = materials[MAT]
M.amount -= mats[MAT] * multiplier
total_amount -= mats[MAT] * multiplier
return total_amount_save - total_amount
/datum/material_container/proc/use_amount_type(amt, material_type)
var/datum/material/M
M = materials[material_type]
if(M)
if(M.amount >= amt)
M.amount -= amt
total_amount -= amt
return amt
return 0
//For spawning mineral sheets; internal use only
/datum/material_container/proc/retrieve(sheet_amt, datum/material/M)
if(!M.sheet_type)
return 0
if(sheet_amt > 0)
if(M.amount < (sheet_amt * MINERAL_MATERIAL_AMOUNT))
sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT)
var/count = 0
while(sheet_amt > MAX_STACK_SIZE)
new M.sheet_type(get_turf(owner), MAX_STACK_SIZE)
count += MAX_STACK_SIZE
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.material_type)
sheet_amt -= MAX_STACK_SIZE
if(round(M.amount / MINERAL_MATERIAL_AMOUNT))
new M.sheet_type(get_turf(owner), sheet_amt)
count += sheet_amt
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.material_type)
return count
return 0
/datum/material_container/proc/retrieve_sheets(sheet_amt, material_type)
if(materials[material_type])
return retrieve(sheet_amt, materials[material_type])
return 0
/datum/material_container/proc/retrieve_amount(amt, material_type)
return retrieve_sheets(amount2sheet(amt),material_type)
/datum/material_container/proc/retrieve_all()
var/result = 0
var/datum/material/M
for(var/MAT in materials)
M = materials[MAT]
result += retrieve_sheets(amount2sheet(M.amount), MAT)
return result
/datum/material_container/proc/has_space(amt = 0)
return (total_amount + amt) <= max_amount
/datum/material_container/proc/has_materials(list/mats, multiplier=1)
if(!mats || !mats.len)
return 0
var/datum/material/M
for(var/MAT in mats)
M = materials[MAT]
if(M.amount < (mats[MAT] * multiplier))
return 0
return 1
/datum/material_container/proc/amount2sheet(amt)
if(amt >= MINERAL_MATERIAL_AMOUNT)
return round(amt / MINERAL_MATERIAL_AMOUNT)
return 0
/datum/material_container/proc/sheet2amount(sheet_amt)
if(sheet_amt > 0)
return sheet_amt * MINERAL_MATERIAL_AMOUNT
return 0
/datum/material_container/proc/amount(material_type)
var/datum/material/M = materials[material_type]
return M ? M.amount : 0
//returns the amount of material relevant to this container;
//if this container does not support glass, any glass in 'I' will not be taken into account
/datum/material_container/proc/get_item_material_amount(obj/item/I)
if(!istype(I))
return 0
var/material_amount = 0
for(var/MAT in materials)
material_amount += I.materials[MAT]
return material_amount
/datum/material
var/amount = 0
var/material_type = null
var/sheet_type = null
/datum/material/metal
/datum/material/metal/New()
..()
material_type = MAT_METAL
sheet_type = /obj/item/stack/sheet/metal
/datum/material/glass
/datum/material/glass/New()
..()
material_type = MAT_GLASS
sheet_type = /obj/item/stack/sheet/glass
/datum/material/silver
/datum/material/silver/New()
..()
material_type = MAT_SILVER
sheet_type = /obj/item/stack/sheet/mineral/silver
/datum/material/gold
/datum/material/gold/New()
..()
material_type = MAT_GOLD
sheet_type = /obj/item/stack/sheet/mineral/gold
/datum/material/diamond
/datum/material/diamond/New()
..()
material_type = MAT_DIAMOND
sheet_type = /obj/item/stack/sheet/mineral/diamond
/datum/material/uranium
/datum/material/uranium/New()
..()
material_type = MAT_URANIUM
sheet_type = /obj/item/stack/sheet/mineral/uranium
/datum/material/plasma
/datum/material/plasma/New()
..()
material_type = MAT_PLASMA
sheet_type = /obj/item/stack/sheet/mineral/plasma
/datum/material/bananium
/datum/material/bananium/New()
..()
material_type = MAT_BANANIUM
sheet_type = /obj/item/stack/sheet/mineral/bananium
/datum/material/tranquillite
/datum/material/tranquillite/New()
..()
material_type = MAT_TRANQUILLITE
sheet_type = /obj/item/stack/sheet/mineral/tranquillite
/datum/material/biomass
/datum/material/biomass/New()
..()
material_type = MAT_BIOMASS
+28 -60
View File
@@ -38,8 +38,8 @@
var/memory
var/assigned_role
var/special_role
var/assigned_role //assigned role is what job you're assigned to when you join the station.
var/special_role //special roles are typically reserved for antags or roles like ERT. If you want to avoid a character being automatically announced by the AI, on arrival (becuase they're an off station character or something); ensure that special_role and assigned_role are equal.
var/list/restricted_roles = list()
var/list/spell_list = list() // Wizard mode & "Give Spell" badmin button.
@@ -102,7 +102,7 @@
current.mind = null
leave_all_huds() //leave all the huds in the old body, so it won't get huds if somebody else enters it
nanomanager.user_transferred(current, new_character)
SSnanoui.user_transferred(current, new_character)
if(new_character.mind) //remove any mind currently in our new body's mind variable
new_character.mind.current = null
@@ -191,7 +191,7 @@
text += "<br>Flash: <a href='?src=[UID()];revolution=flash'>give</a>"
var/list/L = current.get_contents()
var/obj/item/device/flash/flash = locate() in L
var/obj/item/flash/flash = locate() in L
if(flash)
if(!flash.broken)
text += "|<a href='?src=[UID()];revolution=takeflash'>take</a>."
@@ -435,7 +435,7 @@
ishuman(current) )
text = "Uplink: <a href='?src=[UID()];common=uplink'>give</a>"
var/obj/item/device/uplink/hidden/suplink = find_syndicate_uplink()
var/obj/item/uplink/hidden/suplink = find_syndicate_uplink()
var/crystals
if(suplink)
crystals = suplink.uses
@@ -541,8 +541,8 @@
new_objective = new objective_path
new_objective.owner = src
new_objective:target = new_target:mind
//Will display as special role if the target is set as MODE. Ninjas/commandos/nuke ops.
new_objective.explanation_text = "[objective_type] [new_target:real_name], the [new_target:mind:assigned_role=="MODE" ? (new_target:mind:special_role) : (new_target:mind:assigned_role)]."
//Will display as special role if assigned mode is equal to special role.. Ninjas/commandos/nuke ops.
new_objective.explanation_text = "[objective_type] [new_target:real_name], the [new_target:mind:assigned_role == new_target:mind:special_role ? (new_target:mind:special_role) : (new_target:mind:assigned_role)]."
if("destroy")
var/list/possible_targets = active_ais(1)
@@ -674,14 +674,14 @@
switch(href_list["implant"])
if("remove")
for(var/obj/item/weapon/implant/mindshield/I in H.contents)
for(var/obj/item/implant/mindshield/I in H.contents)
if(I && I.implanted)
qdel(I)
to_chat(H, "<span class='notice'><Font size =3><B>Your mindshield implant has been deactivated.</B></FONT></span>")
log_admin("[key_name(usr)] has deactivated [key_name(current)]'s mindshield implant")
message_admins("[key_name_admin(usr)] has deactivated [key_name_admin(current)]'s mindshield implant")
if("add")
var/obj/item/weapon/implant/mindshield/L = new/obj/item/weapon/implant/mindshield(H)
var/obj/item/implant/mindshield/L = new/obj/item/implant/mindshield(H)
L.implant(H)
log_admin("[key_name(usr)] has given [key_name(current)] a mindshield implant")
@@ -778,7 +778,7 @@
if("takeflash")
var/list/L = current.get_contents()
var/obj/item/device/flash/flash = locate() in L
var/obj/item/flash/flash = locate() in L
if(!flash)
to_chat(usr, "<span class='warning'>Deleting flash failed!</span>")
qdel(flash)
@@ -787,7 +787,7 @@
if("repairflash")
var/list/L = current.get_contents()
var/obj/item/device/flash/flash = locate() in L
var/obj/item/flash/flash = locate() in L
if(!flash)
to_chat(usr, "<span class='warning'>Repairing flash failed!</span>")
else
@@ -797,7 +797,7 @@
if("reequip")
var/list/L = current.get_contents()
var/obj/item/device/flash/flash = locate() in L
var/obj/item/flash/flash = locate() in L
qdel(flash)
take_uplink()
var/fail = 0
@@ -821,14 +821,14 @@
if(!(src in ticker.mode.cult))
ticker.mode.add_cultist(src)
special_role = SPECIAL_ROLE_CULTIST
to_chat(current, "<span class='cultitalic'>You catch a glimpse of the Realm of [ticker.mode.cultdat.entity_name], [ticker.mode.cultdat.entity_title3]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.mode.cultdat.entity_name].</span>")
to_chat(current, "<span class='cultitalic'>Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve [ticker.mode.cultdat.entity_title2] above all else. Bring It back.</span>")
to_chat(current, "<span class='cultitalic'>You catch a glimpse of the Realm of [ticker.cultdat.entity_name], [ticker.cultdat.entity_title3]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.cultdat.entity_name].</span>")
to_chat(current, "<span class='cultitalic'>Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve [ticker.cultdat.entity_title2] above all else. Bring It back.</span>")
log_admin("[key_name(usr)] has culted [key_name(current)]")
message_admins("[key_name_admin(usr)] has culted [key_name_admin(current)]")
if("tome")
var/mob/living/carbon/human/H = current
if(istype(H))
var/obj/item/weapon/tome/T = new(H)
var/obj/item/tome/T = new(H)
var/list/slots = list (
"backpack" = slot_in_backpack,
@@ -1199,7 +1199,7 @@
message_admins("[key_name_admin(usr)] has taken [key_name_admin(current)]'s uplink")
if("crystals")
if(usr.client.holder.rights & (R_SERVER|R_EVENT))
var/obj/item/device/uplink/hidden/suplink = find_syndicate_uplink()
var/obj/item/uplink/hidden/suplink = find_syndicate_uplink()
var/crystals
if(suplink)
crystals = suplink.uses
@@ -1227,37 +1227,6 @@
message_admins("[key_name_admin(usr)] has announced [key_name_admin(current)]'s objectives")
edit_memory()
/*
/datum/mind/proc/clear_memory(var/silent = 1)
var/datum/game_mode/current_mode = ticker.mode
// remove traitor uplinks
var/list/L = current.get_contents()
for(var/t in L)
if(istype(t, /obj/item/device/pda))
if(t:uplink) qdel(t:uplink)
t:uplink = null
else if(istype(t, /obj/item/device/radio))
if(t:traitorradio) qdel(t:traitorradio)
t:traitorradio = null
t:traitor_frequency = 0.0
else if(istype(t, /obj/item/weapon/SWF_uplink) || istype(t, /obj/item/weapon/syndicate_uplink))
if(t:origradio)
var/obj/item/device/radio/R = t:origradio
R.loc = current.loc
R.traitorradio = null
R.traitor_frequency = 0.0
qdel(t)
// remove wizards spells
//If there are more special powers that need removal, they can be procced into here./N
current.spellremove(current)
// clear memory
memory = ""
special_role = null
*/
// Datum antag mind procs
@@ -1314,7 +1283,7 @@
return null
/datum/mind/proc/take_uplink()
var/obj/item/device/uplink/hidden/H = find_syndicate_uplink()
var/obj/item/uplink/hidden/H = find_syndicate_uplink()
if(H)
qdel(H)
@@ -1336,7 +1305,7 @@
else
current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]"
special_role = SPECIAL_ROLE_NUKEOPS
assigned_role = "MODE"
assigned_role = SPECIAL_ROLE_NUKEOPS
to_chat(current, "<span class='notice'>You are a [syndicate_name()] agent!</span>")
ticker.mode.forge_syndicate_objectives(src)
ticker.mode.greet_syndicate(src)
@@ -1371,7 +1340,7 @@
if(!(src in ticker.mode.wizards))
ticker.mode.wizards += src
special_role = SPECIAL_ROLE_WIZARD
assigned_role = "MODE"
assigned_role = SPECIAL_ROLE_WIZARD
//ticker.mode.learn_basic_spells(current)
if(!wizardstart.len)
current.loc = pick(latejoin)
@@ -1380,7 +1349,7 @@
current.loc = pick(wizardstart)
ticker.mode.equip_wizard(current)
for(var/obj/item/weapon/spellbook/S in current.contents)
for(var/obj/item/spellbook/S in current.contents)
S.op = 0
ticker.mode.name_wizard(current)
ticker.mode.forge_wizard_objectives(src)
@@ -1393,20 +1362,20 @@
ticker.mode.cult += src
ticker.mode.update_cult_icons_added(src)
special_role = SPECIAL_ROLE_CULTIST
to_chat(current, "<font color=\"cultitalic\"><b><i>You catch a glimpse of the Realm of [ticker.mode.cultdat.entity_name], [ticker.mode.cultdat.entity_title2]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.mode.cultdat.entity_name].</b></i></font>")
to_chat(current, "<font color=\"cultitalic\"><b><i>You catch a glimpse of the Realm of [ticker.cultdat.entity_name], [ticker.cultdat.entity_title2]. You now see how flimsy the world is, you see that it should be open to the knowledge of [ticker.cultdat.entity_name].</b></i></font>")
to_chat(current, "<font color=\"cultitalic\"><b><i>Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.</b></i></font>")
var/datum/game_mode/cult/cult = ticker.mode
if(GAMEMODE_IS_CULT)
cult.memorize_cult_objectives(src)
else
var/explanation = "Summon [ticker.mode.cultdat.entity_name] via the use of the appropriate rune. It will only work if nine cultists stand on and around it."
var/explanation = "Summon [ticker.cultdat.entity_name] via the use of the appropriate rune. It will only work if nine cultists stand on and around it."
to_chat(current, "<B>Objective #1</B>: [explanation]")
current.memory += "<B>Objective #1</B>: [explanation]<BR>"
var/mob/living/carbon/human/H = current
if(istype(H))
var/obj/item/weapon/tome/T = new(H)
var/obj/item/tome/T = new(H)
var/list/slots = list (
"backpack" = slot_in_backpack,
@@ -1443,7 +1412,7 @@
ticker.mode.greet_revolutionary(src,0)
var/list/L = current.get_contents()
var/obj/item/device/flash/flash = locate() in L
var/obj/item/flash/flash = locate() in L
qdel(flash)
take_uplink()
var/fail = 0
@@ -1577,7 +1546,7 @@
var/datum/objective/protect/mindslave/MS = new
MS.owner = src
MS.target = missionary.mind
MS.explanation_text = "Obey every order from and protect [missionary.real_name], the [missionary.mind.assigned_role=="MODE" ? (missionary.mind.special_role) : (missionary.mind.assigned_role)]."
MS.explanation_text = "Obey every order from and protect [missionary.real_name], the [missionary.mind.assigned_role == missionary.mind.special_role ? (missionary.mind.special_role) : (missionary.mind.assigned_role)]."
objectives += MS
for(var/datum/objective/objective in objectives)
to_chat(current, "<B>Objective #1</B>: [objective.explanation_text]")
@@ -1600,16 +1569,15 @@
jumpsuit.color = team_color
H.update_inv_w_uniform(0,0)
add_logs(missionary, current, "converted", addition = "for [convert_duration/600] minutes")
addtimer(src, "remove_zealot", convert_duration, FALSE, jumpsuit) //deconverts after the timer expires
add_attack_logs(missionary, current, "Converted to a zealot for [convert_duration/600] minutes")
addtimer(CALLBACK(src, .proc/remove_zealot, jumpsuit), convert_duration) //deconverts after the timer expires
return 1
/datum/mind/proc/remove_zealot(obj/item/clothing/under/jumpsuit = null)
if(!zealot_master) //if they aren't a zealot, we can't remove their zealot status, obviously. don't bother with the rest so we don't confuse them with the messages
return
ticker.mode.remove_traitor_mind(src)
add_logs(zealot_master, current, "lost control of", addition = "as their zealot master")
add_attack_logs(zealot_master, current, "Lost control of zealot")
zealot_master = null
if(jumpsuit)
+9 -2
View File
@@ -22,8 +22,15 @@
var/list/fields = list( )
/datum/data/record/Destroy()
..()
return QDEL_HINT_HARDDEL_NOW
if(src in data_core.medical)
data_core.medical -= src
if(src in data_core.security)
data_core.security -= src
if(src in data_core.general)
data_core.general -= src
if(src in data_core.locked)
data_core.locked -= src
return ..()
/datum/data/text
name = "text"
-63
View File
@@ -1,63 +0,0 @@
// module datum.
// this is per-object instance, and shows the condition of the modules in the object
// actual modules needed is referenced through modulestypes and the object type
/datum/module
var/status // bits set if working, 0 if broken
var/installed // bits set if installed, 0 if missing
// moduletypes datum
// this is per-object type, and shows the modules needed for a type of object
/datum/moduletypes
var/list/modcount = list() // assoc list of the count of modules for a type
var/list/modules = list( // global associative list
"/obj/machinery/power/apc" = "card_reader,power_control,id_auth,cell_power,cell_charge")
/datum/module/New(var/obj/O)
var/type = O.type // the type of the creating object
var/mneed = mods.inmodlist(type) // find if this type has modules defined
if(!mneed) // not found in module list?
qdel(src) // delete self, thus ending proc
return
var/needed = mods.getbitmask(type) // get a bitmask for the number of modules in this object
status = needed
installed = needed
/datum/moduletypes/proc/addmod(var/type, var/modtextlist)
modules += type // index by type text
modules[type] = modtextlist
/datum/moduletypes/proc/inmodlist(var/type)
return ("[type]" in modules)
/datum/moduletypes/proc/getbitmask(var/type)
var/count = modcount["[type]"]
if(count)
return 2**count-1
var/modtext = modules["[type]"]
var/num = 1
var/pos = 1
while(1)
pos = findtext(modtext, ",", pos, 0)
if(!pos)
break
else
pos++
num++
modcount += "[type]"
modcount["[type]"] = num
return 2**num-1
+13
View File
@@ -0,0 +1,13 @@
// Mutable appearances are an inbuilt byond datastructure. Read the documentation on them by hitting F1 in DM.
// Basically use them instead of images for overlays/underlays and when changing an object's appearance if you're doing so with any regularity.
// Unless you need the overlay/underlay to have a different direction than the base object. Then you have to use an image due to a bug.
// Mutable appearances are children of images, just so you know.
// Helper similar to image()
/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER)
var/mutable_appearance/MA = new()
MA.icon = icon
MA.icon_state = icon_state
MA.layer = layer
return MA
+9
View File
@@ -22,6 +22,8 @@
var/pda = null
var/internals_slot = null //ID of slot containing a gas tank
var/list/backpack_contents = list() // In the list(path=count,otherpath=count) format
var/list/implants = null
var/list/cybernetic_implants = null
/datum/outfit/proc/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
@@ -89,6 +91,13 @@
var/number = backpack_contents[path]
for(var/i = 0, i < number, i++)
equip_item(H, path, slot_in_backpack)
if(implants)
for(var/path in implants)
var/obj/item/implant/I = new path(H)
I.implant(H)
for(var/path in cybernetic_implants)
var/obj/item/organ/internal/O = new path(H)
O.insert(H)
post_equip(H, visualsOnly)
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -35,10 +35,10 @@
/datum/recipe
var/list/reagents // example: = list("berryjuice" = 5) // do not list same reagent twice
var/list/items // example: =list(/obj/item/weapon/crowbar, /obj/item/weapon/welder) // place /foo/bar before /foo
var/result //example: = /obj/item/weapon/reagent_containers/food/snacks/donut
var/list/items // example: =list(/obj/item/crowbar, /obj/item/welder) // place /foo/bar before /foo
var/result //example: = /obj/item/reagent_containers/food/snacks/donut
var/time = 100 // 1/10 part of second
var/byproduct // example: = /obj/item/weapon/kitchen/mould // byproduct to return, such as a mould or trash
var/byproduct // example: = /obj/item/kitchen/mould // byproduct to return, such as a mould or trash
/datum/recipe/proc/check_reagents(datum/reagents/avail_reagents) //1=precisely, 0=insufficiently, -1=superfluous
. = 1
+7 -7
View File
@@ -140,13 +140,13 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
var/obj/effect/proc_holder/spell/noclothes/clothes_spell = locate() in (user.mob_spell_list | (user.mind ? user.mind.spell_list : list()))
if((ishuman(user) && clothes_req) && !istype(clothes_spell))//clothes check
var/mob/living/carbon/human/H = user
if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit/wizard))
if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit/wizard) && !istype(H.wear_suit, /obj/item/clothing/suit/space/eva/plasmaman/wizard))
to_chat(user, "<span class='notice'>I don't feel strong enough without my robe.</span>")
return 0
if(!istype(H.shoes, /obj/item/clothing/shoes/sandal))
to_chat(user, "<span class='notice'>I don't feel strong enough without my sandals.</span>")
return 0
if(!istype(H.head, /obj/item/clothing/head/wizard) && !istype(H.head, /obj/item/clothing/head/helmet/space/hardsuit/wizard))
if(!istype(H.head, /obj/item/clothing/head/wizard) && !istype(H.head, /obj/item/clothing/head/helmet/space/hardsuit/wizard) && !istype(H.wear_suit, /obj/item/clothing/head/helmet/space/eva/plasmaman/wizard))
to_chat(user, "<span class='notice'>I don't feel strong enough without my hat.</span>")
return 0
else if(!ishuman(user))
@@ -218,7 +218,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
before_cast(targets)
invocation()
if(user && user.ckey)
user.create_attack_log("<font color='red'>[user.real_name] ([user.ckey]) cast the spell [name].</font>")
user.create_attack_log("<font color='red'>[key_name(user)] cast the spell [name].</font>")
spawn(0)
if(charge_type == "recharge" && recharge)
start_recharge()
@@ -258,20 +258,20 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
if(istype(target,/mob/living) && message)
to_chat(target, text("[message]"))
if(sparks_spread)
var/datum/effect/system/spark_spread/sparks = new /datum/effect/system/spark_spread()
var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread()
sparks.set_up(sparks_amt, 0, location) //no idea what the 0 is
sparks.start()
if(smoke_spread)
if(smoke_spread == 1)
var/datum/effect/system/harmless_smoke_spread/smoke = new /datum/effect/system/harmless_smoke_spread()
var/datum/effect_system/smoke_spread/smoke = new
smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is
smoke.start()
else if(smoke_spread == 2)
var/datum/effect/system/bad_smoke_spread/smoke = new /datum/effect/system/bad_smoke_spread()
var/datum/effect_system/smoke_spread/bad/smoke = new
smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is
smoke.start()
else if(smoke_spread == 3)
var/datum/effect/system/sleep_smoke_spread/smoke = new /datum/effect/system/sleep_smoke_spread()
var/datum/effect_system/smoke_spread/sleeping/smoke = new
smoke.set_up(smoke_amt, 0, location) // same here
smoke.start()
+11 -11
View File
@@ -33,9 +33,9 @@
charged_item = M
break
for(var/obj/item in hand_items)
if(istype(item, /obj/item/weapon/spellbook))
if(istype(item, /obj/item/weapon/spellbook/oneuse))
var/obj/item/weapon/spellbook/oneuse/I = item
if(istype(item, /obj/item/spellbook))
if(istype(item, /obj/item/spellbook/oneuse))
var/obj/item/spellbook/oneuse/I = item
if(prob(80))
L.visible_message("<span class='warning'>[I] catches fire!</span>")
qdel(I)
@@ -47,21 +47,21 @@
to_chat(L, "<span class='caution'>Glowing red letters appear on the front cover...</span>")
to_chat(L, "<span class='warning'>[pick("NICE TRY BUT NO!","CLEVER BUT NOT CLEVER ENOUGH!", "SUCH FLAGRANT CHEESING IS WHY WE ACCEPTED YOUR APPLICATION!", "CUTE!", "YOU DIDN'T THINK IT'D BE THAT EASY, DID YOU?")]</span>")
burnt_out = 1
else if(istype(item, /obj/item/weapon/gun/magic))
var/obj/item/weapon/gun/magic/I = item
else if(istype(item, /obj/item/gun/magic))
var/obj/item/gun/magic/I = item
if(prob(80) && !I.can_charge)
I.max_charges--
if(I.max_charges <= 0)
I.max_charges = 0
burnt_out = 1
I.charges = I.max_charges
if(istype(item,/obj/item/weapon/gun/magic/wand) && I.max_charges != 0)
var/obj/item/weapon/gun/magic/W = item
if(istype(item,/obj/item/gun/magic/wand) && I.max_charges != 0)
var/obj/item/gun/magic/W = item
W.icon_state = initial(W.icon_state)
charged_item = I
break
else if(istype(item, /obj/item/weapon/stock_parts/cell/))
var/obj/item/weapon/stock_parts/cell/C = item
else if(istype(item, /obj/item/stock_parts/cell/))
var/obj/item/stock_parts/cell/C = item
if(!C.self_recharge)
if(prob(80))
C.maxcharge -= 200
@@ -74,8 +74,8 @@
else if(item.contents)
var/obj/I = null
for(I in item.contents)
if(istype(I, /obj/item/weapon/stock_parts/cell/))
var/obj/item/weapon/stock_parts/cell/C = I
if(istype(I, /obj/item/stock_parts/cell/))
var/obj/item/stock_parts/cell/C = I
if(!C.self_recharge)
if(prob(80))
C.maxcharge -= 200
+1 -1
View File
@@ -1,7 +1,7 @@
/obj/effect/proc_holder/spell/targeted/touch/cluwne
name = "Curse of the Cluwne"
desc = "Turns the target into a fat and cursed monstrosity of a clown."
hand_path = /obj/item/weapon/melee/touch_attack/cluwne
hand_path = /obj/item/melee/touch_attack/cluwne
school = "transmutation"
+7 -3
View File
@@ -60,7 +60,7 @@
invocation_type = "none"
range = 0
summon_type = list(/obj/item/device/soulstone)
summon_type = list(/obj/item/soulstone)
/obj/effect/proc_holder/spell/aoe_turf/conjure/pylon
name = "Cult Pylon"
@@ -94,7 +94,7 @@
/obj/effect/forcefield/cult
desc = "That eerie looking obstacle seems to have been pulled from another dimension through sheer force"
name = "eldritch wall"
icon = 'icons/effects/effects.dmi'
icon = 'icons/effects/cult_effects.dmi'
icon_state = "m_shield_cult"
light_color = LIGHT_COLOR_PURE_RED
@@ -110,10 +110,14 @@
invocation_type = "none"
range = -1
include_user = 1
phaseshift = 1
jaunt_duration = 50 //in deciseconds
centcom_cancast = 0 //Stop people from getting to centcom
jaunt_in_time = 12
jaunt_in_type = /obj/effect/temp_visual/dir_setting/wraith
jaunt_out_type = /obj/effect/temp_visual/dir_setting/wraith/out
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/jaunt_steam(mobloc)
return
/obj/effect/proc_holder/spell/targeted/projectile/magic_missile/lesser
name = "Lesser Magic Missile"
+54 -74
View File
@@ -13,109 +13,89 @@
nonabstract_req = 1
centcom_cancast = 0 //Prevent people from getting to centcom
var phaseshift = 0
var/jaunt_duration = 50 //in deciseconds
var/jaunt_in_time = 5
var/jaunt_in_type = /obj/effect/temp_visual/wizard
var/jaunt_out_type = /obj/effect/temp_visual/wizard/out
action_icon_state = "jaunt"
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets, mob/user = usr) //magnets, so mostly hardcoded
playsound(get_turf(user), 'sound/magic/Ethereal_Enter.ogg', 50, 1, -1)
for(var/mob/living/target in targets)
if(!target.can_safely_leave_loc()) // No more brainmobs hopping out of their brains
to_chat(target, "<span class='warning'>You are somehow too bound to your current location to abandon it.</span>")
continue
spawn(0)
INVOKE_ASYNC(src, .proc/do_jaunt, target)
if(target.buckled)
var/obj/structure/stool/bed/buckled_to = target.buckled.
buckled_to.unbuckle_mob()
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/do_jaunt(mob/living/target)
target.notransform = 1
var/turf/mobloc = get_turf(target)
var/obj/effect/dummy/spell_jaunt/holder = new /obj/effect/dummy/spell_jaunt(mobloc)
new jaunt_out_type(mobloc, target.dir)
target.ExtinguishMob()
target.forceMove(holder)
target.reset_perspective(holder)
target.notransform = 0 //mob is safely inside holder now, no need for protection.
jaunt_steam(mobloc)
var/mobloc = get_turf(target.loc)
var/obj/effect/dummy/spell_jaunt/holder = new /obj/effect/dummy/spell_jaunt( mobloc )
var/atom/movable/overlay/animation = new /atom/movable/overlay( mobloc )
animation.name = "water"
animation.density = 0
animation.anchored = 1
animation.icon = 'icons/mob/mob.dmi'
animation.icon_state = "liquify"
animation.layer = 5
animation.master = holder
target.ExtinguishMob()
if(target.buckled)
target.buckled.unbuckle_mob()
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)
if(!target.Move(mobloc))
for(var/direction in list(1,2,4,8,5,6,9,10))
var/turf/T = get_step(mobloc, direction)
if(T)
if(target.Move(T))
break
target.canmove = 1
target.client.eye = target
qdel(animation)
qdel(holder)
else
flick("liquify",animation)
target.loc = holder
target.client.eye = holder
var/datum/effect/system/steam_spread/steam = new /datum/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)
if(!target.Move(mobloc))
for(var/direction in list(1,2,4,8,5,6,9,10))
var/turf/T = get_step(mobloc, direction)
if(T)
if(target.Move(T))
break
target.canmove = 1
target.client.eye = target
qdel(animation)
qdel(holder)
sleep(jaunt_duration)
if(target.loc != holder) //mob warped out of the warp
qdel(holder)
return
mobloc = get_turf(target.loc)
jaunt_steam(mobloc)
target.canmove = 0
holder.reappearing = 1
playsound(get_turf(target), 'sound/magic/Ethereal_Exit.ogg', 50, 1, -1)
sleep(25 - jaunt_in_time)
new jaunt_in_type(mobloc, holder.dir)
target.setDir(holder.dir)
sleep(jaunt_in_time)
qdel(holder)
if(!QDELETED(target))
if(mobloc.density)
for(var/direction in alldirs)
var/turf/T = get_step(mobloc, direction)
if(T)
if(target.Move(T))
break
target.canmove = 1
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/jaunt_steam(mobloc)
var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread()
steam.set_up(10, 0, mobloc)
steam.start()
/obj/effect/dummy/spell_jaunt
name = "water"
icon = 'icons/effects/effects.dmi'
icon_state = "nothing"
var/canmove = 1
var/reappearing = 0
var/movedelay = 0
var/movespeed = 2
density = 0
anchored = 1
invisibility = 60
burn_state = LAVA_PROOF
/obj/effect/dummy/spell_jaunt/Destroy()
// Eject contents if deleted somehow
for(var/atom/movable/AM in src)
AM.loc = get_turf(src)
AM.forceMove(get_turf(src))
return ..()
/obj/effect/dummy/spell_jaunt/relaymove(var/mob/user, direction)
if(!src.canmove) return
/obj/effect/dummy/spell_jaunt/relaymove(mob/user, direction)
if((movedelay > world.time) || reappearing || !direction)
return
var/turf/newLoc = get_step(src,direction)
setDir(direction)
if(!(newLoc.flags & NOJAUNT))
loc = newLoc
forceMove(newLoc)
else
to_chat(user, "<span class='warning'>Some strange aura is blocking the way!</span>")
src.canmove = 0
spawn(2) src.canmove = 1
movedelay = world.time + movespeed
/obj/effect/dummy/spell_jaunt/ex_act(blah)
return
+1 -1
View File
@@ -1,7 +1,7 @@
/obj/effect/proc_holder/spell/targeted/touch/fake_disintegrate
name = "Disintegrate"
desc = "This spell charges your hand with vile energy that can be used to violently explode victims."
hand_path = "/obj/item/weapon/melee/touch_attack/fake_disintegrate"
hand_path = "/obj/item/melee/touch_attack/fake_disintegrate"
school = "evocation"
charge_max = 600
+1 -1
View File
@@ -18,5 +18,5 @@
C.drop_item()
C.swap_hand()
C.drop_item()
var/obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted/GUN = new
var/obj/item/gun/projectile/shotgun/boltaction/enchanted/GUN = new
C.put_in_hands(GUN)
+11 -7
View File
@@ -28,7 +28,7 @@
config.continuous_rounds = 0
return ..()
/obj/effect/proc_holder/spell/targeted/lichdom/cast(list/targets,mob/user = usr)
/obj/effect/proc_holder/spell/targeted/lichdom/cast(list/targets,mob/user = usr)
if(!config.continuous_rounds)
existence_stops_round_end = 1
config.continuous_rounds = 1
@@ -49,7 +49,7 @@
charge_counter = charge_max
return
if(!marked_item || qdeleted(marked_item)) //Wait nevermind
if(!marked_item || QDELETED(marked_item)) //Wait nevermind
to_chat(M, "<span class='warning'>Your phylactery is gone!</span>")
return
@@ -66,11 +66,6 @@
var/mob/living/carbon/human/lich = new /mob/living/carbon/human(item_turf)
lich.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(lich), slot_shoes)
lich.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(lich), slot_w_uniform)
lich.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(lich), slot_wear_suit)
lich.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(lich), slot_head)
lich.real_name = M.mind.name
M.mind.transfer_to(lich)
lich.set_species("Skeleton")
@@ -81,6 +76,11 @@
current_body = lich
lich.Weaken(10+10*resurrections)
++resurrections
lich.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(lich), slot_shoes)
lich.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(lich), slot_w_uniform)
lich.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(lich), slot_wear_suit)
lich.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(lich), slot_head)
if(old_body && old_body.loc)
if(iscarbon(old_body))
var/mob/living/carbon/C = old_body
@@ -125,5 +125,9 @@
H.set_species("Skeleton")
H.unEquip(H.wear_suit)
H.unEquip(H.head)
H.unEquip(H.shoes)
H.unEquip(H.head)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(H), slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(H), slot_w_uniform)
+5 -8
View File
@@ -20,15 +20,8 @@ Make sure spells that are removed from spell_list are actually removed and delet
Also, you never added distance checking after target is selected. I've went ahead and did that.
*/
/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets, mob/user = usr, distanceoverride)
if(!targets.len)
to_chat(user, "No mind found.")
return
if(targets.len > 1)
to_chat(user, "Too many minds! You're not a hive damnit!")//Whaa...aat?
return
var/mob/living/target = targets[1]
var/mob/living/target = targets[range]
if(!(target in oview(range)) && !distanceoverride)//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it.
to_chat(user, "They are too far away!")
@@ -50,6 +43,10 @@ Also, you never added distance checking after target is selected. I've went ahea
to_chat(user, "Their mind is resisting your spell.")
return
if(istype(target, /mob/living/silicon))
to_chat(user, "You feel this enslaved being is just as dead as its cold, hard exoskeleton.")
return
var/mob/living/victim = target//The target of the spell whos body will be transferred to.
var/mob/caster = user//The wizard/whomever doing the body transferring.
+1 -1
View File
@@ -14,7 +14,7 @@
/obj/effect/proc_holder/spell/targeted/rathens/cast(list/targets, mob/user = usr)
playsound(get_turf(user), 'sound/goonstation/effects/superfart.ogg', 25, 1)
for(var/mob/living/carbon/human/H in targets)
var/datum/effect/system/harmless_smoke_spread/s = new /datum/effect/system/harmless_smoke_spread
var/datum/effect_system/smoke_spread/s = new
s.set_up(5, 0, H)
s.start()
var/obj/item/organ/internal/appendix/A = H.get_int_organ(/obj/item/organ/internal/appendix)
+1 -1
View File
@@ -76,7 +76,7 @@
var/obj/item/brain/B = new /obj/item/brain(target.loc)
B.transfer_identity(C)
C.death()
add_logs(target, C, "magically debrained", addition="INTENT: [uppertext(target.a_intent)]")*/
add_attack_logs(target, C, "Magically debrained INTENT: [uppertext(target.a_intent)]")*/
if(C.stomach_contents && item_to_retrive in C.stomach_contents)
C.stomach_contents -= item_to_retrive
for(var/X in C.bodyparts)
+4 -4
View File
@@ -1,6 +1,6 @@
/obj/effect/proc_holder/spell/targeted/touch
var/hand_path = /obj/item/weapon/melee/touch_attack
var/obj/item/weapon/melee/touch_attack/attached_hand = null
var/hand_path = /obj/item/melee/touch_attack
var/obj/item/melee/touch_attack/attached_hand = null
invocation_type = "none" //you scream on connecting, not summoning
include_user = 1
range = -1
@@ -47,7 +47,7 @@
/obj/effect/proc_holder/spell/targeted/touch/disintegrate
name = "Disintegrate"
desc = "This spell charges your hand with vile energy that can be used to violently explode victims."
hand_path = /obj/item/weapon/melee/touch_attack/disintegrate
hand_path = /obj/item/melee/touch_attack/disintegrate
school = "evocation"
charge_max = 600
@@ -59,7 +59,7 @@
/obj/effect/proc_holder/spell/targeted/touch/flesh_to_stone
name = "Flesh to Stone"
desc = "This spell charges your hand with the power to turn victims into inert statues for a long period of time."
hand_path = /obj/item/weapon/melee/touch_attack/fleshtostone
hand_path = /obj/item/melee/touch_attack/fleshtostone
school = "transmutation"
charge_max = 600
+13 -14
View File
@@ -25,7 +25,7 @@
proj_trail_icon_state = "magicmd"
action_icon_state = "magicm"
sound = 'sound/magic/MAGIC_MISSILE.ogg'
/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile
@@ -97,7 +97,7 @@
emp_heavy = 6
emp_light = 10
sound = 'sound/magic/Disable_Tech.ogg'
/obj/effect/proc_holder/spell/targeted/turf_teleport/blink
@@ -123,7 +123,7 @@
centcom_cancast = 0 //prevent people from getting to centcom
action_icon_state = "blink"
sound1 = 'sound/magic/blink.ogg'
sound2 = 'sound/magic/blink.ogg'
@@ -144,7 +144,7 @@
smoke_amt = 5
action_icon_state = "spell_teleport"
sound1 = 'sound/magic/Teleport_diss.ogg'
sound2 = 'sound/magic/Teleport_app.ogg'
@@ -194,7 +194,7 @@
summon_type = list(/mob/living/simple_animal/hostile/carp)
cast_sound = 'sound/magic/Summon_Karp.ogg'
/obj/effect/proc_holder/spell/aoe_turf/conjure/construct
name = "Artificer"
desc = "This spell conjures a construct which may be controlled by Shades"
@@ -334,7 +334,7 @@
cooldown_min = 150
selection_type = "view"
var/maxthrow = 5
var/sparkle_path = /obj/effect/temp_visual/gravpush
action_icon_state = "repulse"
sound = 'sound/magic/Repulse.ogg'
@@ -347,16 +347,13 @@
for(var/atom/movable/AM in T)
thrownatoms += AM
for(var/atom/movable/AM in thrownatoms)
if(AM == user || AM.anchored) continue
for(var/am in thrownatoms)
var/atom/movable/AM = am
if(AM == user || AM.anchored)
continue
var/obj/effect/overlay/targeteffect = new /obj/effect/overlay{icon='icons/effects/effects.dmi'; icon_state="shieldsparkles"; mouse_opacity=0; density = 0}()
AM.overlays += targeteffect
throwtarget = get_edge_target_turf(user, get_dir(user, get_step_away(AM, user)))
distfromcaster = get_dist(user, AM)
spawn(10)
AM.overlays -= targeteffect
qdel(targeteffect)
if(distfromcaster == 0)
if(istype(AM, /mob/living))
var/mob/living/M = AM
@@ -364,11 +361,13 @@
M.adjustBruteLoss(5)
to_chat(M, "<span class='userdanger'>You're slammed into the floor by a mystical force!</span>")
else
new sparkle_path(get_turf(AM), get_dir(user, AM)) //created sparkles will disappear on their own
if(istype(AM, /mob/living))
var/mob/living/M = AM
M.Weaken(2)
to_chat(M, "<span class='userdanger'>You're thrown back by a mystical force!</span>")
spawn(0) AM.throw_at(throwtarget, ((Clamp((maxthrow - (Clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1)//So stuff gets tossed around at the same time.
spawn(0)
AM.throw_at(throwtarget, ((Clamp((maxthrow - (Clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1)//So stuff gets tossed around at the same time.
/obj/effect/proc_holder/spell/targeted/sacred_flame
name = "Sacred Flame"
+16 -19
View File
@@ -5,8 +5,8 @@
var/target
/obj/effect/statclick/New(ntarget, text)
name = text
target = ntarget
name = text
/obj/effect/statclick/proc/update(text)
name = text
@@ -15,25 +15,22 @@
/obj/effect/statclick/debug
var/class
/obj/effect/statclick/debug/New(ntarget)
name = "Initializing..."
target = ntarget
if(istype(target, /datum/controller/process))
class = "process"
else if(istype(target, /datum/controller/processScheduler))
class = "scheduler"
else if(istype(target, /datum/controller))
class = "controller"
else if(istype(target, /datum))
class = "datum"
else
class = "unknown"
// This bit is called when clicked in the stat panel
/obj/effect/statclick/debug/Click()
if(!is_admin(usr))
if(!is_admin(usr) || !target)
return
if(!class)
if(istype(target, /datum/controller/process))
class = "process"
else if(istype(target, /datum/controller/processScheduler))
class = "scheduler"
if(istype(target, /datum/controller/subsystem))
class = "subsystem"
else if(istype(target, /datum/controller))
class = "controller"
else if(istype(target, /datum))
class = "datum"
else
class = "unknown"
usr.client.debug_variables(target)
message_admins("Admin [key_name_admin(usr)] is debugging the [target] [class].")
message_admins("Admin [key_name_admin(usr)] is debugging the [target] [class].")
+41
View File
@@ -0,0 +1,41 @@
//Largely beneficial effects go here, even if they have drawbacks. An example is provided in Shadow Mend.
/datum/status_effect/shadow_mend
id = "shadow_mend"
duration = 30
alert_type = /obj/screen/alert/status_effect/shadow_mend
/obj/screen/alert/status_effect/shadow_mend
name = "Shadow Mend"
desc = "Shadowy energies wrap around your wounds, sealing them at a price. After healing, you will slowly lose health every three seconds for thirty seconds."
icon_state = "shadow_mend"
/datum/status_effect/shadow_mend/on_apply()
owner.visible_message("<span class='notice'>Violet light wraps around [owner]'s body!</span>", "<span class='notice'>Violet light wraps around your body!</span>")
playsound(owner, 'sound/magic/teleport_app.ogg', 50, 1)
return ..()
/datum/status_effect/shadow_mend/tick()
owner.adjustBruteLoss(-15)
owner.adjustFireLoss(-15)
/datum/status_effect/shadow_mend/on_remove()
owner.visible_message("<span class='warning'>The violet light around [owner] glows black!</span>", "<span class='warning'>The tendrils around you cinch tightly and reap their toll...</span>")
playsound(owner, 'sound/magic/teleport_diss.ogg', 50, 1)
owner.apply_status_effect(STATUS_EFFECT_VOID_PRICE)
/datum/status_effect/void_price
id = "void_price"
duration = 300
tick_interval = 30
alert_type = /obj/screen/alert/status_effect/void_price
/obj/screen/alert/status_effect/void_price
name = "Void Price"
desc = "Black tendrils cinch tightly against you, digging wicked barbs into your flesh."
icon_state = "shadow_mend"
/datum/status_effect/void_price/tick()
playsound(owner, 'sound/weapons/bite.ogg', 50, 1)
owner.adjustBruteLoss(3)
+10
View File
@@ -0,0 +1,10 @@
//OTHER DEBUFFS
/datum/status_effect/cultghost //is a cult ghost and can't use manifest runes
id = "cult_ghost"
duration = -1
alert_type = null
/datum/status_effect/cultghost/tick()
if(owner.reagents)
owner.reagents.del_reagent("holywater") //can't be deconverted
+9
View File
@@ -0,0 +1,9 @@
//entirely neutral or internal status effects go here
/datum/status_effect/high_five
id = "high_five"
duration = 25
alert_type = null
/datum/status_effect/high_five/on_timeout()
owner.visible_message("[owner] was left hanging....")
+120
View File
@@ -0,0 +1,120 @@
//Status effects are used to apply temporary or permanent effects to mobs. Mobs are aware of their status effects at all times.
//This file contains their code, plus code for applying and removing them.
//When making a new status effect, add a define to status_effects.dm in __DEFINES for ease of use!
/datum/status_effect
var/id = "effect" //Used for screen alerts.
var/duration = -1 //How long the status effect lasts in DECISECONDS. Enter -1 for an effect that never ends unless removed through some means.
var/tick_interval = 10 //How many deciseconds between ticks, approximately. Leave at 10 for every second.
var/mob/living/owner //The mob affected by the status effect.
var/status_type = STATUS_EFFECT_UNIQUE //How many of the effect can be on one mob, and what happens when you try to add another
var/on_remove_on_mob_delete = FALSE //if we call on_remove() when the mob is deleted
var/examine_text //If defined, this text will appear when the mob is examined - to use he, she etc. use "SUBJECTPRONOUN" and replace it in the examines themselves
var/alert_type = /obj/screen/alert/status_effect //the alert thrown by the status effect, contains name and description
var/obj/screen/alert/status_effect/linked_alert = null //the alert itself, if it exists
/datum/status_effect/New(list/arguments)
on_creation(arglist(arguments))
/datum/status_effect/proc/on_creation(mob/living/new_owner, ...)
if(new_owner)
owner = new_owner
if(owner)
LAZYADD(owner.status_effects, src)
if(!owner || !on_apply())
qdel(src)
return
if(duration != -1)
duration = world.time + duration
tick_interval = world.time + tick_interval
if(alert_type)
var/obj/screen/alert/status_effect/A = owner.throw_alert(id, alert_type)
A.attached_effect = src //so the alert can reference us, if it needs to
linked_alert = A //so we can reference the alert, if we need to
fast_processing.Add(src)
return TRUE
/datum/status_effect/Destroy()
fast_processing.Remove(src)
if(owner)
owner.clear_alert(id)
LAZYREMOVE(owner.status_effects, src)
on_remove()
owner = null
return ..()
/datum/status_effect/proc/process()
if(!owner)
qdel(src)
return
if(tick_interval < world.time)
tick()
tick_interval = world.time + initial(tick_interval)
if(duration != -1 && duration < world.time)
on_timeout()
qdel(src)
/datum/status_effect/proc/on_apply() //Called whenever the buff is applied; returning FALSE will cause it to autoremove itself.
return TRUE
/datum/status_effect/proc/tick() //Called every tick.
/datum/status_effect/proc/on_timeout()//called when a buff times out
/datum/status_effect/proc/on_remove() //Called whenever the buff expires or is removed; do note that at the point this is called, it is out of the owner's status_effects but owner is not yet null
/datum/status_effect/proc/be_replaced() //Called instead of on_remove when a status effect is replaced by itself or when a status effect with on_remove_on_mob_delete = FALSE has its mob deleted
owner.clear_alert(id)
LAZYREMOVE(owner.status_effects, src)
owner = null
qdel(src)
////////////////
// ALERT HOOK //
////////////////
/obj/screen/alert/status_effect
name = "Curse of Mundanity"
desc = "You don't feel any different..."
var/datum/status_effect/attached_effect
//////////////////
// HELPER PROCS //
//////////////////
/mob/living/proc/apply_status_effect(effect, ...) //applies a given status effect to this mob, returning the effect if it was successful
. = FALSE
var/datum/status_effect/S1 = effect
LAZYINITLIST(status_effects)
for(var/datum/status_effect/S in status_effects)
if(S.id == initial(S1.id) && S.status_type)
if(S.status_type == STATUS_EFFECT_REPLACE)
S.be_replaced()
else
return
var/list/arguments = args.Copy()
arguments[1] = src
S1 = new effect(arguments)
. = S1
/mob/living/proc/remove_status_effect(effect) //removes all of a given status effect from this mob, returning TRUE if at least one was removed
. = FALSE
if(status_effects)
var/datum/status_effect/S1 = effect
for(var/datum/status_effect/S in status_effects)
if(initial(S1.id) == S.id)
qdel(S)
. = TRUE
/mob/living/proc/has_status_effect(effect) //returns the effect if the mob calling the proc owns the given status effect
. = FALSE
if(status_effects)
var/datum/status_effect/S1 = effect
for(var/datum/status_effect/S in status_effects)
if(initial(S1.id) == S.id)
return S
/mob/living/proc/has_status_effect_list(effect) //returns a list of effects with matching IDs that the mod owns; use for effects there can be multiple of
. = list()
if(status_effects)
var/datum/status_effect/S1 = effect
for(var/datum/status_effect/S in status_effects)
if(initial(S1.id) == S.id)
. += S
+398 -389
View File
File diff suppressed because it is too large Load Diff
+156 -116
View File
@@ -56,7 +56,7 @@ var/list/uplink_items = list()
var/surplus = 100 //Chance of being included in the surplus crate (when pick() selects it)
var/hijack_only = FALSE //can this item be purchased only during hijackings?
/datum/uplink_item/proc/spawn_item(var/turf/loc, var/obj/item/device/uplink/U)
/datum/uplink_item/proc/spawn_item(var/turf/loc, var/obj/item/uplink/U)
if(hijack_only)
if(!(locate(/datum/objective/hijack) in usr.mind.objectives))
to_chat(usr, "<span class='warning'>The Syndicate lacks resources to provide you with this item.</span>")
@@ -74,7 +74,7 @@ var/list/uplink_items = list()
desc = replacetext(initial(temp.desc), "\n", "<br>")
return desc
/datum/uplink_item/proc/buy(var/obj/item/device/uplink/hidden/U, var/mob/user)
/datum/uplink_item/proc/buy(var/obj/item/uplink/hidden/U, var/mob/user)
..()
if(!istype(U))
@@ -99,7 +99,7 @@ var/list/uplink_items = list()
var/mob/living/carbon/human/A = user
A.put_in_any_hand_if_possible(I)
if(istype(I,/obj/item/weapon/storage/box/) && I.contents.len>0)
if(istype(I,/obj/item/storage/box/) && I.contents.len>0)
for(var/atom/o in I)
U.purchase_log += "<BIG>[bicon(o)]</BIG>"
else
@@ -124,7 +124,7 @@ var/list/uplink_items = list()
name = "Banana Grenade"
desc = "A grenade that explodes into HONK! brand banana peels that are genetically modified to be extra slippery and extrude caustic acid when stepped on"
reference = "BG"
item = /obj/item/weapon/grenade/clown_grenade
item = /obj/item/grenade/clown_grenade
cost = 5
job = list("Clown")
@@ -133,7 +133,7 @@ var/list/uplink_items = list()
name = "Cane Shotgun + Assassination Darts"
desc = "A specialized, one shell shotgun with a built-in cloaking device to mimic a cane. The shotgun is capable of hiding it's contents and the pin alongside being supressed. Comes with 6 special darts and a preloaded shrapnel round."
reference = "MCS"
item = /obj/item/weapon/storage/box/syndie_kit/caneshotgun
item = /obj/item/storage/box/syndie_kit/caneshotgun
cost = 10
job = list("Mime")
@@ -142,7 +142,7 @@ var/list/uplink_items = list()
name = "Chef Excellence's Special Sauce"
desc = "A custom made sauce made from the toxin glands of 1000 space carp, if somebody ingests enough they'll be dead in 3 minutes or less guaranteed."
reference = "CESS"
item = /obj/item/weapon/reagent_containers/food/condiment/syndisauce
item = /obj/item/reagent_containers/food/condiment/syndisauce
cost = 2
job = list("Chef")
@@ -150,7 +150,7 @@ var/list/uplink_items = list()
name = "Meat Cleaver"
desc = "A mean looking meat cleaver that does damage comparable to an Energy Sword but with the added benefit of chopping your victim into hunks of meat after they've died and the chance to stun when thrown."
reference = "MC"
item = /obj/item/weapon/kitchen/knife/butcher/meatcleaver
item = /obj/item/kitchen/knife/butcher/meatcleaver
cost = 10
job = list("Chef")
@@ -158,7 +158,7 @@ var/list/uplink_items = list()
name = "Syndicate Donk Pockets"
desc = "A box of highly specialized Donk pockets with a number of regenerative and stimulating chemicals inside of them; the box comes equipped with a self-heating mechanism."
reference = "SDP"
item = /obj/item/weapon/storage/box/syndidonkpockets
item = /obj/item/storage/box/syndidonkpockets
cost = 2
job = list("Chef")
@@ -176,7 +176,7 @@ var/list/uplink_items = list()
name = "Missionary Starter Kit"
desc = "A box containing a missionary staff, missionary robes, and bible. The robes and staff can be linked to allow you to convert victims at range for a short time to do your bidding. The bible is for bible stuff."
reference = "MK"
item = /obj/item/weapon/storage/box/syndie_kit/missionary_set
item = /obj/item/storage/box/syndie_kit/missionary_set
cost = 15
job = list("Chaplain")
@@ -184,7 +184,7 @@ var/list/uplink_items = list()
name = "Artistic Toolbox"
desc = "An accursed toolbox that grants its followers extreme power at the cost of requiring repeated sacrifices to it. If sacrifices are not provided, it will turn on its follower."
reference = "HGAT"
item = /obj/item/weapon/storage/toolbox/green/memetic
item = /obj/item/storage/toolbox/green/memetic
cost = 20
job = list("Chaplain")
surplus = 0 //No lucky chances from the crate; if you get this, this is ALL you're getting
@@ -196,7 +196,7 @@ var/list/uplink_items = list()
name = "Proximity Mine"
desc = "An Anti-Personnel proximity mine cleverly disguised as a wet floor caution sign that is triggered by running past it, activate it to start the 15 second timer and activate again to disarm."
reference = "PM"
item = /obj/item/weapon/caution/proximity_sign
item = /obj/item/caution/proximity_sign
cost = 4
job = list("Janitor")
surplus = 0
@@ -207,14 +207,14 @@ var/list/uplink_items = list()
name = "Radiation Laser"
desc = "A radiation laser concealed inside of a Health Analyser. After a moderate delay, causes temporary collapse and radiation. Has adjustable controls, but will not function as a regular health analyser, only appears like one. May not function correctly on radiation resistant humanoids!"
reference = "RL"
item = /obj/item/device/rad_laser
item = /obj/item/rad_laser
cost = 5
job = list("Chief Medical Officer", "Medical Doctor", "Geneticist", "Psychiatrist", "Chemist", "Paramedic", "Coroner", "Virologist")
/datum/uplink_item/dangerous/cat_grenade
name = "Feral Cat Delivery Grenade"
desc = "The feral cat delivery grenade contains 8 dehydrated feral cats in a similar manner to dehydrated monkeys, which, upon detonation, will be rehydrated by a small reservoir of water contained within the grenade. These cats will then attack anything in sight."
item = /obj/item/weapon/grenade/spawnergrenade/feral_cats
item = /obj/item/grenade/spawnergrenade/feral_cats
reference = "CCLG"
cost = 4
job = list("Psychiatrist")//why? Becuase its funny that a person in charge of your mental wellbeing has a cat granade..
@@ -235,7 +235,7 @@ var/list/uplink_items = list()
name = "Boozey Shotgun Shells"
desc = "A box containing 6 shotgun shells that simulate the effects of extreme drunkenness on the target, more effective for each type of alcohol in the target's system."
reference = "BSS"
item = /obj/item/weapon/storage/box/syndie_kit/boolets
item = /obj/item/storage/box/syndie_kit/boolets
cost = 3
job = list("Bartender")
@@ -245,7 +245,7 @@ var/list/uplink_items = list()
name = "Safety Scissors"
desc = "A pair of scissors that are anything but what their name implies; can easily cut right into someone's throat."
reference = "CTS"
item = /obj/item/weapon/scissors/safety
item = /obj/item/scissors/safety
cost = 5
job = list("Barber")
@@ -255,7 +255,7 @@ var/list/uplink_items = list()
name = "Briefcase Full of Bees"
desc = "A seemingly innocent briefcase full of not-so-innocent Syndicate-bred bees. Inject the case with blood to train the bees to ignore the donor(s). It also wirelessly taps into station intercomms to broadcast a message of TERROR."
reference = "BEE"
item = /obj/item/weapon/bee_briefcase
item = /obj/item/bee_briefcase
cost = 10
job = list("Botanist")
@@ -275,7 +275,7 @@ var/list/uplink_items = list()
name = "Telegun"
desc = "An extremely high-tech energy gun that utilizes bluespace technology to teleport away living targets. Select the target beacon on the telegun itself; projectiles will send targets to the beacon locked onto."
reference = "TG"
item = /obj/item/weapon/gun/energy/telegun
item = /obj/item/gun/energy/telegun
cost = 12
job = list("Research Director")
@@ -284,7 +284,7 @@ var/list/uplink_items = list()
name = "The E20"
desc = "A seemingly innocent die, those who are not afraid to roll for attack will find it's effects quite explosive. Has a four second timer."
reference = "ETW"
item = /obj/item/weapon/dice/d20/e20
item = /obj/item/dice/d20/e20
cost = 3
job = list("Librarian")
@@ -310,7 +310,7 @@ var/list/uplink_items = list()
name = "Energized Fire Axe"
desc = "A fire axe with a massive electrical charge built into it. It can release this charge on its first victim and will be rather plain after that."
reference = "EFA"
item = /obj/item/weapon/twohanded/energizedfireaxe
item = /obj/item/twohanded/energizedfireaxe
cost = 10
job = list("Life Support Specialist")
@@ -320,7 +320,7 @@ var/list/uplink_items = list()
name = "Stimulants"
desc = "A highly illegal compound contained within a compact auto-injector; when injected it makes the user extremely resistant to incapacitation and greatly enhances the body's ability to repair itself."
reference = "ST"
item = /obj/item/weapon/reagent_containers/hypospray/autoinjector/stimulants
item = /obj/item/reagent_containers/hypospray/autoinjector/stimulants
cost = 7
job = list("Scientist", "Research Director", "Geneticist", "Chief Medical Officer", "Medical Doctor", "Psychiatrist", "Chemist", "Paramedic", "Coroner", "Virologist")
@@ -330,7 +330,7 @@ var/list/uplink_items = list()
name = "Poison Bottle"
desc = "The Syndicate will ship a bottle containing 40 units of a randomly selected poison. The poison can range from highly irritating to incredibly lethal."
reference = "TPB"
item = /obj/item/weapon/reagent_containers/glass/bottle/traitor
item = /obj/item/reagent_containers/glass/bottle/traitor
cost = 2
job = list("Research Director", "Chief Medical Officer", "Medical Doctor", "Psychiatrist", "Chemist", "Paramedic", "Virologist", "Bartender", "Chef")
@@ -340,7 +340,7 @@ var/list/uplink_items = list()
name = "Poison Pen"
desc = "Cutting edge of deadly writing implements technology, this gadget will infuse any piece of paper with delayed contact poison."
reference = "PP"
item = /obj/item/weapon/pen/poison
item = /obj/item/pen/poison
cost = 2
excludefrom = list(/datum/game_mode/nuclear)
job = list("Head of Personnel", "Quartermaster", "Cargo Technician")
@@ -356,14 +356,14 @@ var/list/uplink_items = list()
name = "FK-69 Pistol"
reference = "SPI"
desc = "A small, easily concealable handgun that uses 10mm auto rounds in 8-round magazines and is compatible with suppressors."
item = /obj/item/weapon/gun/projectile/automatic/pistol
item = /obj/item/gun/projectile/automatic/pistol
cost = 4
/datum/uplink_item/dangerous/revolver
name = "Syndicate .357 Revolver"
reference = "SR"
desc = "A brutally simple syndicate revolver that fires .357 Magnum cartridges and has 7 chambers."
item = /obj/item/weapon/gun/projectile/revolver
item = /obj/item/gun/projectile/revolver
cost = 13
surplus = 50
@@ -371,7 +371,7 @@ var/list/uplink_items = list()
name = "C-20r Submachine Gun"
reference = "SMG"
desc = "A fully-loaded Scarborough Arms bullpup submachine gun that fires .45 rounds with a 20-round magazine and is compatible with suppressors."
item = /obj/item/weapon/gun/projectile/automatic/c20r
item = /obj/item/gun/projectile/automatic/c20r
cost = 14
gamemodes = list(/datum/game_mode/nuclear)
surplus = 40
@@ -380,7 +380,7 @@ var/list/uplink_items = list()
name = "M-90gl Carbine"
desc = "A fully-loaded three-round burst carbine that uses 30-round 5.56mm magazines with a togglable underslung 40mm grenade launcher."
reference = "AR"
item = /obj/item/weapon/gun/projectile/automatic/m90
item = /obj/item/gun/projectile/automatic/m90
cost = 18
gamemodes = list(/datum/game_mode/nuclear)
surplus = 50
@@ -389,7 +389,7 @@ var/list/uplink_items = list()
name = "L6 Squad Automatic Weapon"
desc = "A fully-loaded Aussec Armory belt-fed machine gun. This deadly weapon has a massive 50-round magazine of devastating 7.62x51mm ammunition."
reference = "LMG"
item = /obj/item/weapon/gun/projectile/automatic/l6_saw
item = /obj/item/gun/projectile/automatic/l6_saw
cost = 40
gamemodes = list(/datum/game_mode/nuclear)
surplus = 0
@@ -398,7 +398,7 @@ var/list/uplink_items = list()
name = "Sniper Rifle"
desc = "Ranged fury, Syndicate style. guaranteed to cause shock and awe or your TC back!"
reference = "SSR"
item = /obj/item/weapon/gun/projectile/automatic/sniper_rifle/syndicate
item = /obj/item/gun/projectile/automatic/sniper_rifle/syndicate
cost = 16
surplus = 25
gamemodes = list(/datum/game_mode/nuclear)
@@ -407,7 +407,7 @@ var/list/uplink_items = list()
name = "Energy Crossbow"
desc = "A miniature energy crossbow that is small enough both to fit into a pocket and to slip into a backpack unnoticed by observers. Fires bolts tipped with toxin, a poisonous substance that is the product of a living organism. Stuns enemies for a short period of time. Recharges automatically."
reference = "EC"
item = /obj/item/weapon/gun/energy/kinetic_accelerator/crossbow
item = /obj/item/gun/energy/kinetic_accelerator/crossbow
cost = 12
excludefrom = list(/datum/game_mode/nuclear)
surplus = 50
@@ -416,8 +416,8 @@ var/list/uplink_items = list()
name = "Flamethrower"
desc = "A flamethrower, fuelled by a portion of highly flammable bio-toxins stolen previously from Nanotrasen stations. Make a statement by roasting the filth in their own greed. Use with caution."
reference = "FT"
item = /obj/item/weapon/flamethrower/full/tank
cost = 11
item = /obj/item/flamethrower/full/tank
cost = 8
gamemodes = list(/datum/game_mode/nuclear)
surplus = 40
@@ -425,7 +425,7 @@ var/list/uplink_items = list()
name = "Energy Sword"
desc = "The energy sword is an edged weapon with a blade of pure energy. The sword is small enough to be pocketed when inactive. Activating it produces a loud, distinctive noise."
reference = "ES"
item = /obj/item/weapon/melee/energy/sword/saber
item = /obj/item/melee/energy/sword/saber
cost = 8
/datum/uplink_item/dangerous/powerfist
@@ -435,29 +435,29 @@ var/list/uplink_items = list()
Using a wrench on the piston valve will allow you to tweak the amount of gas used per punch to \
deal extra damage and hit targets further. Use a screwdriver to take out any attached tanks."
reference = "PF"
item = /obj/item/weapon/melee/powerfist
item = /obj/item/melee/powerfist
cost = 8
/datum/uplink_item/dangerous/chainsaw
name = "Chainsaw"
desc = "A high powered chainsaw for cutting up ...you know...."
reference = "CH"
item = /obj/item/weapon/twohanded/chainsaw
item = /obj/item/twohanded/chainsaw
cost = 13
/datum/uplink_item/dangerous/batterer
name = "Mind Batterer"
desc = "A device that has a chance of knocking down people around you for a long amount of time. 50% chance per person. The user is unaffected. Has 5 charges."
reference = "BTR"
item = /obj/item/device/batterer
item = /obj/item/batterer
cost = 5
/datum/uplink_item/dangerous/manhacks
name = "Viscerator Delivery Grenade"
desc = "A unique grenade that deploys a swarm of viscerators upon activation, which will chase down and shred any non-operatives in the area."
reference = "VDG"
item = /obj/item/weapon/grenade/spawnergrenade/manhacks
cost = 8
item = /obj/item/grenade/spawnergrenade/manhacks
cost = 6
gamemodes = list(/datum/game_mode/nuclear)
surplus = 35
@@ -465,16 +465,16 @@ var/list/uplink_items = list()
name = "Box of Bioterror Syringes"
desc = "A box full of preloaded syringes, containing various chemicals that seize up the victim's motor and broca system , making it impossible for them to move or speak while in their system."
reference = "BTS"
item = /obj/item/weapon/storage/box/syndie_kit/bioterror
cost = 6
item = /obj/item/storage/box/syndie_kit/bioterror
cost = 5
gamemodes = list(/datum/game_mode/nuclear)
/datum/uplink_item/dangerous/saringrenades
name = "Sarin Gas Grenades"
desc = "A box of four (4) grenades filled with Sarin, a deadly neurotoxin. Use extreme caution when handling and be sure to vacate the premise after using; ensure communication is maintained with team to avoid accidental gassings."
reference = "TGG"
item = /obj/item/weapon/storage/box/syndie_kit/sarin
cost = 15
item = /obj/item/storage/box/syndie_kit/sarin
cost = 12
gamemodes = list(/datum/game_mode/nuclear)
surplus = 0
@@ -482,7 +482,7 @@ var/list/uplink_items = list()
name = "Atmos Grenades"
desc = "A box of two (2) grenades that wreak havoc with the atmosphere of the target area. Capable of engulfing a large area in lit plasma, or N2O. Deploy with extreme caution!"
reference = "AGG"
item = /obj/item/weapon/storage/box/syndie_kit/atmosgasgrenades
item = /obj/item/storage/box/syndie_kit/atmosgasgrenades
cost = 11
/datum/uplink_item/dangerous/emp
@@ -490,14 +490,14 @@ var/list/uplink_items = list()
desc = "A box that contains two EMP grenades and an EMP implant. Useful to disrupt communication, \
security's energy weapons, and silicon lifeforms when you're in a tight spot."
reference = "EMPK"
item = /obj/item/weapon/storage/box/syndie_kit/emp
item = /obj/item/storage/box/syndie_kit/emp
cost = 2
/datum/uplink_item/dangerous/syndicate_minibomb
name = "Syndicate Minibomb"
desc = "The minibomb is a grenade with a five-second fuse."
reference = "SMB"
item = /obj/item/weapon/grenade/syndieminibomb
item = /obj/item/grenade/syndieminibomb
cost = 6
/datum/uplink_item/dangerous/gygax
@@ -523,7 +523,7 @@ var/list/uplink_items = list()
name = "Syndicate Cyborg"
desc = "A cyborg designed and programmed for systematic extermination of non-Syndicate personnel."
reference = "SC"
item = /obj/item/weapon/antag_spawner/borg_tele
item = /obj/item/antag_spawner/borg_tele
cost = 50
gamemodes = list(/datum/game_mode/nuclear)
surplus = 0
@@ -532,7 +532,7 @@ var/list/uplink_items = list()
name = "Toy Submachine Gun"
desc = "A fully-loaded Donksoft bullpup submachine gun that fires riot grade rounds with a 20-round magazine."
reference = "FSMG"
item = /obj/item/weapon/gun/projectile/automatic/c20r/toy
item = /obj/item/gun/projectile/automatic/c20r/toy
cost = 5
gamemodes = list(/datum/game_mode/nuclear)
surplus = 0
@@ -541,7 +541,7 @@ var/list/uplink_items = list()
name = "Toy Machine Gun"
desc = "A fully-loaded Donksoft belt-fed machine gun. This weapon has a massive 50-round magazine of devastating riot grade darts, that can briefly incapacitate someone in just one volley."
reference = "FLMG"
item = /obj/item/weapon/gun/projectile/automatic/l6_saw/toy
item = /obj/item/gun/projectile/automatic/l6_saw/toy
cost = 10
gamemodes = list(/datum/game_mode/nuclear)
surplus = 0
@@ -558,14 +558,14 @@ var/list/uplink_items = list()
//for refunding the syndieborg teleporter
/datum/uplink_item/dangerous/syndieborg/spawn_item()
var/obj/item/weapon/antag_spawner/borg_tele/T = ..()
var/obj/item/antag_spawner/borg_tele/T = ..()
if(istype(T))
T.TC_cost = cost
/datum/uplink_item/dangerous/guardian
name = "Holoparasites"
desc = "Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, they require an organic host as a home base and source of fuel."
item = /obj/item/weapon/storage/box/syndie_kit/guardian
item = /obj/item/storage/box/syndie_kit/guardian
excludefrom = list(/datum/game_mode/nuclear)
cost = 12
@@ -622,7 +622,7 @@ var/list/uplink_items = list()
name = "Ammo Duffelbag - Shotgun Ammo Grab Bag"
desc = "A duffelbag filled with Bulldog ammo to kit out an entire team, at a discounted price."
reference = "SAGL"
item = /obj/item/weapon/storage/backpack/duffel/syndie/ammo/loaded
item = /obj/item/storage/backpack/duffel/syndie/ammo/loaded
cost = 10 //bulk buyer's discount. Very useful if you're buying a mech and dont have TC left to buy people non-shotgun guns
gamemodes = list(/datum/game_mode/nuclear)
@@ -698,7 +698,7 @@ var/list/uplink_items = list()
desc = "A 3-round magazine of soporific ammo designed for use with .50 sniper rifles. Put your enemies to sleep today!"
reference = "50S"
item = /obj/item/ammo_box/magazine/sniper_rounds/soporific
cost = 6
cost = 3
/datum/uplink_item/ammo/sniper/haemorrhage
name = ".50 Haemorrhage Magazine"
@@ -725,7 +725,7 @@ var/list/uplink_items = list()
desc = "A length of fiber wire between two wooden handles, perfect for the discrete assassin. This weapon, when used on a target from behind \
will instantly put them in your grasp and silence them, as well as causing rapid suffocation. Does not work on those who do not need to breathe."
reference = "GAR"
item = /obj/item/weapon/twohanded/garrote
item = /obj/item/twohanded/garrote
cost = 10
/datum/uplink_item/stealthy_weapons/martialarts
@@ -733,7 +733,7 @@ var/list/uplink_items = list()
desc = "This scroll contains the secrets of an ancient martial arts technique. You will master unarmed combat, \
deflecting all ranged weapon fire, but you also refuse to use dishonorable ranged weaponry."
reference = "SCS"
item = /obj/item/weapon/sleeping_carp_scroll
item = /obj/item/sleeping_carp_scroll
cost = 17
excludefrom = list(/datum/game_mode/nuclear)
@@ -742,21 +742,21 @@ var/list/uplink_items = list()
desc = "A box of shurikens and reinforced bolas from ancient Earth martial arts. They are highly effective \
throwing weapons. The bolas can knock a target down and the shurikens will embed into limbs."
reference = "STK"
item = /obj/item/weapon/storage/box/syndie_kit/throwing_weapons
item = /obj/item/storage/box/syndie_kit/throwing_weapons
cost = 3
/datum/uplink_item/stealthy_weapons/edagger
name = "Energy Dagger"
desc = "A dagger made of energy that looks and functions as a pen when off."
reference = "EDP"
item = /obj/item/weapon/pen/edagger
item = /obj/item/pen/edagger
cost = 2
/datum/uplink_item/stealthy_weapons/sleepy_pen
name = "Sleepy Pen"
desc = "A syringe disguised as a functional pen. It's filled with a potent anaesthetic. \ The pen holds two doses of the mixture. The pen can be refilled."
reference = "SP"
item = /obj/item/weapon/pen/sleepy
item = /obj/item/pen/sleepy
cost = 8
excludefrom = list(/datum/game_mode/nuclear)
@@ -764,7 +764,7 @@ var/list/uplink_items = list()
name = "Toy Gun (with Stun Darts)"
desc = "An innocent looking toy pistol designed to fire foam darts. Comes loaded with riot grade darts, to incapacitate a target."
reference = "FSPI"
item = /obj/item/weapon/gun/projectile/automatic/toy/pistol/riot
item = /obj/item/gun/projectile/automatic/toy/pistol/riot
cost = 3
surplus = 10
@@ -772,7 +772,7 @@ var/list/uplink_items = list()
name = "Syndicate Soap"
desc = "A sinister-looking surfactant used to clean blood stains to hide murders and prevent DNA analysis. You can also drop it underfoot to slip people."
reference = "SOAP"
item = /obj/item/weapon/soap/syndie
item = /obj/item/soap/syndie
cost = 1
surplus = 50
@@ -780,22 +780,31 @@ var/list/uplink_items = list()
name = "Dart Pistol"
desc = "A miniaturized version of a normal syringe gun. It is very quiet when fired and can fit into any space a small item can."
reference = "DART"
item = /obj/item/weapon/gun/syringe/syndicate
item = /obj/item/gun/syringe/syndicate
cost = 4
surplus = 50
excludefrom = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_weapons/RSG
name = "Rapid Syringe Gun"
desc = "A rapid syringe gun able to hold six shot and fire them rapidly. Great together with the bioterror syringe"
reference = "RSG"
item = /obj/item/gun/syringe/rapidsyringe
cost = 4
gamemodes = list(/datum/game_mode/nuclear)
/datum/uplink_item/stealthy_weapons/detomatix
name = "Detomatix PDA Cartridge"
desc = "When inserted into a personal digital assistant, this cartridge gives you five opportunities to detonate PDAs of crewmembers who have their message feature enabled. The concussive effect from the explosion will knock the recipient out for a short period, and deafen them for longer. It has a chance to detonate your PDA."
reference = "DEPC"
item = /obj/item/weapon/cartridge/syndicate
item = /obj/item/cartridge/syndicate
cost = 6
/datum/uplink_item/stealthy_weapons/silencer
name = "Universal Suppressor"
desc = "Fitted for use on any small caliber weapon with a threaded barrel, this suppressor will silence the shots of the weapon for increased stealth and superior ambushing capability."
reference = "US"
item = /obj/item/weapon/suppressor
item = /obj/item/suppressor
cost = 1
surplus = 10
@@ -803,7 +812,7 @@ var/list/uplink_items = list()
name = "Pizza Bomb"
desc = "A pizza box with a bomb taped inside of it. The timer needs to be set by opening the box; afterwards, opening the box again will trigger the detonation."
reference = "PB"
item = /obj/item/device/pizza_bomb
item = /obj/item/pizza_bomb
cost = 5
surplus = 8
@@ -845,7 +854,7 @@ var/list/uplink_items = list()
desc = "A stamp that can be activated to imitate an official Nanotrasen Stamp. The disguised stamp will work exactly like the real stamp and will allow you to forge false documents to gain access or equipment; \
it can also be used in a washing machine to forge clothing."
reference = "CHST"
item = /obj/item/weapon/stamp/chameleon
item = /obj/item/stamp/chameleon
cost = 1
surplus = 35
@@ -865,11 +874,21 @@ var/list/uplink_items = list()
gamemodes = list(/datum/game_mode/nuclear)
excludefrom = list()
/datum/uplink_item/stealthy_tools/frame
name = "F.R.A.M.E. PDA Cartridge"
desc = "When inserted into a personal digital assistant, this cartridge gives you five PDA viruses which \
when used cause the targeted PDA to become a new uplink with zero TCs, and immediately become unlocked. \
You will receive the unlock code upon activating the virus, and the new uplink may be charged with \
telecrystals normally."
reference = "FRAME"
item = /obj/item/cartridge/frame
cost = 4
/datum/uplink_item/stealthy_tools/agent_card
name = "Agent ID Card"
desc = "Agent cards prevent artificial intelligences from tracking the wearer, and can copy access from other identification cards. The access is cumulative, so scanning one card does not erase the access gained from another."
reference = "AIDC"
item = /obj/item/weapon/card/id/syndicate
item = /obj/item/card/id/syndicate
cost = 2
/datum/uplink_item/stealthy_tools/voice_changer
@@ -883,14 +902,14 @@ var/list/uplink_items = list()
name = "Chameleon-Projector"
desc = "Projects an image across a user, disguising them as an object scanned with it, as long as they don't move the projector from their hand. The disguised user cannot run and projectiles pass over them."
reference = "CP"
item = /obj/item/device/chameleon
item = /obj/item/chameleon
cost = 7
/datum/uplink_item/stealthy_tools/camera_bug
name = "Camera Bug"
desc = "Enables you to view all cameras on the network and track a target. Bugging cameras allows you to disable them remotely."
reference = "CB"
item = /obj/item/device/camera_bug
item = /obj/item/camera_bug
cost = 1
surplus = 90
@@ -898,14 +917,14 @@ var/list/uplink_items = list()
name = "DNA Scrambler"
desc = "A syringe with one injection that randomizes appearance and name upon use. A cheaper but less versatile alternative to an agent card and voice changer."
reference = "DNAS"
item = /obj/item/weapon/dnascrambler
item = /obj/item/dnascrambler
cost = 4
/datum/uplink_item/stealthy_tools/smugglersatchel
name = "Smuggler's Satchel"
desc = "This satchel is thin enough to be hidden in the gap between plating and tiling, great for stashing your stolen goods. Comes with a crowbar and a floor tile inside."
reference = "SMSA"
item = /obj/item/weapon/storage/backpack/satchel_flat
item = /obj/item/storage/backpack/satchel_flat
cost = 2
surplus = 30
@@ -914,7 +933,7 @@ var/list/uplink_items = list()
desc = "A small, self-charging, short-ranged EMP device disguised as a flashlight. \
Useful for disrupting headsets, cameras, and borgs during stealth operations."
reference = "EMPL"
item = /obj/item/device/flashlight/emp
item = /obj/item/flashlight/emp
cost = 2
surplus = 30
@@ -923,7 +942,7 @@ var/list/uplink_items = list()
desc = "These cardboard cutouts are coated with a thin material that prevents discoloration and makes the images on them appear more lifelike. This pack contains three as well as a \
spraycan for changing their appearances."
reference = "ADCC"
item = /obj/item/weapon/storage/box/syndie_kit/cutouts
item = /obj/item/storage/box/syndie_kit/cutouts
cost = 1
surplus = 20
@@ -937,28 +956,35 @@ var/list/uplink_items = list()
name = "Cryptographic Sequencer"
desc = "The cryptographic sequencer, also known as an emag, is a small card that unlocks hidden functions in electronic devices, subverts intended functions and characteristically breaks security mechanisms."
reference = "EMAG"
item = /obj/item/weapon/card/emag
item = /obj/item/card/emag
cost = 6
/datum/uplink_item/device_tools/toolbox
name = "Fully Loaded Toolbox"
desc = "The syndicate toolbox is a suspicious black and red. Aside from tools, it comes with insulated gloves and a multitool."
reference = "FLTB"
item = /obj/item/weapon/storage/toolbox/syndicate
item = /obj/item/storage/toolbox/syndicate
cost = 1
/datum/uplink_item/device_tools/surgerybag
name = "Syndicate Surgery Duffelbag"
desc = "The Syndicate surgery duffelbag is a toolkit containing all surgery tools, a straitjacket, and a muzzle."
reference = "SSDB"
item = /obj/item/weapon/storage/backpack/duffel/syndie/surgery
item = /obj/item/storage/backpack/duffel/syndie/surgery
cost = 4
/datum/uplink_item/device_tools/bonerepair
name = "Prototype Bone Repair Kit"
desc = "Stolen prototype bone repair nanites. Contains one nanocalcium autoinjector and guide."
reference = "NCAI"
item = /obj/item/storage/box/syndie_kit/bonerepair
cost = 6
/datum/uplink_item/device_tools/military_belt
name = "Military Belt"
desc = "A robust seven-slot red belt made for carrying a broad variety of weapons, ammunition and explosives"
reference = "SBM"
item = /obj/item/weapon/storage/belt/military
item = /obj/item/storage/belt/military
cost = 3
excludefrom = list(/datum/game_mode/nuclear)
@@ -967,8 +993,8 @@ var/list/uplink_items = list()
desc = "The syndicate medkit is a suspicious black and red. Included is a combat stimulant injector for rapid healing, a medical HUD for quick identification of injured comrades, \
and other medical supplies helpful for a medical field operative."
reference = "SCMK"
item = /obj/item/weapon/storage/firstaid/tactical
cost = 9
item = /obj/item/storage/firstaid/tactical
cost = 7
gamemodes = list(/datum/game_mode/nuclear)
//Space Suits and Hardsuits
@@ -982,7 +1008,7 @@ var/list/uplink_items = list()
fits inside bags, and has a weapon slot. Nanotrasen crewmembers are trained to report red space suit \
sightings, however."
reference = "SS"
item = /obj/item/weapon/storage/box/syndie_kit/space
item = /obj/item/storage/box/syndie_kit/space
cost = 4
/datum/uplink_item/suits/hardsuit
@@ -994,14 +1020,14 @@ var/list/uplink_items = list()
Additionally the suit is collapsible, making it small enough to fit within a backpack. \
Nanotrasen crew who spot these suits are known to panic."
reference = "BRHS"
item = /obj/item/weapon/storage/box/syndie_kit/hardsuit
item = /obj/item/storage/box/syndie_kit/hardsuit
cost = 8
excludefrom = list(/datum/game_mode/nuclear)
/datum/uplink_item/suits/hardsuit/elite
name = "Elite Syndicate Hardsuit"
desc = "An advanced hardsuit with superior armor and mobility to the standard Syndicate Hardsuit."
item = /obj/item/weapon/storage/box/syndie_kit/elite_hardsuit
item = /obj/item/storage/box/syndie_kit/elite_hardsuit
cost = 8
reference = "ESHS"
excludefrom = list()
@@ -1010,7 +1036,7 @@ var/list/uplink_items = list()
/datum/uplink_item/suits/hardsuit/shielded
name = "Shielded Hardsuit"
desc = "An advanced hardsuit with built in energy shielding. The shields will rapidly recharge when not under fire."
item = /obj/item/weapon/storage/box/syndie_kit/shielded_hardsuit
item = /obj/item/storage/box/syndie_kit/shielded_hardsuit
cost = 30
reference = "SHS"
excludefrom = list()
@@ -1028,7 +1054,7 @@ var/list/uplink_items = list()
name = "Binary Translator Key"
desc = "A key, that when inserted into a radio headset, allows you to listen to and talk with artificial intelligences and cybernetic organisms in binary."
reference = "BITK"
item = /obj/item/device/encryptionkey/binary
item = /obj/item/encryptionkey/binary
cost = 5
surplus = 75
@@ -1036,7 +1062,7 @@ var/list/uplink_items = list()
name = "Syndicate Encryption Key"
desc = "A key, that when inserted into a radio headset, allows you to listen to all station department channels as well as talk on an encrypted Syndicate channel."
reference = "SEK"
item = /obj/item/device/encryptionkey/syndicate
item = /obj/item/encryptionkey/syndicate
cost = 2 //Nowhere near as useful as the Binary Key!
surplus = 75
@@ -1044,8 +1070,8 @@ var/list/uplink_items = list()
name = "Hacked AI Upload Module"
desc = "When used with an upload console, this module allows you to upload priority laws to an artificial intelligence. Be careful with their wording, as artificial intelligences may look for loopholes to exploit."
reference = "HAI"
item = /obj/item/weapon/aiModule/syndicate
cost = 14
item = /obj/item/aiModule/syndicate
cost = 12
/datum/uplink_item/device_tools/magboots
name = "Blood-Red Magboots"
@@ -1069,14 +1095,14 @@ var/list/uplink_items = list()
name = "Composition C-4"
desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls or connect an assembly to its wiring to make it remotely detonable. It has a modifiable timer with a minimum setting of 10 seconds."
reference = "C4"
item = /obj/item/weapon/grenade/plastic/c4
item = /obj/item/grenade/plastic/c4
cost = 1
/datum/uplink_item/device_tools/breaching_charge
name = "Composition X-4"
desc = "X-4 is a shaped charge designed to be safe to the user while causing maximum damage to the occupants of the room beach breached. It has a modifiable timer with a minimum setting of 10 seconds."
reference = "X4"
item = /obj/item/weapon/grenade/plastic/x4
item = /obj/item/grenade/plastic/x4
cost = 2
gamemodes = list(/datum/game_mode/nuclear)
@@ -1084,7 +1110,7 @@ var/list/uplink_items = list()
name = "Power Sink"
desc = "When screwed to wiring attached to an electric grid, then activated, this large device places excessive load on the grid, causing a stationwide blackout. The sink cannot be carried because of its excessive size. Ordering this sends you a small beacon that will teleport the power sink to your location on activation."
reference = "PS"
item = /obj/item/device/powersink
item = /obj/item/powersink
cost = 10
/datum/uplink_item/device_tools/singularity_beacon
@@ -1094,7 +1120,7 @@ var/list/uplink_items = list()
in containment. Because of its size, it cannot be carried. Ordering this \
sends you a small beacon that will teleport the larger beacon to your location upon activation."
reference = "SNGB"
item = /obj/item/device/radio/beacon/syndicate
item = /obj/item/radio/beacon/syndicate
cost = 12
surplus = 0
@@ -1103,7 +1129,7 @@ var/list/uplink_items = list()
desc = "The Syndicate Bomb has an adjustable timer with a minimum setting of 60 seconds. Ordering the bomb sends you a small beacon, which will teleport the explosive to your location when you activate it. \
You can wrench the bomb down to prevent removal. The crew may attempt to defuse the bomb."
reference = "SB"
item = /obj/item/device/radio/beacon/syndicate/bomb
item = /obj/item/radio/beacon/syndicate/bomb
cost = 11
/datum/uplink_item/device_tools/syndicate_detonator
@@ -1111,7 +1137,7 @@ var/list/uplink_items = list()
desc = "The Syndicate Detonator is a companion device to the Syndicate Bomb. Simply press the included button and an encrypted radio frequency will instruct all live syndicate bombs to detonate. \
Useful for when speed matters or you wish to synchronize multiple bomb blasts. Be sure to stand clear of the blast radius before using the detonator."
reference = "SD"
item = /obj/item/device/syndicatedetonator
item = /obj/item/syndicatedetonator
cost = 3
gamemodes = list(/datum/game_mode/nuclear)
@@ -1119,14 +1145,14 @@ var/list/uplink_items = list()
name = "Advanced Pinpointer"
desc = "A pinpointer that tracks any specified coordinates, DNA string, high value item or the nuclear authentication disk."
reference = "ADVP"
item = /obj/item/weapon/pinpointer/advpinpointer
item = /obj/item/pinpointer/advpinpointer
cost = 4
/datum/uplink_item/device_tools/ai_detector
name = "Artificial Intelligence Detector" // changed name in case newfriends thought it detected disguised ai's
desc = "A functional multitool that turns red when it detects an artificial intelligence watching it or its holder. Knowing when an artificial intelligence is watching you is useful for knowing when to maintain cover."
reference = "AID"
item = /obj/item/device/multitool/ai_detect
item = /obj/item/multitool/ai_detect
cost = 1
/datum/uplink_item/device_tools/telecrystal
@@ -1137,35 +1163,49 @@ var/list/uplink_items = list()
cost = 1
surplus = 0
/datum/uplink_item/device_tools/telecrystal/five
name = "5 Raw Telecrystals"
desc = "Five telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
reference = "RTCF"
item = /obj/item/stack/telecrystal/five
cost = 5
/datum/uplink_item/device_tools/telecrystal/twenty
name = "20 Raw Telecrystals"
desc = "Twenty telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count."
reference = "RTCT"
item = /obj/item/stack/telecrystal/twenty
cost = 20
/datum/uplink_item/device_tools/jammer
name = "Radio Jammer"
desc = "This device will disrupt any nearby outgoing radio communication when activated."
reference = "RJ"
item = /obj/item/device/jammer
item = /obj/item/jammer
cost = 5
/datum/uplink_item/device_tools/teleporter
name = "Teleporter Circuit Board"
desc = "A printed circuit board that completes the teleporter onboard the mothership. Advise you test fire the teleporter before entering it, as malfunctions can occur."
item = /obj/item/weapon/circuitboard/teleporter
item = /obj/item/circuitboard/teleporter
reference = "TP"
cost = 40
cost = 20
gamemodes = list(/datum/game_mode/nuclear)
surplus = 0
/datum/uplink_item/device_tools/assault_pod
name = "Assault Pod Targetting Device"
desc = "Use to select the landing zone of your assault pod."
item = /obj/item/device/assault_pod
item = /obj/item/assault_pod
reference = "APT"
cost = 30
cost = 25
gamemodes = list(/datum/game_mode/nuclear)
surplus = 0
/datum/uplink_item/device_tools/shield
name = "Energy Shield"
desc = "An incredibly useful personal shield projector, capable of reflecting energy projectiles and defending against other attacks."
item = /obj/item/weapon/shield/energy
item = /obj/item/shield/energy
reference = "ESD"
cost = 16
gamemodes = list(/datum/game_mode/nuclear)
@@ -1174,7 +1214,7 @@ var/list/uplink_items = list()
/datum/uplink_item/device_tools/medgun
name = "Medbeam Gun"
desc = "Medical Beam Gun, useful in prolonged firefights."
item = /obj/item/weapon/gun/medbeam
item = /obj/item/gun/medbeam
reference = "MBG"
cost = 15
gamemodes = list(/datum/game_mode/nuclear)
@@ -1189,14 +1229,14 @@ var/list/uplink_items = list()
name = "Freedom Implant"
desc = "An implant injected into the body and later activated using a bodily gesture to attempt to slip restraints."
reference = "FI"
item = /obj/item/weapon/implanter/freedom
item = /obj/item/implanter/freedom
cost = 5
/datum/uplink_item/implants/uplink
name = "Uplink Implant"
desc = "An implant injected into the body, and later activated using a bodily gesture to open an uplink with 10 telecrystals. The ability for an agent to open an uplink after their possessions have been stripped from them makes this implant excellent for escaping confinement."
reference = "UI"
item = /obj/item/weapon/implanter/uplink
item = /obj/item/implanter/uplink
cost = 14
surplus = 0
@@ -1204,21 +1244,21 @@ var/list/uplink_items = list()
name = "Storage Implant"
desc = "An implant injected into the body, and later activated at the user's will. It will open a small subspace pocket capable of storing two items."
reference = "ESI"
item = /obj/item/weapon/implanter/storage
item = /obj/item/implanter/storage
cost = 8
/datum/uplink_item/implants/mindslave
name = "Mindslave Implant"
desc = "A box containing an implanter filled with a mindslave implant that when injected into another person makes them loyal to you and your cause, unless of course they're already implanted by someone else. Loyalty ends if the implant is no longer in their system."
reference = "MI"
item = /obj/item/weapon/implanter/traitor
item = /obj/item/implanter/traitor
cost = 10
/datum/uplink_item/implants/adrenal
name = "Adrenal Implant"
desc = "An implant injected into the body, and later activated using a bodily gesture to inject a chemical cocktail, which has a mild healing effect along with removing all stuns and increasing his speed."
reference = "AI"
item = /obj/item/weapon/implanter/adrenalin
item = /obj/item/implanter/adrenalin
cost = 8
/datum/uplink_item/implants/microbomb
@@ -1226,7 +1266,7 @@ var/list/uplink_items = list()
desc = "An implant injected into the body, and later activated either manually or automatically upon death. The more implants inside of you, the higher the explosive power. \
This will permanently destroy your body, however."
reference = "MBI"
item = /obj/item/weapon/implanter/explosive
item = /obj/item/implanter/explosive
cost = 2
gamemodes = list(/datum/game_mode/nuclear)
@@ -1236,13 +1276,13 @@ var/list/uplink_items = list()
surplus = 0
gamemodes = list(/datum/game_mode/nuclear)
/datum/uplink_item/cyber_implants/spawn_item(turf/loc, obj/item/device/uplink/U)
/datum/uplink_item/cyber_implants/spawn_item(turf/loc, obj/item/uplink/U)
if(item)
if(findtext(item, /obj/item/organ/internal/cyberimp))
U.uses -= max(cost, 0)
U.used_TC += cost
feedback_add_details("traitor_uplink_items_bought", name) //this one and the line before copypasted because snowflaek code
return new /obj/item/weapon/storage/box/cyber_implants(loc, item)
return new /obj/item/storage/box/cyber_implants(loc, item)
else
return ..()
@@ -1280,7 +1320,7 @@ var/list/uplink_items = list()
desc = "A random selection of cybernetic implants. Guaranteed 5 high quality implants. \
Comes with an automated implanting tool."
reference = "CIB"
item = /obj/item/weapon/storage/box/cyber_implants/bundle
item = /obj/item/storage/box/cyber_implants/bundle
cost = 40
// POINTLESS BADASSERY
@@ -1293,14 +1333,14 @@ var/list/uplink_items = list()
name = "Syndicate Smokes"
desc = "Strong flavor, dense smoke, infused with omnizine."
reference = "SYSM"
item = /obj/item/weapon/storage/fancy/cigarettes/cigpack_syndicate
item = /obj/item/storage/fancy/cigarettes/cigpack_syndicate
cost = 2
/datum/uplink_item/badass/bundle
name = "Syndicate Bundle"
desc = "Syndicate Bundles are specialised groups of items that arrive in a plain box. These items are collectively worth more than 20 telecrystals, but you do not know which specialisation you will receive."
reference = "SYB"
item = /obj/item/weapon/storage/box/syndicate
item = /obj/item/storage/box/syndicate
cost = 20
excludefrom = list(/datum/game_mode/nuclear)
@@ -1319,7 +1359,7 @@ var/list/uplink_items = list()
desc = "A secure briefcase containing 5000 space credits. Useful for bribing personnel, or purchasing goods and services at lucrative prices. \
The briefcase also feels a little heavier to hold; it has been manufactured to pack a little bit more of a punch if your client needs some convincing."
reference = "CASH"
item = /obj/item/weapon/storage/secure/briefcase/syndie
item = /obj/item/storage/secure/briefcase/syndie
cost = 1
/datum/uplink_item/badass/balloon
@@ -1333,7 +1373,7 @@ var/list/uplink_items = list()
name = "Macrobomb Implant"
desc = "An implant injected into the body, and later activated either manually or automatically upon death. Upon death, releases a massive explosion that will wipe out everything nearby."
reference = "HAB"
item = /obj/item/weapon/implanter/explosive_macro
item = /obj/item/implanter/explosive_macro
cost = 20
gamemodes = list(/datum/game_mode/nuclear)
@@ -1341,10 +1381,10 @@ var/list/uplink_items = list()
name = "Random Item"
desc = "Picking this choice will send you a random item from the list. Useful for when you cannot think of a strategy to finish your objectives with."
reference = "RAIT"
item = /obj/item/weapon/storage/box/syndicate
item = /obj/item/storage/box/syndicate
cost = 0
/datum/uplink_item/badass/random/spawn_item(var/turf/loc, var/obj/item/device/uplink/U)
/datum/uplink_item/badass/random/spawn_item(var/turf/loc, var/obj/item/uplink/U)
var/list/buyable_items = get_uplink_items()
var/list/possible_items = list()
@@ -1368,10 +1408,10 @@ var/list/uplink_items = list()
desc = "A crate containing 50 telecrystals worth of random syndicate leftovers."
reference = "SYSC"
cost = 20
item = /obj/item/weapon/storage/box/syndicate
item = /obj/item/storage/box/syndicate
excludefrom = list(/datum/game_mode/nuclear)
/datum/uplink_item/badass/surplus_crate/spawn_item(turf/loc, obj/item/device/uplink/U)
/datum/uplink_item/badass/surplus_crate/spawn_item(turf/loc, obj/item/uplink/U)
var/obj/structure/closet/crate/C = new(loc)
var/list/temp_uplink_list = get_uplink_items()
var/list/buyable_items = list()
+4 -4
View File
@@ -31,7 +31,7 @@
var/list/impacted_areas = list() //Areas to be affected by the weather, calculated when the weather begins
var/target_z = MAIN_STATION //The z-level to affect
var/list/protected_areas = list()//Areas that are protected and excluded from the affected areas.
var/overlay_layer = 10 //Since it's above everything else, this is the layer used by default. 2 is below mobs and walls if you need to use that.
var/aesthetic = FALSE //If the weather has no purpose other than looks
var/immunity_type = "storm" //Used by mobs to prevent them from being affected by the weather
@@ -70,7 +70,7 @@
to_chat(M, telegraph_message)
if(telegraph_sound)
M << sound(telegraph_sound)
addtimer(src, "start", telegraph_duration)
addtimer(CALLBACK(src, .proc/start), telegraph_duration)
/datum/weather/proc/start()
if(stage >= MAIN_STAGE)
@@ -85,7 +85,7 @@
if(weather_sound)
M << sound(weather_sound)
weather_master.processing_weather |= src
addtimer(src, "wind_down", weather_duration)
addtimer(CALLBACK(src, .proc/wind_down), weather_duration)
/datum/weather/proc/wind_down()
if(stage >= WIND_DOWN_STAGE)
@@ -100,7 +100,7 @@
if(end_sound)
M << sound(end_sound)
weather_master.processing_weather -= src
addtimer(src, "end", end_duration)
addtimer(CALLBACK(src, .proc/end), end_duration)
/datum/weather/proc/end()
if(stage == END_STAGE)
+6 -5
View File
@@ -54,11 +54,11 @@ var/const/AIRLOCK_WIRE_LIGHT = 512
/datum/wires/airlock/CanUse(mob/living/L)
var/obj/machinery/door/airlock/A = holder
if(!issilicon(L))
if(iscarbon(L))
if(A.isElectrified())
if(A.shock(L, 100))
return 0
if(A.p_open)
if(A.panel_open)
return 1
return 0
@@ -164,9 +164,10 @@ var/const/AIRLOCK_WIRE_LIGHT = 512
//one wire for door bolts. Sending a pulse through this drops door bolts if they're not down (whether power's on or not),
//raises them if they are down (only if power's on)
if(!A.locked)
A.lock()
else
A.unlock()
if(A.lock())
A.audible_message("<span class='italics'>You hear a click from the bottom of the door.</span>", null, 1)
else if(A.unlock())
A.audible_message("<span class='italics'>You hear a click from the bottom of the door.</span>", null, 1)
if(AIRLOCK_WIRE_BACKUP_POWER1)
//two wires for backup power. Sending a pulse through either one causes a breaker to trip, but this does not disable it unless main power is down too (in which case it is disabled for 1 minute or however long it takes main power to come back, whichever is shorter).
+4 -4
View File
@@ -10,10 +10,10 @@ var/const/AUTOLATHE_DISABLE_WIRE = 4
switch(index)
if(AUTOLATHE_HACK_WIRE)
return "Hack"
if(AUTOLATHE_SHOCK_WIRE)
return "Shock"
if(AUTOLATHE_DISABLE_WIRE)
return "Disable"
@@ -69,6 +69,6 @@ var/const/AUTOLATHE_DISABLE_WIRE = 4
updateUIs()
/datum/wires/autolathe/proc/updateUIs()
nanomanager.update_uis(src)
SSnanoui.update_uis(src)
if(holder)
nanomanager.update_uis(holder)
SSnanoui.update_uis(holder)
+2 -2
View File
@@ -25,7 +25,7 @@ var/const/WIRE_EXPLODE = 1
..()
/datum/wires/explosive/gibtonite
holder_type = /obj/item/weapon/twohanded/required/gibtonite
holder_type = /obj/item/twohanded/required/gibtonite
/datum/wires/explosive/gibtonite/CanUse(mob/L)
return 1
@@ -34,5 +34,5 @@ var/const/WIRE_EXPLODE = 1
return
/datum/wires/explosive/gibtonite/explode()
var/obj/item/weapon/twohanded/required/gibtonite/P = holder
var/obj/item/twohanded/required/gibtonite/P = holder
P.GibtoniteReaction(null, 2)
+5 -5
View File
@@ -11,12 +11,12 @@ var/const/NUCLEARBOMB_WIRE_SAFETY = 4
switch(index)
if(NUCLEARBOMB_WIRE_LIGHT)
return "Bomb Light"
if(NUCLEARBOMB_WIRE_TIMING)
return "Bomb Timing"
if(NUCLEARBOMB_WIRE_SAFETY)
return "Bomb Safety"
return "Bomb Safety"
/datum/wires/nuclearbomb/CanUse(mob/living/L)
var/obj/machinery/nuclearbomb/N = holder
@@ -77,6 +77,6 @@ var/const/NUCLEARBOMB_WIRE_SAFETY = 4
N.lighthack = !N.lighthack
/datum/wires/nuclearbomb/proc/updateUIs()
nanomanager.update_uis(src)
SSnanoui.update_uis(src)
if(holder)
nanomanager.update_uis(holder)
SSnanoui.update_uis(holder)
+4 -4
View File
@@ -1,5 +1,5 @@
/datum/wires/radio
holder_type = /obj/item/device/radio
holder_type = /obj/item/radio
wire_count = 3
var/const/WIRE_SIGNAL = 1
@@ -18,13 +18,13 @@ var/const/WIRE_TRANSMIT = 4
return "Transmitter"
/datum/wires/radio/CanUse(mob/living/L)
var/obj/item/device/radio/R = holder
var/obj/item/radio/R = holder
if(R.b_stat)
return 1
return 0
/datum/wires/radio/UpdatePulsed(index)
var/obj/item/device/radio/R = holder
var/obj/item/radio/R = holder
switch(index)
if(WIRE_SIGNAL)
R.listening = !R.listening && !IsIndexCut(WIRE_RECEIVE)
@@ -38,7 +38,7 @@ var/const/WIRE_TRANSMIT = 4
..()
/datum/wires/radio/UpdateCut(index, mended)
var/obj/item/device/radio/R = holder
var/obj/item/radio/R = holder
switch(index)
if(WIRE_SIGNAL)
R.listening = mended && !IsIndexCut(WIRE_RECEIVE)
+44 -17
View File
@@ -76,22 +76,50 @@ var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown",
ui_interact(user)
/datum/wires/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
ui = nanomanager.try_update_ui(user, src, ui_key, ui, force_open)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "wires.tmpl", holder.name, window_x, window_y)
ui.open()
/datum/wires/ui_data(mob/user, ui_key = "main", datum/topic_state/state = physical_state)
var/data[0]
var/list/replace_colours = null
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes)
if(eyes && H.disabilities & COLOURBLIND)
replace_colours = eyes.replace_colours
var/list/W[0]
for(var/colour in wires)
W[++W.len] = list("colour" = capitalize(colour), "cut" = IsColourCut(colour), "index" = can_see_wire_index(user) ? GetWireName(GetIndex(colour)) : null, "attached" = IsAttached(colour))
var/new_colour = colour
var/colour_name = colour
if(colour in replace_colours)
new_colour = replace_colours[colour]
if(new_colour in LIST_REPLACE_RENAME)
colour_name = LIST_REPLACE_RENAME[new_colour]
else
colour_name = new_colour
else
new_colour = colour
colour_name = new_colour
W[++W.len] = list("colour_name" = capitalize(colour_name), "seen_colour" = capitalize(new_colour),"colour" = capitalize(colour), "cut" = IsColourCut(colour), "index" = can_see_wire_index(user) ? GetWireName(GetIndex(colour)) : null, "attached" = IsAttached(colour))
if(W.len > 0)
data["wires"] = W
var/list/status = get_status()
if(replace_colours)
var/i
for(i=1, i<=status.len, i++)
for(var/colour in replace_colours)
var/new_colour = replace_colours[colour]
if(new_colour in LIST_REPLACE_RENAME)
new_colour = LIST_REPLACE_RENAME[new_colour]
if(findtext(status[i],colour))
status[i] = replacetext(status[i],colour,new_colour)
break
data["status_len"] = status.len
data["status"] = status
@@ -99,21 +127,20 @@ var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown",
/datum/wires/nano_host()
return holder
/datum/wires/proc/can_see_wire_index(mob/user)
if(user.can_admin_interact())
return TRUE
else if(istype(user.get_active_hand(), /obj/item/device/multitool))
var/obj/item/device/multitool/M = user.get_active_hand()
else if(istype(user.get_active_hand(), /obj/item/multitool))
var/obj/item/multitool/M = user.get_active_hand()
if(M.shows_wire_information)
return TRUE
return FALSE
/datum/wires/Topic(href, href_list)
if(..())
return 1
var/mob/L = usr
if(CanUse(L) && href_list["action"])
var/obj/item/I = L.get_active_hand()
@@ -121,14 +148,14 @@ var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown",
holder.add_hiddenprint(L)
switch(href_list["action"])
if("cut") // Toggles the cut/mend status
if(istype(I, /obj/item/weapon/wirecutters) || L.can_admin_interact())
if(istype(I, /obj/item/wirecutters) || L.can_admin_interact())
if(istype(I))
playsound(holder, I.usesound, 20, 1)
CutWireColour(colour)
else
to_chat(L, "<span class='error'>You need wirecutters!</span>")
if("pulse")
if(istype(I, /obj/item/device/multitool) || L.can_admin_interact())
if(istype(I, /obj/item/multitool) || L.can_admin_interact())
playsound(holder, 'sound/weapons/empty.ogg', 20, 1)
PulseColour(colour)
else
@@ -139,7 +166,7 @@ var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown",
if(O)
L.put_in_hands(O)
else
if(istype(I, /obj/item/device/assembly/signaler))
if(istype(I, /obj/item/assembly/signaler))
if(L.drop_item())
Attach(colour, I)
else
@@ -147,7 +174,7 @@ var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown",
else
to_chat(L, "<span class='error'>You need a remote signaller!</span>")
nanomanager.update_uis(src)
SSnanoui.update_uis(src)
return 1
//
@@ -157,12 +184,12 @@ var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown",
// Called when wires cut/mended.
/datum/wires/proc/UpdateCut(index, mended)
if(holder)
nanomanager.update_uis(holder)
SSnanoui.update_uis(holder)
// Called when wire pulsed. Add code here.
/datum/wires/proc/UpdatePulsed(index)
if(holder)
nanomanager.update_uis(holder)
SSnanoui.update_uis(holder)
/datum/wires/proc/CanUse(mob/L)
return 1
@@ -212,7 +239,7 @@ var/const/POWER = 8
return index
else
CRASH("[colour] is not a key in wires.")
/datum/wires/proc/GetWireName(index)
return
@@ -241,7 +268,7 @@ var/const/POWER = 8
return signallers[colour]
return null
/datum/wires/proc/Attach(colour, obj/item/device/assembly/signaler/S)
/datum/wires/proc/Attach(colour, obj/item/assembly/signaler/S)
if(colour && S)
if(!IsAttached(colour))
signallers[colour] = S
@@ -251,7 +278,7 @@ var/const/POWER = 8
/datum/wires/proc/Detach(colour)
if(colour)
var/obj/item/device/assembly/signaler/S = GetAttached(colour)
var/obj/item/assembly/signaler/S = GetAttached(colour)
if(S)
signallers -= colour
S.connected = null
@@ -259,7 +286,7 @@ var/const/POWER = 8
return S
/datum/wires/proc/Pulse(obj/item/device/assembly/signaler/S)
/datum/wires/proc/Pulse(obj/item/assembly/signaler/S)
for(var/colour in signallers)
if(S == signallers[colour])