| Name: | [active1.fields["name"]] |
| ID: | [active1.fields["id"]] |
- | Sex: | [active1.fields["sex"]] |
+ | Gender: | [active1.fields["gender"]] |
| Age: | [active1.fields["age"]] | "}
dat += "| Species: | [active1.fields["species"]] | "
dat += {"| Rank: | [active1.fields["rank"]] |
@@ -309,36 +288,39 @@ What a mess.*/
active1 = null
active2 = null
- if("Confirm Identity")
- eject_id(usr)
-
if("Log Out")
authenticated = null
screen = null
active1 = null
active2 = null
+ playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
if("Log In")
- if(issilicon(usr))
- var/mob/living/silicon/borg = usr
+ var/mob/M = usr
+ var/obj/item/card/id/I = M.get_idcard(TRUE)
+ if(issilicon(M))
+ var/mob/living/silicon/borg = M
active1 = null
active2 = null
authenticated = borg.name
rank = "AI"
screen = 1
- else if(IsAdminGhost(usr))
+ else if(IsAdminGhost(M))
active1 = null
active2 = null
- authenticated = usr.client.holder.admin_signature
+ authenticated = M.client.holder.admin_signature
rank = "Central Command"
screen = 1
- else if(istype(scan, /obj/item/card/id))
+ else if(I && check_access(I))
active1 = null
active2 = null
- if(check_access(scan))
- authenticated = scan.registered_name
- rank = scan.assignment
- screen = 1
+ authenticated = I.registered_name
+ rank = I.assignment
+ screen = 1
+ else
+ to_chat(usr, "Unauthorized Access.")
+ playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
+
//RECORD FUNCTIONS
if("Record Maintenance")
screen = 2
@@ -346,16 +328,14 @@ What a mess.*/
active2 = null
if("Browse Record")
- var/datum/data/record/R = locate(href_list["d_rec"])
- var/S = locate(href_list["d_rec"])
- if(!( GLOB.data_core.general.Find(R) ))
+ var/datum/data/record/R = locate(href_list["d_rec"]) in GLOB.data_core.general
+ if(!R)
temp = "Record Not Found!"
else
+ active1 = active2 = R
for(var/datum/data/record/E in GLOB.data_core.security)
if((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
- S = E
- active1 = R
- active2 = S
+ active2 = E
screen = 3
@@ -368,7 +348,7 @@ What a mess.*/
var/obj/item/paper/P = new /obj/item/paper( loc )
P.info = "Security Record - (SR-[GLOB.data_core.securityPrintCount]) "
if((istype(active1, /datum/data/record) && GLOB.data_core.general.Find(active1)))
- P.info += text("Name: [] ID: [] \nSex: [] \nAge: [] ", active1.fields["name"], active1.fields["id"], active1.fields["sex"], active1.fields["age"])
+ P.info += text("Name: [] ID: [] \nGender: [] \nAge: [] ", active1.fields["name"], active1.fields["id"], active1.fields["gender"], active1.fields["age"])
P.info += "\nSpecies: [active1.fields["species"]] "
P.info += text("\nFingerprint: [] \nPhysical Status: [] \nMental Status: [] ", active1.fields["fingerprint"], active1.fields["p_stat"], active1.fields["m_stat"])
else
@@ -419,6 +399,7 @@ What a mess.*/
P.info += "Security Record Lost! "
P.name = text("SR-[] '[]'", GLOB.data_core.securityPrintCount, "Record Lost")
P.info += ""
+ P.update_icon()
printing = null
if("Print Poster")
if(!( printing ))
@@ -512,7 +493,7 @@ What a mess.*/
G.fields["name"] = "New Record"
G.fields["id"] = "[num2hex(rand(1, 1.6777215E7), 6)]"
G.fields["rank"] = "Unassigned"
- G.fields["sex"] = "Male"
+ G.fields["gender"] = "Male"
G.fields["age"] = "Unknown"
G.fields["species"] = "Human"
G.fields["photo_front"] = new /icon()
@@ -584,12 +565,14 @@ What a mess.*/
if(!canUseSecurityRecordsConsole(usr, t1, a1))
return
active1.fields["fingerprint"] = t1
- if("sex")
+ if("gender")
if(istype(active1, /datum/data/record))
- if(active1.fields["sex"] == "Male")
- active1.fields["sex"] = "Female"
+ if(active1.fields["gender"] == "Male")
+ active1.fields["gender"] = "Female"
+ else if(active1.fields["gender"] == "Female")
+ active1.fields["gender"] = "Other"
else
- active1.fields["sex"] = "Male"
+ active1.fields["gender"] = "Male"
if("age")
if(istype(active1, /datum/data/record))
var/t1 = input("Please input age:", "Secure. records", active1.fields["age"], null) as num
@@ -767,19 +750,14 @@ What a mess.*/
P = user.get_active_held_item()
return P
-/obj/machinery/computer/secure_data/proc/print_photo(icon/temp, name)
+/obj/machinery/computer/secure_data/proc/print_photo(icon/temp, person_name)
if (printing)
return
printing = TRUE
sleep(20)
var/obj/item/photo/P = new/obj/item/photo(drop_location())
- var/icon/small_img = icon(temp)
- var/icon/ic = icon('icons/obj/items_and_weapons.dmi',"photo")
- small_img.Scale(8, 8)
- ic.Blend(small_img,ICON_OVERLAY, 13, 13)
- P.icon = ic
- P.picture.picture_image = temp
- P.desc = "The photo on file for [name]."
+ var/datum/picture/toEmbed = new(name = person_name, desc = "The photo on file for [person_name].", image = temp)
+ P.set_picture(toEmbed, TRUE, TRUE)
P.pixel_x = rand(-10, 10)
P.pixel_y = rand(-10, 10)
printing = FALSE
@@ -799,7 +777,7 @@ What a mess.*/
else
R.fields["name"] = "[pick(pick(GLOB.first_names_male), pick(GLOB.first_names_female))] [pick(GLOB.last_names)]"
if(2)
- R.fields["sex"] = pick("Male", "Female")
+ R.fields["gender"] = pick("Male", "Female", "Other")
if(3)
R.fields["age"] = rand(5, 85)
if(4)
@@ -823,7 +801,7 @@ What a mess.*/
/obj/machinery/computer/secure_data/proc/canUseSecurityRecordsConsole(mob/user, message1 = 0, record1, record2)
if(user)
if(authenticated)
- if(user.canUseTopic(src))
+ if(user.canUseTopic(src, BE_CLOSE))
if(!trim(message1))
return 0
if(!record1 || record1 == active1)
@@ -831,22 +809,3 @@ What a mess.*/
return 1
return 0
-/obj/machinery/computer/secure_data/AltClick(mob/user)
- if(user.canUseTopic(src))
- eject_id(user)
-
-/obj/machinery/computer/secure_data/proc/eject_id(mob/user)
- if(scan)
- scan.forceMove(drop_location())
- if(!issilicon(user) && Adjacent(user))
- user.put_in_hands(scan)
- scan = null
- playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
- else //switching the ID with the one you're holding
- if(issilicon(user) || !Adjacent(user))
- return
- var/obj/item/card/id/held_id = user.is_holding_item_of_type(/obj/item/card/id)
- if(QDELETED(held_id) || !user.transferItemToLoc(held_id, src))
- return
- scan = held_id
- playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 1081cb5fa7..365d19b826 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -1280,20 +1280,23 @@
return !density || (check_access(ID) && !locked && hasPower())
/obj/machinery/door/airlock/emag_act(mob/user)
- if(!operating && density && hasPower() && !(obj_flags & EMAGGED))
- operating = TRUE
- update_icon(AIRLOCK_EMAG, 1)
- sleep(6)
- if(QDELETED(src))
- return
- operating = FALSE
- if(!open())
- update_icon(AIRLOCK_CLOSED, 1)
- obj_flags |= EMAGGED
- lights = FALSE
- locked = TRUE
- loseMainPower()
- loseBackupPower()
+ . = ..()
+ if(operating || !density || !hasPower() || obj_flags & EMAGGED)
+ return
+ operating = TRUE
+ update_icon(AIRLOCK_EMAG, 1)
+ addtimer(CALLBACK(src, .proc/open_sesame), 6)
+ return TRUE
+
+/obj/machinery/door/airlock/proc/open_sesame()
+ operating = FALSE
+ if(!open())
+ update_icon(AIRLOCK_CLOSED, 1)
+ obj_flags |= EMAGGED
+ lights = FALSE
+ locked = TRUE
+ loseMainPower()
+ loseBackupPower()
/obj/machinery/door/airlock/attack_alien(mob/living/carbon/alien/humanoid/user)
add_fingerprint(user)
diff --git a/code/game/machinery/doors/unpowered.dm b/code/game/machinery/doors/unpowered.dm
index 2e7e7d5cba..702f700617 100644
--- a/code/game/machinery/doors/unpowered.dm
+++ b/code/game/machinery/doors/unpowered.dm
@@ -13,9 +13,6 @@
else
return ..()
-/obj/machinery/door/unpowered/emag_act()
- return
-
/obj/machinery/door/unpowered/shuttle
icon = 'icons/turf/shuttle.dmi'
name = "door"
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 97ab664b85..933bb4f42a 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -206,15 +206,20 @@
..()
/obj/machinery/door/window/emag_act(mob/user)
- if(!operating && density && !(obj_flags & EMAGGED))
- obj_flags |= EMAGGED
- operating = TRUE
- flick("[src.base_state]spark", src)
- playsound(src, "sparks", 75, 1)
- sleep(6)
- operating = FALSE
- desc += " Its access panel is smoking slightly."
- open(2)
+ . = ..()
+ if(operating || !density || obj_flags & EMAGGED)
+ return
+ obj_flags |= EMAGGED
+ operating = TRUE
+ flick("[src.base_state]spark", src)
+ playsound(src, "sparks", 75, 1)
+ addtimer(CALLBACK(src, .proc/open_windows_me), 6)
+ return TRUE
+
+/obj/machinery/door/window/proc/open_windows_me()
+ operating = FALSE
+ desc += " Its access panel is smoking slightly."
+ open(2)
/obj/machinery/door/window/attackby(obj/item/I, mob/living/user, params)
diff --git a/code/game/machinery/embedded_controller/access_controller.dm b/code/game/machinery/embedded_controller/access_controller.dm
index 70ce3d36ae..3b9322d207 100644
--- a/code/game/machinery/embedded_controller/access_controller.dm
+++ b/code/game/machinery/embedded_controller/access_controller.dm
@@ -26,6 +26,7 @@
findObjsByTag()
/obj/machinery/doorButtons/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
@@ -33,6 +34,7 @@
req_one_access = list()
playsound(src, "sparks", 100, 1)
to_chat(user, "You short out the access controller.")
+ return TRUE
/obj/machinery/doorButtons/proc/removeMe()
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index 8f0d56a49e..5c2676c2b9 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -97,6 +97,7 @@
alarm()
/obj/machinery/firealarm/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
@@ -104,6 +105,7 @@
user.visible_message("Sparks fly out of [src]!",
"You emag [src], disabling its thermal sensors.")
playsound(src, "sparks", 50, 1)
+ return TRUE
/obj/machinery/firealarm/temperature_expose(datum/gas_mixture/air, temperature, volume)
if((temperature > T0C + 200 || temperature < BODYTEMP_COLD_DAMAGE_LIMIT) && (last_alarm+FIREALARM_COOLDOWN < world.time) && !(obj_flags & EMAGGED) && detecting && !stat)
diff --git a/code/game/machinery/gulag_item_reclaimer.dm b/code/game/machinery/gulag_item_reclaimer.dm
index f6cb58bbbc..f51c145635 100644
--- a/code/game/machinery/gulag_item_reclaimer.dm
+++ b/code/game/machinery/gulag_item_reclaimer.dm
@@ -9,7 +9,6 @@
idle_power_usage = 100
active_power_usage = 2500
var/list/stored_items = list()
- var/obj/item/card/id/prisoner/inserted_id = null
var/obj/machinery/gulag_teleporter/linked_teleporter = null
/obj/machinery/gulag_item_reclaimer/Destroy()
@@ -18,28 +17,15 @@
I.forceMove(get_turf(src))
if(linked_teleporter)
linked_teleporter.linked_reclaimer = null
- if(inserted_id)
- inserted_id.forceMove(get_turf(src))
- inserted_id = null
return ..()
/obj/machinery/gulag_item_reclaimer/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED) // emagging lets anyone reclaim all the items
return
req_access = list()
obj_flags |= EMAGGED
-
-/obj/machinery/gulag_item_reclaimer/attackby(obj/item/I, mob/user)
- if(istype(I, /obj/item/card/id))
- if(!inserted_id)
- if(!user.transferItemToLoc(I, src))
- return
- inserted_id = I
- to_chat(user, "You insert [I].")
- return
- else
- to_chat(user, "There's an ID inserted already.")
- return ..()
+ return TRUE
/obj/machinery/gulag_item_reclaimer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
@@ -55,15 +41,19 @@
if(allowed(user))
can_reclaim = TRUE
- if(inserted_id)
- data["id"] = inserted_id
- data["id_name"] = inserted_id.registered_name
- if(inserted_id.points >= inserted_id.goal)
+ var/obj/item/card/id/I = user.get_idcard(TRUE)
+ if(istype(I, /obj/item/card/id/prisoner))
+ var/obj/item/card/id/prisoner/P = I
+ if(P.points >= P.goal)
can_reclaim = TRUE
var/list/mobs = list()
for(var/i in stored_items)
var/mob/thismob = i
+ if(QDELETED(thismob))
+ say("Alert! Unable to locate vital signals of a previously processed prisoner. Ejecting equipment!")
+ drop_items(thismob)
+ continue
var/list/mob_info = list()
mob_info["name"] = thismob.real_name
mob_info["mob"] = "[REF(thismob)]"
@@ -78,16 +68,6 @@
/obj/machinery/gulag_item_reclaimer/ui_act(action, list/params)
switch(action)
- if("handle_id")
- if(inserted_id)
- usr.put_in_hands(inserted_id)
- inserted_id = null
- else
- var/obj/item/I = usr.is_holding_item_of_type(/obj/item/card/id)
- if(I)
- if(!usr.transferItemToLoc(I, src))
- return
- inserted_id = I
if("release_items")
var/mob/M = locate(params["mobref"])
if(M == usr || allowed(usr))
@@ -98,8 +78,9 @@
/obj/machinery/gulag_item_reclaimer/proc/drop_items(mob/user)
if(!stored_items[user])
return
+ var/drop_location = drop_location()
for(var/i in stored_items[user])
var/obj/item/W = i
stored_items[user] -= W
- W.forceMove(get_turf(src))
+ W.forceMove(drop_location)
stored_items -= user
diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm
index 8be7becfdd..1fccadda21 100644
--- a/code/game/machinery/harvester.dm
+++ b/code/game/machinery/harvester.dm
@@ -158,11 +158,13 @@
open_machine()
/obj/machinery/harvester/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
allow_living = TRUE
to_chat(user, "You overload [src]'s lifesign scanners.")
+ return TRUE
/obj/machinery/harvester/container_resist(mob/living/user)
if(!harvesting)
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index 84a688c724..b217c14e53 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -145,7 +145,7 @@
return
// If the human is losing too much blood, beep.
- if(attached.blood_volume < BLOOD_VOLUME_SAFE && prob(5))
+ if(attached.blood_volume < ( (BLOOD_VOLUME_SAFE*attached.blood_ratio) && prob(5) ) )
visible_message("[src] beeps loudly.")
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
attached.transfer_blood_to(beaker, amount)
@@ -218,4 +218,4 @@
to_chat(user, "[attached ? attached : "No one"] is attached.")
#undef IV_TAKING
-#undef IV_INJECTING
\ No newline at end of file
+#undef IV_INJECTING
diff --git a/code/game/machinery/limbgrower.dm b/code/game/machinery/limbgrower.dm
index a3250fe1b0..59806e97a4 100644
--- a/code/game/machinery/limbgrower.dm
+++ b/code/game/machinery/limbgrower.dm
@@ -215,6 +215,7 @@
return dat
/obj/machinery/limbgrower/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED)
return
for(var/id in SSresearch.techweb_designs)
@@ -223,3 +224,4 @@
stored_research.add_design(D)
to_chat(user, "A warning flashes onto the screen, stating that safety overrides have been deactivated!")
obj_flags |= EMAGGED
+ return TRUE
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index b0204ddeb8..b0a75c99dc 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -290,6 +290,7 @@
return ..()
/obj/machinery/porta_turret/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED)
return
to_chat(user, "You short out [src]'s threat assessment circuits.")
@@ -300,6 +301,7 @@
update_icon()
sleep(60) //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit
on = TRUE //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here
+ return TRUE
/obj/machinery/porta_turret/emp_act(severity)
@@ -837,6 +839,7 @@
to_chat(user, "Access denied.")
/obj/machinery/turretid/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED)
return
to_chat(user, "You short out the turret controls' access analysis module.")
@@ -844,6 +847,7 @@
locked = FALSE
if(user && user.machine == src)
attack_hand(user)
+ return TRUE
/obj/machinery/turretid/attack_ai(mob/user)
if(!ailock || IsAdminGhost(user))
diff --git a/code/game/machinery/porta_turret/portable_turret_cover.dm b/code/game/machinery/porta_turret/portable_turret_cover.dm
index 6ff795c1cc..afb00d4ee2 100644
--- a/code/game/machinery/porta_turret/portable_turret_cover.dm
+++ b/code/game/machinery/porta_turret/portable_turret_cover.dm
@@ -86,10 +86,13 @@
. = 0
/obj/machinery/porta_turret_cover/emag_act(mob/user)
- if(!(parent_turret.obj_flags & EMAGGED))
- to_chat(user, "You short out [parent_turret]'s threat assessment circuits.")
- visible_message("[parent_turret] hums oddly...")
- parent_turret.obj_flags |= EMAGGED
- parent_turret.on = 0
- spawn(40)
- parent_turret.on = 1
+ . = ..()
+ if(parent_turret.obj_flags & EMAGGED)
+ return
+ to_chat(user, "You short out [parent_turret]'s threat assessment circuits.")
+ visible_message("[parent_turret] hums oddly...")
+ parent_turret.obj_flags |= EMAGGED
+ parent_turret.on = 0
+ spawn(40)
+ parent_turret.on = 1
+ return TRUE
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index ff40a8539a..9d431487e0 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -65,6 +65,7 @@
return ..()
/obj/machinery/recycler/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
@@ -73,6 +74,7 @@
update_icon()
playsound(src, "sparks", 75, 1, -1)
to_chat(user, "You use the cryptographic sequencer on [src].")
+ return TRUE
/obj/machinery/recycler/update_icon()
..()
diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm
index e2aebd2370..fc6577a4f1 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -195,6 +195,7 @@
return ..()
/obj/machinery/shieldgen/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED)
to_chat(user, "The access controller is damaged!")
return
@@ -202,6 +203,7 @@
locked = FALSE
playsound(src, "sparks", 100, 1)
to_chat(user, "You short out the access controller.")
+ return TRUE
/obj/machinery/shieldgen/update_icon()
if(active)
@@ -387,6 +389,7 @@
add_fingerprint(user)
/obj/machinery/shieldwallgen/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED)
to_chat(user, "The access controller is damaged!")
return
@@ -394,6 +397,7 @@
locked = FALSE
playsound(src, "sparks", 100, 1)
to_chat(user, "You short out the access controller.")
+ return TRUE
//////////////Containment Field START
/obj/machinery/shieldwall
diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm
index 298587cdea..4b73032a8a 100644
--- a/code/game/machinery/slotmachine.dm
+++ b/code/game/machinery/slotmachine.dm
@@ -99,6 +99,7 @@
return ..()
/obj/machinery/computer/slot_machine/emag_act()
+ . = ..()
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
@@ -106,6 +107,7 @@
spark_system.set_up(4, 0, src.loc)
spark_system.start()
playsound(src, "sparks", 50, 1)
+ return TRUE
/obj/machinery/computer/slot_machine/ui_interact(mob/living/user)
. = ..()
diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm
index b11c6c102d..ebb40148d8 100644
--- a/code/game/machinery/telecomms/computers/message.dm
+++ b/code/game/machinery/telecomms/computers/message.dm
@@ -42,21 +42,23 @@
return ..()
/obj/machinery/computer/message_monitor/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED)
return
- if(!isnull(linkedServer))
- obj_flags |= EMAGGED
- screen = 2
- spark_system.set_up(5, 0, src)
- spark_system.start()
- var/obj/item/paper/monitorkey/MK = new(loc, linkedServer)
- // Will help make emagging the console not so easy to get away with.
- MK.info += "
�%@%(*$%&(�&?*(%&�/{}"
- var/time = 100 * length(linkedServer.decryptkey)
- addtimer(CALLBACK(src, .proc/UnmagConsole), time)
- message = rebootmsg
- else
+ if(isnull(linkedServer))
to_chat(user, "A no server error appears on the screen.")
+ return
+ obj_flags |= EMAGGED
+ screen = 2
+ spark_system.set_up(5, 0, src)
+ spark_system.start()
+ var/obj/item/paper/monitorkey/MK = new(loc, linkedServer)
+ // Will help make emagging the console not so easy to get away with.
+ MK.info += "
�%@%(*$%&(�&?*(%&�/{}"
+ var/time = 100 * length(linkedServer.decryptkey)
+ addtimer(CALLBACK(src, .proc/UnmagConsole), time)
+ message = rebootmsg
+ return TRUE
/obj/machinery/computer/message_monitor/New()
. = ..()
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index 64081a77e4..1f1f13ee22 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -68,16 +68,16 @@
if (ismovableatom(M))
if(do_teleport(M, com.target, channel = TELEPORT_CHANNEL_BLUESPACE))
use_power(5000)
- if(!calibrated && prob(30 - ((accurate) * 10))) //oh dear a problem
- log_game("[M] ([key_name(M)]) was turned into a fly person")
- if(ishuman(M))//don't remove people from the round randomly you jerks
- var/mob/living/carbon/human/human = M
- if(human.dna && human.dna.species.id == "human")
- to_chat(M, "You hear a buzzing in your ears.")
- human.set_species(/datum/species/fly)
- human.apply_effect((rand(120 - accurate * 40, 180 - accurate * 60)), EFFECT_IRRADIATE, 0)
- calibrated = 0
+ if(!calibrated && iscarbon(M) && prob(30 - ((accurate) * 10))) //oh dear a problem
+ var/mob/living/carbon/C = M
+ if(C.dna?.species && C.dna.species.id != "fly" && !HAS_TRAIT(C, TRAIT_RADIMMUNE))
+ to_chat(C, "You hear a buzzing in your ears.")
+ C.set_species(/datum/species/fly)
+ log_game("[C] ([key_name(C)]) was turned into a fly person")
+ C.apply_effect((rand(120 - accurate * 40, 180 - accurate * 60)), EFFECT_IRRADIATE, 0)
+
+ calibrated = FALSE
return
/obj/machinery/teleport/hub/update_icon()
diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm
index 7896d7aa35..cd7051d074 100644
--- a/code/game/mecha/combat/durand.dm
+++ b/code/game/mecha/combat/durand.dm
@@ -20,3 +20,6 @@
..()
defense_action.Remove(user)
+/obj/mecha/combat/Initialize()
+ . = ..()
+ trackers += new /obj/item/mecha_parts/mecha_tracking(src)
diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm
index 95137938d0..f9fa2544b8 100644
--- a/code/game/mecha/combat/gygax.dm
+++ b/code/game/mecha/combat/gygax.dm
@@ -63,3 +63,6 @@
..()
thrusters_action.Remove(user)
+/obj/mecha/combat/Initialize()
+ . = ..()
+ trackers += new /obj/item/mecha_parts/mecha_tracking(src)
diff --git a/code/game/mecha/combat/honker.dm b/code/game/mecha/combat/honker.dm
index 125aecd667..4c32e9c367 100644
--- a/code/game/mecha/combat/honker.dm
+++ b/code/game/mecha/combat/honker.dm
@@ -154,4 +154,6 @@
color = color+pick(colors)
return color
-
+/obj/mecha/combat/Initialize()
+ . = ..()
+ trackers += new /obj/item/mecha_parts/mecha_tracking(src)
diff --git a/code/game/mecha/combat/phazon.dm b/code/game/mecha/combat/phazon.dm
index f5f369c2ad..1264a647c4 100644
--- a/code/game/mecha/combat/phazon.dm
+++ b/code/game/mecha/combat/phazon.dm
@@ -28,3 +28,6 @@
switch_damtype_action.Remove(user)
phasing_action.Remove(user)
+/obj/mecha/combat/Initialize()
+ . = ..()
+ trackers += new /obj/item/mecha_parts/mecha_tracking(src)
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index 01e304872f..e1dc80911f 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -64,10 +64,15 @@
/obj/machinery/mecha_part_fabricator/emag_act()
+ . = ..()
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
req_access = list()
+ INVOKE_ASYNC(src, .proc/error_action_sucessful)
+ return TRUE
+
+/obj/machinery/mecha_part_fabricator/proc/error_action_sucessful()
say("DB error \[Code 0x00F1\]")
sleep(10)
say("Attempting auto-repair...")
diff --git a/code/game/mecha/mecha_control_console.dm b/code/game/mecha/mecha_control_console.dm
index 9498eec3da..18c9b3eb2f 100644
--- a/code/game/mecha/mecha_control_console.dm
+++ b/code/game/mecha/mecha_control_console.dm
@@ -109,7 +109,7 @@
var/obj/mecha/M = in_mecha()
if(M)
M.emp_act(EMP_HEAVY)
- addtimer(CALLBACK(src, /obj/item/mecha_parts/mecha_tracking/proc/recharge), 5 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
+ addtimer(CALLBACK(src, /obj/item/mecha_parts/mecha_tracking/proc/recharge), 15 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
recharging = 1
/obj/item/mecha_parts/mecha_tracking/proc/recharge()
diff --git a/code/game/objects/effects/alien_acid.dm b/code/game/objects/effects/alien_acid.dm
index 1a605d64b0..3b5a029df4 100644
--- a/code/game/objects/effects/alien_acid.dm
+++ b/code/game/objects/effects/alien_acid.dm
@@ -17,7 +17,7 @@
target = get_turf(src)
if(acid_amt)
- acid_level = min(acid_amt*acid_pwr, 12000) //capped so the acid effect doesn't last a half hour on the floor.
+ acid_level = min( (CLAMP(round(acid_amt, 1), 0, INFINITY)) *acid_pwr, 12000) //capped so the acid effect doesn't last a half hour on the floor.
//handle APCs and newscasters and stuff nicely
pixel_x = target.pixel_x + rand(-4,4)
diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm
index cc69b88cc4..9f072c48b6 100644
--- a/code/game/objects/effects/decals/cleanable/misc.dm
+++ b/code/game/objects/effects/decals/cleanable/misc.dm
@@ -42,6 +42,9 @@
/obj/effect/decal/cleanable/glass/ex_act()
qdel(src)
+/obj/effect/decal/cleanable/glass/plasma
+ icon_state = "plasmatiny"
+
/obj/effect/decal/cleanable/dirt
name = "dirt"
desc = "Someone should clean that up."
diff --git a/code/game/objects/effects/decals/turfdecal/tilecoloring.dm b/code/game/objects/effects/decals/turfdecal/tilecoloring.dm
index 1708753dc1..1e755bc7e9 100644
--- a/code/game/objects/effects/decals/turfdecal/tilecoloring.dm
+++ b/code/game/objects/effects/decals/turfdecal/tilecoloring.dm
@@ -36,4 +36,203 @@
/obj/effect/turf_decal/tile/neutral
name = "neutral corner"
color = "#D4D4D4"
- alpha = 50
\ No newline at end of file
+ alpha = 50
+
+/obj/effect/turf_decal/trimline
+ layer = TURF_PLATING_DECAL_LAYER
+ alpha = 110
+ icon_state = "trimline_box"
+
+/obj/effect/turf_decal/trimline/white
+ color = "#FFFFFF"
+
+/obj/effect/turf_decal/trimline/white/line
+ name = "trim decal"
+ icon_state = "trimline"
+
+/obj/effect/turf_decal/trimline/white/corner
+ icon_state = "trimline_corner"
+
+/obj/effect/turf_decal/trimline/white/end
+ icon_state = "trimline_end"
+
+/obj/effect/turf_decal/trimline/white/filled
+ icon_state = "trimline_box_fill"
+
+/obj/effect/turf_decal/trimline/white/filled/line
+ icon_state = "trimline_fill"
+
+/obj/effect/turf_decal/trimline/white/filled/corner
+ icon_state = "trimline_corner_fill"
+
+/obj/effect/turf_decal/trimline/white/filled/end
+ icon_state = "trimline_end_fill"
+
+/obj/effect/turf_decal/trimline/red
+ color = "#DE3A3A"
+
+/obj/effect/turf_decal/trimline/red/line
+ icon_state = "trimline"
+
+/obj/effect/turf_decal/trimline/red/corner
+ icon_state = "trimline_corner"
+
+/obj/effect/turf_decal/trimline/red/end
+ icon_state = "trimline_end"
+
+/obj/effect/turf_decal/trimline/red/filled
+ icon_state = "trimline_box_fill"
+
+/obj/effect/turf_decal/trimline/red/filled/line
+ icon_state = "trimline_fill"
+
+/obj/effect/turf_decal/trimline/red/filled/corner
+ icon_state = "trimline_corner_fill"
+
+/obj/effect/turf_decal/trimline/red/filled/end
+ icon_state = "trimline_end_fill"
+
+/obj/effect/turf_decal/trimline/green
+ color = "#9FED58"
+
+/obj/effect/turf_decal/trimline/green/line
+ icon_state = "trimline"
+
+/obj/effect/turf_decal/trimline/green/corner
+ icon_state = "trimline_corner"
+
+/obj/effect/turf_decal/trimline/green/end
+ icon_state = "trimline_end"
+
+/obj/effect/turf_decal/trimline/green/filled
+ icon_state = "trimline_box_fill"
+
+/obj/effect/turf_decal/trimline/green/filled/line
+ icon_state = "trimline_fill"
+
+/obj/effect/turf_decal/trimline/green/filled/corner
+ icon_state = "trimline_corner_fill"
+
+/obj/effect/turf_decal/trimline/green/filled/end
+ icon_state = "trimline_end_fill"
+
+/obj/effect/turf_decal/trimline/blue
+ color = "#52B4E9"
+
+/obj/effect/turf_decal/trimline/blue/line
+ icon_state = "trimline"
+
+/obj/effect/turf_decal/trimline/blue/corner
+ icon_state = "trimline_corner"
+
+/obj/effect/turf_decal/trimline/blue/end
+ icon_state = "trimline_end"
+
+/obj/effect/turf_decal/trimline/blue/filled
+ icon_state = "trimline_box_fill"
+
+/obj/effect/turf_decal/trimline/blue/filled/line
+ icon_state = "trimline_fill"
+
+/obj/effect/turf_decal/trimline/blue/filled/corner
+ icon_state = "trimline_corner_fill"
+
+/obj/effect/turf_decal/trimline/blue/filled/end
+ icon_state = "trimline_end_fill"
+
+/obj/effect/turf_decal/trimline/yellow
+ color = "#EFB341"
+
+/obj/effect/turf_decal/trimline/yellow/line
+ icon_state = "trimline"
+
+/obj/effect/turf_decal/trimline/yellow/corner
+ icon_state = "trimline_corner"
+
+/obj/effect/turf_decal/trimline/yellow/end
+ icon_state = "trimline_end"
+
+/obj/effect/turf_decal/trimline/yellow/filled
+ icon_state = "trimline_box_fill"
+
+/obj/effect/turf_decal/trimline/yellow/filled/line
+ icon_state = "trimline_fill"
+
+/obj/effect/turf_decal/trimline/yellow/filled/corner
+ icon_state = "trimline_corner_fill"
+
+/obj/effect/turf_decal/trimline/yellow/filled/end
+ icon_state = "trimline_end_fill"
+
+/obj/effect/turf_decal/trimline/purple
+ color = "#D381C9"
+
+/obj/effect/turf_decal/trimline/purple/line
+ icon_state = "trimline"
+
+/obj/effect/turf_decal/trimline/purple/corner
+ icon_state = "trimline_corner"
+
+/obj/effect/turf_decal/trimline/purple/end
+ icon_state = "trimline_end"
+
+/obj/effect/turf_decal/trimline/purple/filled
+ icon_state = "trimline_box_fill"
+
+/obj/effect/turf_decal/trimline/purple/filled/line
+ icon_state = "trimline_fill"
+
+/obj/effect/turf_decal/trimline/purple/filled/corner
+ icon_state = "trimline_corner_fill"
+
+/obj/effect/turf_decal/trimline/purple/filled/end
+ icon_state = "trimline_end_fill"
+
+/obj/effect/turf_decal/trimline/brown
+ color = "#A46106"
+
+/obj/effect/turf_decal/trimline/brown/line
+ icon_state = "trimline"
+
+/obj/effect/turf_decal/trimline/brown/corner
+ icon_state = "trimline_corner"
+
+/obj/effect/turf_decal/trimline/brown/end
+ icon_state = "trimline_end"
+
+/obj/effect/turf_decal/trimline/brown/filled
+ icon_state = "trimline_box_fill"
+
+/obj/effect/turf_decal/trimline/brown/filled/line
+ icon_state = "trimline_fill"
+
+/obj/effect/turf_decal/trimline/brown/filled/corner
+ icon_state = "trimline_corner_fill"
+
+/obj/effect/turf_decal/trimline/brown/filled/end
+ icon_state = "trimline_end_fill"
+
+/obj/effect/turf_decal/trimline/neutral
+ color = "#D4D4D4"
+ alpha = 50
+
+/obj/effect/turf_decal/trimline/neutral/line
+ icon_state = "trimline"
+
+/obj/effect/turf_decal/trimline/neutral/corner
+ icon_state = "trimline_corner"
+
+/obj/effect/turf_decal/trimline/neutral/end
+ icon_state = "trimline_end"
+
+/obj/effect/turf_decal/trimline/neutral/filled
+ icon_state = "trimline_box_fill"
+
+/obj/effect/turf_decal/trimline/neutral/filled/line
+ icon_state = "trimline_fill"
+
+/obj/effect/turf_decal/trimline/neutral/filled/corner
+ icon_state = "trimline_corner_fill"
+
+/obj/effect/turf_decal/trimline/brown/filled/end
+ icon_state = "trimline_end_fill"
\ No newline at end of file
diff --git a/code/game/objects/effects/spawners/bundle.dm b/code/game/objects/effects/spawners/bundle.dm
index 2fe8d2a460..b9acba70d9 100644
--- a/code/game/objects/effects/spawners/bundle.dm
+++ b/code/game/objects/effects/spawners/bundle.dm
@@ -133,7 +133,7 @@
/obj/effect/spawner/bundle/costume/holiday_priest
name = "holiday priest costume spawner"
items = list(
- /obj/item/clothing/suit/holidaypriest)
+ /obj/item/clothing/suit/chaplain/holidaypriest)
/obj/effect/spawner/bundle/costume/marisawizard
name = "marisa wizard costume spawner"
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index e17fe20977..c98cef2b87 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -33,6 +33,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/usesound = null
var/throwhitsound = null
var/w_class = WEIGHT_CLASS_NORMAL
+ var/total_mass //Total mass in arbitrary pound-like values. If there's no balance reasons for an item to have otherwise, this var should be the item's weight in pounds.
var/slot_flags = 0 //This is used to determine on which slots an item can fit.
pass_flags = PASSTABLE
pressure_resistance = 4
@@ -67,6 +68,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/strip_delay = 40 //In deciseconds, how long an item takes to remove from another person
var/breakouttime = 0
var/list/materials
+ var/reskinned = FALSE
var/list/attack_verb //Used in attackby() to say how something was attacked "[x] has been [z.attack_verb] by [y] with [z]"
var/list/species_exception = null // list() of species types, if a species cannot put items in a certain slot, but species type is in list, it will be able to wear that item
diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm
index 1ff3c7df9f..cf706359f7 100644
--- a/code/game/objects/items/RCD.dm
+++ b/code/game/objects/items/RCD.dm
@@ -37,6 +37,7 @@ RLD
var/has_ammobar = FALSE //controls whether or not does update_icon apply ammo indicator overlays
var/ammo_sections = 10 //amount of divisions in the ammo indicator overlay/number of ammo indicator states
var/custom_range = 7
+ var/upgrade = FALSE
/obj/item/construction/Initialize()
. = ..()
@@ -82,6 +83,11 @@ RLD
loaded = loadwithsheets(W, sheetmultiplier * 0.25, user) // 1 matter for 1 floortile, as 4 tiles are produced from 1 metal
if(loaded)
to_chat(user, "[src] now holds [matter]/[max_matter] matter-units.")
+ else if(istype(W, /obj/item/rcd_upgrade))
+ to_chat(user, "You upgrade the RCD with the [W]!")
+ upgrade = TRUE
+ playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
+ qdel(W)
else
return ..()
update_icon() //ensures that ammo counters (if present) get updated
@@ -148,6 +154,7 @@ RLD
has_ammobar = TRUE
var/mode = 1
var/ranged = FALSE
+ var/computer_dir = 1
var/airlock_type = /obj/machinery/door/airlock
var/airlock_glass = FALSE // So the floor's rcd_act knows how much ammo to use
var/window_type = /obj/structure/window/fulltile
@@ -270,6 +277,28 @@ RLD
return FALSE
return TRUE
+/obj/item/construction/rcd/proc/change_computer_dir(mob/user)
+ if(!user)
+ return
+ var/list/computer_dirs = list(
+ "NORTH" = image(icon = 'icons/mob/radial.dmi', icon_state = "cnorth"),
+ "EAST" = image(icon = 'icons/mob/radial.dmi', icon_state = "ceast"),
+ "SOUTH" = image(icon = 'icons/mob/radial.dmi', icon_state = "csouth"),
+ "WEST" = image(icon = 'icons/mob/radial.dmi', icon_state = "cwest")
+ )
+ var/computerdirs = show_radial_menu(user, src, computer_dirs, custom_check = CALLBACK(src, .proc/check_menu, user), require_near = TRUE, tooltips = TRUE)
+ if(!check_menu(user))
+ return
+ switch(computerdirs)
+ if("NORTH")
+ computer_dir = 1
+ if("EAST")
+ computer_dir = 4
+ if("SOUTH")
+ computer_dir = 2
+ if("WEST")
+ computer_dir = 8
+
/obj/item/construction/rcd/proc/change_airlock_setting(mob/user)
if(!user)
return
@@ -434,10 +463,15 @@ RLD
..()
var/list/choices = list(
"Airlock" = image(icon = 'icons/mob/radial.dmi', icon_state = "airlock"),
- "Deconstruct" = image(icon= 'icons/mob/radial.dmi', icon_state = "delete"),
"Grilles & Windows" = image(icon = 'icons/mob/radial.dmi', icon_state = "grillewindow"),
"Floors & Walls" = image(icon = 'icons/mob/radial.dmi', icon_state = "wallfloor")
)
+ if(upgrade)
+ choices += list(
+ "Deconstruct" = image(icon= 'icons/mob/radial.dmi', icon_state = "delete"),
+ "Machine Frames" = image(icon = 'icons/mob/radial.dmi', icon_state = "machine"),
+ "Computer Frames" = image(icon = 'icons/mob/radial.dmi', icon_state = "computer_dir"),
+ )
if(mode == RCD_AIRLOCK)
choices += list(
"Change Access" = image(icon = 'icons/mob/radial.dmi', icon_state = "access"),
@@ -459,6 +493,12 @@ RLD
mode = RCD_DECONSTRUCT
if("Grilles & Windows")
mode = RCD_WINDOWGRILLE
+ if("Machine Frames")
+ mode = RCD_MACHINE
+ if("Computer Frames")
+ mode = RCD_COMPUTER
+ change_computer_dir(user)
+ return
if("Change Access")
change_airlock_access(user)
return
@@ -511,6 +551,7 @@ RLD
no_ammo_message = "Insufficient charge."
desc = "A device used to rapidly build walls and floors."
canRturf = TRUE
+ upgrade = TRUE
/obj/item/construction/rcd/borg/useResource(amount, mob/user)
@@ -542,6 +583,9 @@ RLD
/obj/item/construction/rcd/loaded
matter = 160
+/obj/item/construction/rcd/loaded/upgraded
+ upgrade = TRUE
+
/obj/item/construction/rcd/combat
name = "Combat RCD"
desc = "A device used to rapidly build and deconstruct. Reload with metal, plasteel, glass or compressed matter cartridges. This RCD has been upgraded to be able to remove Rwalls!"
@@ -582,7 +626,7 @@ RLD
name = "admin RCD"
max_matter = INFINITY
matter = INFINITY
-
+ upgrade = TRUE
// Ranged RCD
@@ -776,6 +820,12 @@ RLD
return TRUE
return FALSE
+/obj/item/rcd_upgrade
+ name = "RCD advanced design disk"
+ desc = "It contains the design for machine frames, computer frames, and deconstruction."
+ icon = 'icons/obj/module.dmi'
+ icon_state = "datadisk3"
+
#undef GLOW_MODE
#undef LIGHT_MODE
#undef REMOVE_MODE
diff --git a/code/game/objects/items/RSF.dm b/code/game/objects/items/RSF.dm
index f0d15cc3a2..01205ee889 100644
--- a/code/game/objects/items/RSF.dm
+++ b/code/game/objects/items/RSF.dm
@@ -134,12 +134,14 @@ RSF
return
/obj/item/cookiesynth/emag_act(mob/user)
+ . = ..()
obj_flags ^= EMAGGED
if(obj_flags & EMAGGED)
to_chat(user, "You short out [src]'s reagent safety checker!")
else
to_chat(user, "You reset [src]'s reagent safety checker!")
- toxin = 0
+ toxin = FALSE
+ return TRUE
/obj/item/cookiesynth/attack_self(mob/user)
var/mob/living/silicon/robot/P = null
diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm
index e5f40d7c52..875a4bd04f 100644
--- a/code/game/objects/items/cards_ids.dm
+++ b/code/game/objects/items/cards_ids.dm
@@ -93,34 +93,22 @@
/obj/item/card/emag/afterattack(atom/target, mob/user, proximity)
. = ..()
var/atom/A = target
- if(!proximity && prox_check)
+ if(!proximity && prox_check || !(isobj(A) || issilicon(A) || isbot(A) || isdrone(A)))
+ return
+ if(istype(A, /obj/item/storage) && !(istype(A, /obj/item/storage/lockbox) || istype(A, /obj/item/storage/pod)))
return
- //Citadel changes: modular code misfiring, so we're bypassing into main code.
if(!uses)
user.visible_message("[src] emits a weak spark. It's burnt out!")
playsound(src, 'sound/effects/light_flicker.ogg', 100, 1)
return
else if(uses <= 3)
playsound(src, 'sound/effects/light_flicker.ogg', 30, 1) //Tiiiiiiny warning sound to let ya know your emag's almost dead
-
- if(isturf(A))
+ if(!A.emag_act(user))
return
- if(istype(A,/obj/item/storage/lockbox) || istype(A, /obj/item/storage/pod))
- A.emag_act(user)
- uses = max(uses - 1, 0)
- if(!uses)
- user.visible_message("[src] fizzles and sparks. It seems like it's out of charges.")
- playsound(src, 'sound/effects/light_flicker.ogg', 100, 1)
- if(istype(A,/obj/item/storage))
- return
- if(!(isobj(A) || issilicon(A) || isbot(A) || isdrone(A)))
- return
- else
- A.emag_act(user)
- uses = max(uses - 1, 0)
- if(!uses)
- user.visible_message("[src] fizzles and sparks. It seems like it's out of charges.")
- playsound(src, 'sound/effects/light_flicker.ogg', 100, 1)
+ uses = max(uses - 1, 0)
+ if(!uses)
+ user.visible_message("[src] fizzles and sparks. It seems like it's out of charges.")
+ playsound(src, 'sound/effects/light_flicker.ogg', 100, 1)
/obj/item/card/emagfake
diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm
index 000c52ae43..09a128c558 100644
--- a/code/game/objects/items/cigs_lighters.dm
+++ b/code/game/objects/items/cigs_lighters.dm
@@ -764,20 +764,22 @@ CIGARETTE PACKETS ARE IN FANCY.DM
..()
/obj/item/clothing/mask/vape/emag_act(mob/user)// I WON'T REGRET WRITTING THIS, SURLY.
- if(screw)
- if(!(obj_flags & EMAGGED))
- cut_overlays()
- obj_flags |= EMAGGED
- super = FALSE
- to_chat(user, "You maximize the voltage of [src].")
- add_overlay("vapeopen_high")
- var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread //for effect
- sp.set_up(5, 1, src)
- sp.start()
- else
- to_chat(user, "[src] is already emagged!")
- else
+ . = ..()
+ if(!screw)
to_chat(user, "You need to open the cap to do that.")
+ return
+ if(obj_flags & EMAGGED)
+ to_chat(user, "[src] is already emagged!")
+ return
+ cut_overlays()
+ obj_flags |= EMAGGED
+ super = FALSE
+ to_chat(user, "You maximize the voltage of [src].")
+ add_overlay("vapeopen_high")
+ var/datum/effect_system/spark_spread/sp = new /datum/effect_system/spark_spread //for effect
+ sp.set_up(5, 1, src)
+ sp.start()
+ return TRUE
/obj/item/clothing/mask/vape/attack_self(mob/user)
if(reagents.total_volume > 0)
diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm
index 7d2ffe0a02..c260a95afd 100644
--- a/code/game/objects/items/circuitboards/computer_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm
@@ -162,10 +162,11 @@
/obj/item/circuitboard/computer/prisoner
name = "Prisoner Management Console (Computer Board)"
- build_path = /obj/machinery/computer/prisoner
+ build_path = /obj/machinery/computer/prisoner/management
+
/obj/item/circuitboard/computer/gulag_teleporter_console
name = "Labor Camp teleporter console (Computer Board)"
- build_path = /obj/machinery/computer/gulag_teleporter_computer
+ build_path = /obj/machinery/computer/prisoner/gulag_teleporter_computer
/obj/item/circuitboard/computer/rdconsole/production
name = "R&D Console Production Only (Computer Board)"
@@ -217,10 +218,13 @@
to_chat(user, "The spectrum chip is unresponsive.")
/obj/item/circuitboard/computer/cargo/emag_act(mob/living/user)
- if(!(obj_flags & EMAGGED))
- contraband = TRUE
- obj_flags |= EMAGGED
- to_chat(user, "You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.")
+ . = ..()
+ if(obj_flags & EMAGGED)
+ return
+ contraband = TRUE
+ obj_flags |= EMAGGED
+ to_chat(user, "You adjust [src]'s routing and receiver spectrum, unlocking special supplies and contraband.")
+ return TRUE
/obj/item/circuitboard/computer/cargo/express
name = "Express Supply Console (Computer Board)"
@@ -234,8 +238,12 @@
obj_flags &= ~EMAGGED
/obj/item/circuitboard/computer/cargo/express/emag_act(mob/living/user)
- to_chat(user, "You change the routing protocols, allowing the Drop Pod to land anywhere on the station.")
- obj_flags |= EMAGGED
+ . = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
+ if(obj_flags & EMAGGED)
+ return
+ to_chat(user, "You change the routing protocols, allowing the Drop Pod to land anywhere on the station.")
+ obj_flags |= EMAGGED
+ return TRUE
/obj/item/circuitboard/computer/cargo/request
name = "Supply Request Console (Computer Board)"
@@ -366,4 +374,4 @@
/obj/item/circuitboard/computer/nanite_cloud_controller
name = "Nanite Cloud Control (Computer Board)"
- build_path = /obj/machinery/computer/nanite_cloud_controller
\ No newline at end of file
+ build_path = /obj/machinery/computer/nanite_cloud_controller
diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm
index 55e75b3992..5bef86c6d2 100644
--- a/code/game/objects/items/defib.dm
+++ b/code/game/objects/items/defib.dm
@@ -140,12 +140,10 @@
return ..()
/obj/item/defibrillator/emag_act(mob/user)
- if(safety)
- safety = FALSE
- to_chat(user, "You silently disable [src]'s safety protocols with the cryptographic sequencer.")
- else
- safety = TRUE
- to_chat(user, "You silently enable [src]'s safety protocols with the cryptographic sequencer.")
+ . = ..()
+ safety = !safety
+ to_chat(user, "You silently [safety ? "enable" : "disable"] [src]'s safety protocols with the cryptographic sequencer.")
+ return TRUE
/obj/item/defibrillator/emp_act(severity)
. = ..()
diff --git a/code/game/objects/items/devices/PDA/cart.dm b/code/game/objects/items/devices/PDA/cart.dm
index bf352e8eb7..3885a1f4d9 100644
--- a/code/game/objects/items/devices/PDA/cart.dm
+++ b/code/game/objects/items/devices/PDA/cart.dm
@@ -498,6 +498,23 @@ Code:
else
menu += "[ldat]"
+ menu += "Pimpin' Ride:"
+
+ ldat = null
+ for (var/obj/vehicle/ridden/janicart/M in world)
+ var/turf/ml = get_turf(M)
+
+ if(ml)
+ if (ml.z != cl.z)
+ continue
+ var/direction = get_dir(src, M)
+ ldat += "Ride - \[[ml.x],[ml.y] ([uppertext(dir2text(direction))])\] "
+
+ if (!ldat)
+ menu += "None"
+ else
+ menu += "[ldat]"
+
menu += "Located Janitorial Cart:"
ldat = null
diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm
index 7823e570e0..38133e37bc 100644
--- a/code/game/objects/items/devices/geiger_counter.dm
+++ b/code/game/objects/items/devices/geiger_counter.dm
@@ -192,13 +192,15 @@
update_icon()
/obj/item/geiger_counter/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED)
return
if(scanning)
to_chat(user, "Turn off [src] before you perform this action!")
- return 0
+ return
to_chat(user, "You override [src]'s radiation storing protocols. It will now generate small doses of radiation, and stored rads are now projected into creatures you scan.")
obj_flags |= EMAGGED
+ return TRUE
/obj/item/geiger_counter/cyborg
var/datum/component/mobhook
diff --git a/code/game/objects/items/devices/lightreplacer.dm b/code/game/objects/items/devices/lightreplacer.dm
index 6615ebe8a8..1e31f14cfd 100644
--- a/code/game/objects/items/devices/lightreplacer.dm
+++ b/code/game/objects/items/devices/lightreplacer.dm
@@ -149,9 +149,11 @@
to_chat(user, "You fill \the [src] with lights from \the [S]. " + status_string() + "")
/obj/item/lightreplacer/emag_act()
+ . = ..()
if(obj_flags & EMAGGED)
return
Emag()
+ return TRUE
/obj/item/lightreplacer/attack_self(mob/user)
to_chat(user, status_string())
diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm
index 347bb6894d..915fcac504 100644
--- a/code/game/objects/items/devices/megaphone.dm
+++ b/code/game/objects/items/devices/megaphone.dm
@@ -38,11 +38,13 @@
speech_args[SPEECH_SPANS] |= voicespan
/obj/item/megaphone/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED)
return
to_chat(user, "You overload \the [src]'s voice synthesizer.")
obj_flags |= EMAGGED
voicespan = list(SPAN_REALLYBIG, "userdanger")
+ return TRUE
/obj/item/megaphone/sec
name = "security megaphone"
diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm
index a3ab9153ce..207497922e 100644
--- a/code/game/objects/items/devices/multitool.dm
+++ b/code/game/objects/items/devices/multitool.dm
@@ -32,6 +32,24 @@
var/datum/integrated_io/selected_io = null //functional for integrated circuits.
var/mode = 0
+/obj/item/multitool/chaplain
+ name = "\improper hypertool"
+ desc = "Used for pulsing wires to test which to cut. Also emits microwaves to fry some brains!"
+ damtype = BRAIN
+ force = 18
+ armour_penetration = 35
+ hitsound = 'sound/effects/sparks4.ogg'
+ var/chaplain_spawnable = TRUE
+ total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
+ throw_speed = 3
+ throw_range = 4
+ throwforce = 10
+ obj_flags = UNIQUE_RENAME
+
+/obj/item/multitool/chaplain/Initialize()
+ . = ..()
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+
/obj/item/multitool/examine(mob/user)
..()
if(selected_io)
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 57b9e89af7..0059938720 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -163,7 +163,37 @@ SLIME SCANNER
msg += "\tSevere brain damage detected. Subject likely to have mental traumas.\n"
else if (M.getBrainLoss() >= 45)
msg += "\tBrain damage detected.\n"
- if(iscarbon(M))
+ if(ishuman(M) && advanced) // Should I make this not advanced?
+ var/mob/living/carbon/human/H = M
+ var/obj/item/organ/liver/L = H.getorganslot("liver")
+ if(L)
+ if(L.swelling > 20)
+ msg += "\tSubject is suffering from an enlarged liver.\n" //i.e. shrink their liver or give them a transplant.
+ else
+ msg += "\tSubject's liver is missing.\n"
+ var/obj/item/organ/tongue/T = H.getorganslot("tongue")
+ if(T)
+ if(T.damage > 40)
+ msg += "\tSubject is suffering from severe burn tissue on their tongue.\n" //i.e. their tongue is shot
+ if(T.name == "fluffy tongue")
+ msg += "\tSubject is suffering from a fluffified tongue. Suggested cure: Yamerol or a tongue transplant.\n"
+ else
+ msg += "\tSubject's tongue is missing.\n"
+ var/obj/item/organ/lungs/Lung = H.getorganslot("lungs")
+ if(Lung)
+ if(Lung.damage > 150)
+ msg += "\tSubject is suffering from acute emphysema leading to trouble breathing.\n" //i.e. Their lungs are shot
+ else
+ msg += "\tSubject's lungs have collapsed from trauma!\n"
+ var/obj/item/organ/genital/penis/P = H.getorganslot("penis")
+ if(P)
+ if(P.length>20)
+ msg += "\tSubject has a sizeable gentleman's organ at [P.length] inches.\n"
+ var/obj/item/organ/genital/breasts/Br = H.getorganslot("breasts")
+ if(Br)
+ if(Br.cached_size>5)
+ msg += "\tSubject has a sizeable bosom with a [Br.size] cup.\n"
+
var/mob/living/carbon/C = M
if(LAZYLEN(C.get_traumas()))
var/list/trauma_text = list()
@@ -183,7 +213,7 @@ SLIME SCANNER
msg += "\tSubject has the following physiological traits: [C.get_trait_string()].\n"
if(advanced)
msg += "\tBrain Activity Level: [(200 - M.getBrainLoss())/2]%.\n"
- if (M.radiation)
+ if(M.radiation)
msg += "\tSubject is irradiated.\n"
if(advanced)
msg += "\tRadiation Level: [M.radiation]%.\n"
@@ -191,6 +221,17 @@ SLIME SCANNER
if(advanced && M.hallucinating())
msg += "\tSubject is hallucinating.\n"
+ //MKUltra
+ if(advanced && M.has_status_effect(/datum/status_effect/chem/enthrall))
+ msg += "\tSubject has abnormal brain fuctions.\n"
+
+ //Astrogen shenanigans
+ if(advanced && M.reagents.has_reagent("astral"))
+ if(M.mind)
+ msg += "\tWarning: subject may be possesed.\n"
+ else
+ msg += "\tSubject appears to be astrally projecting.\n"
+
//Eyes and ears
if(advanced)
if(iscarbon(M))
@@ -256,6 +297,7 @@ SLIME SCANNER
for(var/obj/item/bodypart/org in damaged)
msg += "\t\t[capitalize(org.name)]: [(org.brute_dam > 0) ? "[org.brute_dam]" : "0"]-[(org.burn_dam > 0) ? "[org.burn_dam]" : "0"]\n"
+
// Species and body temperature
if(ishuman(M))
var/mob/living/carbon/human/H = M
@@ -310,7 +352,7 @@ SLIME SCANNER
var/mob/living/carbon/human/H = C
if(H.bleed_rate)
msg += "Subject is bleeding!\n"
- var/blood_percent = round((C.blood_volume / BLOOD_VOLUME_NORMAL)*100)
+ var/blood_percent = round((C.blood_volume / (BLOOD_VOLUME_NORMAL * C.blood_ratio))*100)
var/blood_type = C.dna.blood_type
if(blood_id != "blood")//special blood substance
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
@@ -318,9 +360,9 @@ SLIME SCANNER
blood_type = R.name
else
blood_type = blood_id
- if(C.blood_volume <= BLOOD_VOLUME_SAFE && C.blood_volume > BLOOD_VOLUME_OKAY)
+ if(C.blood_volume <= (BLOOD_VOLUME_SAFE*C.blood_ratio) && C.blood_volume > (BLOOD_VOLUME_OKAY*C.blood_ratio))
msg += "LOW blood level [blood_percent] %, [C.blood_volume] cl, type: [blood_type]\n"
- else if(C.blood_volume <= BLOOD_VOLUME_OKAY)
+ else if(C.blood_volume <= (BLOOD_VOLUME_OKAY*C.blood_ratio))
msg += "CRITICAL blood level [blood_percent] %, [C.blood_volume] cl, type: [blood_type]\n"
else
msg += "Blood level [blood_percent] %, [C.blood_volume] cl, type: [blood_type]\n"
diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm
index 36a92b3db9..a306b48385 100644
--- a/code/game/objects/items/handcuffs.dm
+++ b/code/game/objects/items/handcuffs.dm
@@ -164,21 +164,6 @@
/obj/item/restraints/handcuffs/cable/white
item_color = "white"
-/obj/item/restraints/handcuffs/alien
- icon_state = "handcuffAlien"
-
-/obj/item/restraints/handcuffs/fake
- name = "fake handcuffs"
- desc = "Fake handcuffs meant for gag purposes."
- breakouttime = 10 //Deciseconds = 1s
-
-/obj/item/restraints/handcuffs/fake/kinky
- name = "kinky handcuffs"
- desc = "Fake handcuffs meant for erotic roleplay."
- icon = 'modular_citadel/icons/obj/items_and_weapons.dmi'
- icon_state = "handcuffgag"
- item_state = "kinkycuff"
-
/obj/item/restraints/handcuffs/cable/attackby(obj/item/I, mob/user, params)
..()
if(istype(I, /obj/item/stack/rods))
@@ -213,7 +198,6 @@
/obj/item/restraints/handcuffs/cable/zipties
name = "zipties"
desc = "Plastic, disposable zipties that can be used to restrain temporarily but are destroyed after use."
- icon_state = "zipties"
item_state = "zipties"
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
@@ -229,6 +213,21 @@
/obj/item/restraints/handcuffs/cable/zipties/used/attack()
return
+/obj/item/restraints/handcuffs/alien
+ icon_state = "handcuffAlien"
+
+/obj/item/restraints/handcuffs/fake
+ name = "fake handcuffs"
+ desc = "Fake handcuffs meant for gag purposes."
+ breakouttime = 10 //Deciseconds = 1s
+
+/obj/item/restraints/handcuffs/fake/kinky
+ name = "kinky handcuffs"
+ desc = "Fake handcuffs meant for erotic roleplay."
+ icon = 'modular_citadel/icons/obj/items_and_weapons.dmi'
+ icon_state = "handcuffgag"
+ item_state = "kinkycuff"
+
//Legcuffs
/obj/item/restraints/legcuffs
diff --git a/code/game/objects/items/his_grace.dm b/code/game/objects/items/his_grace.dm
index 65a4bd542b..3be57d23f1 100644
--- a/code/game/objects/items/his_grace.dm
+++ b/code/game/objects/items/his_grace.dm
@@ -12,8 +12,9 @@
lefthand_file = 'icons/mob/inhands/equipment/toolbox_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/toolbox_righthand.dmi'
icon = 'icons/obj/items_and_weapons.dmi'
- w_class = WEIGHT_CLASS_GIGANTIC
+ w_class = WEIGHT_CLASS_BULKY
force = 12
+ total_mass = TOTAL_MASS_NORMAL_ITEM // average toolbox
attack_verb = list("robusted")
hitsound = 'sound/weapons/smash.ogg'
var/awakened = FALSE
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index 0e8a9fef9e..5e8250ea00 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -34,6 +34,7 @@
desc = "God wills it!"
icon_state = "knight_templar"
item_state = "knight_templar"
+ allowed = list(/obj/item/storage/book/bible, HOLY_WEAPONS, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
// CITADEL CHANGES: More variants
/obj/item/clothing/suit/armor/riot/chaplain/teutonic
@@ -122,7 +123,6 @@
icon_state = "studentuni"
item_state = "studentuni"
body_parts_covered = ARMS|CHEST
- allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
/obj/item/clothing/head/helmet/chaplain/cage
name = "cage"
@@ -166,7 +166,6 @@
icon_state = "witchhunter"
item_state = "witchhunter"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
- allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
/obj/item/clothing/head/helmet/chaplain/witchunter_hat
name = "witchunter hat"
@@ -191,7 +190,7 @@
icon_state = "chaplain_hoodie"
item_state = "chaplain_hoodie"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
- allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
+ allowed = list(/obj/item/storage/book/bible, HOLY_WEAPONS, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
hoodtype = /obj/item/clothing/head/hooded/chaplain_hood
/obj/item/clothing/head/hooded/chaplain_hood
@@ -229,8 +228,8 @@
throwforce = 10
w_class = WEIGHT_CLASS_TINY
obj_flags = UNIQUE_RENAME
- var/reskinned = FALSE
var/chaplain_spawnable = TRUE
+ total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
/obj/item/nullrod/Initialize()
. = ..()
@@ -247,10 +246,8 @@
/obj/item/nullrod/proc/reskin_holy_weapon(mob/M)
if(GLOB.holy_weapon_type)
return
- var/obj/item/nullrod/holy_weapon
- var/list/holy_weapons_list = typesof(/obj/item/nullrod) + list(
- /obj/item/melee/transforming/energy/sword/cx/chaplain
- )
+ var/obj/item/holy_weapon
+ var/list/holy_weapons_list = subtypesof(/obj/item/nullrod) + list(HOLY_WEAPONS)
var/list/display_names = list()
for(var/V in holy_weapons_list)
var/obj/item/nullrod/rodtype = V
@@ -273,6 +270,13 @@
qdel(src)
M.put_in_active_hand(holy_weapon)
+/obj/item/nullrod/proc/jedi_spin(mob/living/user)
+ for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH))
+ user.setDir(i)
+ if(i == WEST)
+ user.emote("flip")
+ sleep(1)
+
/obj/item/nullrod/godhand
icon_state = "disintegrate"
item_state = "disintegrate"
@@ -285,14 +289,12 @@
hitsound = 'sound/weapons/sear.ogg'
damtype = BURN
attack_verb = list("punched", "cross countered", "pummeled")
-
+ total_mass = TOTAL_MASS_HAND_REPLACEMENT
/obj/item/nullrod/godhand/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, HAND_REPLACEMENT_TRAIT)
-
-
/obj/item/nullrod/staff
icon_state = "godstaff-red"
item_state = "godstaff-red"
@@ -536,6 +538,7 @@
sharpness = IS_SHARP
attack_verb = list("sawed", "torn", "cut", "chopped", "diced")
hitsound = 'sound/weapons/chainsawhit.ogg'
+ total_mass = TOTAL_MASS_HAND_REPLACEMENT
/obj/item/nullrod/chainsaw/Initialize()
. = ..()
@@ -584,6 +587,7 @@
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
slot_flags = ITEM_SLOT_BELT
+ force = 12
reach = 2
attack_verb = list("whipped", "lashed")
hitsound = 'sound/weapons/chainhit.ogg'
@@ -612,6 +616,7 @@
item_flags = ABSTRACT
w_class = WEIGHT_CLASS_HUGE
sharpness = IS_SHARP
+ total_mass = TOTAL_MASS_HAND_REPLACEMENT
/obj/item/nullrod/armblade/Initialize()
. = ..()
@@ -659,6 +664,44 @@
lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
+/obj/item/nullrod/claymore/bostaff/attack(mob/target, mob/living/user)
+ add_fingerprint(user)
+ if((HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50))
+ to_chat(user, "You club yourself over the head with [src].")
+ user.Knockdown(60)
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ H.apply_damage(2*force, BRUTE, BODY_ZONE_HEAD)
+ else
+ user.take_bodypart_damage(2*force)
+ return
+ if(iscyborg(target))
+ return ..()
+ if(!isliving(target))
+ return ..()
+ var/mob/living/carbon/C = target
+ if(C.stat || C.health < 0 || C.staminaloss > 130 )
+ to_chat(user, "It would be dishonorable to attack a foe while they cannot retaliate.")
+ return
+ if(user.a_intent == INTENT_DISARM)
+ if(!ishuman(target))
+ return ..()
+ var/mob/living/carbon/human/H = target
+ var/list/fluffmessages = list("[user] clubs [H] with [src]!", \
+ "[user] smacks [H] with the butt of [src]!", \
+ "[user] broadsides [H] with [src]!", \
+ "[user] smashes [H]'s head with [src]!", \
+ "[user] beats [H] with front of [src]!", \
+ "[user] twirls and slams [H] with [src]!")
+ H.visible_message("[pick(fluffmessages)]", \
+ "[pick(fluffmessages)]")
+ playsound(get_turf(user), 'sound/effects/woodhit.ogg', 75, 1, -1)
+ H.adjustStaminaLoss(rand(12,18))
+ if(prob(25))
+ (INVOKE_ASYNC(src, .proc/jedi_spin, user))
+ else
+ return ..()
+
/obj/item/nullrod/tribal_knife
icon_state = "crysknife"
item_state = "crysknife"
@@ -701,8 +744,8 @@
name = "egyptian staff"
desc = "A tutorial in mummification is carved into the staff. You could probably craft the wraps if you had some cloth."
icon = 'icons/obj/guns/magic.dmi'
- icon_state = "pharoah_sceptre"
- item_state = "pharoah_sceptre"
+ icon_state = "pharaoh_sceptre"
+ item_state = "pharaoh_sceptre"
lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
w_class = WEIGHT_CLASS_NORMAL
diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm
index 935d2a007e..d854ab9f5a 100644
--- a/code/game/objects/items/melee/energy.dm
+++ b/code/game/objects/items/melee/energy.dm
@@ -5,9 +5,12 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30)
resistance_flags = FIRE_PROOF
var/brightness_on = 3
+ total_mass = 0.4 //Survival flashlights typically weigh around 5 ounces.
+
/obj/item/melee/transforming/energy/Initialize()
. = ..()
+ total_mass_on = (total_mass_on ? total_mass_on : (w_class_on * 0.75))
if(active)
set_light(brightness_on)
START_PROCESSING(SSobj, src)
@@ -79,6 +82,7 @@
attack_verb_off = list("attacked", "chopped", "cleaved", "torn", "cut")
attack_verb_on = list()
light_color = "#40ceff"
+ total_mass = null
/obj/item/melee/transforming/energy/axe/suicide_act(mob/user)
user.visible_message("[user] swings [src] towards [user.p_their()] head! It looks like [user.p_theyre()] trying to commit suicide!")
diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm
index daeceb7f87..f9affc230d 100644
--- a/code/game/objects/items/melee/misc.dm
+++ b/code/game/objects/items/melee/misc.dm
@@ -44,6 +44,7 @@
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "impaled", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
sharpness = IS_SHARP
+ total_mass = TOTAL_MASS_HAND_REPLACEMENT
/obj/item/melee/synthetic_arm_blade/Initialize()
. = ..()
@@ -67,6 +68,7 @@
attack_verb = list("slashed", "cut")
hitsound = 'sound/weapons/rapierhit.ogg'
materials = list(MAT_METAL = 1000)
+ total_mass = 3.4
/obj/item/melee/sabre/Initialize()
. = ..()
@@ -155,6 +157,7 @@
w_class = WEIGHT_CLASS_BULKY
sharpness = IS_SHARP_ACCURATE //It cant be sharpend cook -_-
attack_verb = list("slashed", "cut", "pierces", "pokes")
+ total_mass = 3.4
/obj/item/melee/rapier/Initialize()
. = ..()
@@ -226,7 +229,7 @@
target.LAssailant = null
else
target.LAssailant = user
- cooldown = world.time + 40
+ cooldown = world.time
user.adjustStaminaLossBuffered(getweight())//CIT CHANGE - makes swinging batons cost stamina
/obj/item/melee/classic_baton/telescopic
@@ -242,6 +245,7 @@
item_flags = NONE
force = 0
on = FALSE
+ total_mass = TOTAL_MASS_SMALL_ITEM
/obj/item/melee/classic_baton/telescopic/suicide_act(mob/user)
var/mob/living/carbon/human/H = user
@@ -402,6 +406,7 @@
var/static/list/ovens
var/on = FALSE
var/datum/beam/beam
+ total_mass = 2.5
/obj/item/melee/roastingstick/Initialize()
. = ..()
diff --git a/code/game/objects/items/melee/transforming.dm b/code/game/objects/items/melee/transforming.dm
index 0d39e6c847..aabb930bb2 100644
--- a/code/game/objects/items/melee/transforming.dm
+++ b/code/game/objects/items/melee/transforming.dm
@@ -13,6 +13,7 @@
var/list/nemesis_factions //Any mob with a faction that exists in this list will take bonus damage/effects
var/w_class_on = WEIGHT_CLASS_BULKY
var/clumsy_check = TRUE
+ var/total_mass_on //Total mass in ounces when transformed. Primarily for balance purposes. Don't think about it too hard.
/obj/item/melee/transforming/Initialize()
. = ..()
@@ -46,6 +47,7 @@
active = !active
if(active)
force = force_on
+ total_mass = total_mass_on
throwforce = throwforce_on
hitsound = hitsound_on
throw_speed = 4
@@ -62,6 +64,7 @@
attack_verb = attack_verb_off
icon_state = initial(icon_state)
w_class = initial(w_class)
+ total_mass = initial(total_mass)
if(is_sharp())
var/datum/component/butchering/BT = LoadComponent(/datum/component/butchering)
BT.butchering_enabled = TRUE
@@ -84,4 +87,4 @@
/obj/item/melee/transforming/proc/clumsy_transform_effect(mob/living/user)
if(clumsy_check && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
to_chat(user, "You accidentally cut yourself with [src], like a doofus!")
- user.take_bodypart_damage(5,5)
+ user.take_bodypart_damage(5,5)
\ No newline at end of file
diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm
index 40380dfe80..48588cf9f3 100644
--- a/code/game/objects/items/plushes.dm
+++ b/code/game/objects/items/plushes.dm
@@ -629,7 +629,7 @@
/obj/item/toy/plush/mothplushie
name = "insect plushie"
- desc = "An adorable stuffed toy that resembles some kind of insect"
+ desc = "An adorable stuffed toy that resembles some kind of insect."
icon_state = "bumble"
item_state = "bumble"
squeak_override = list('modular_citadel/sound/voice/mothsqueak.ogg' = 1)
@@ -773,8 +773,10 @@
item_state = "blep"
/obj/item/toy/plush/mammal/circe
+ desc = "A luxuriously soft toy that resembles a nine-tailed kitsune."
icon_state = "circe"
item_state = "circe"
+ attack_verb = list("medicated", "tailhugged", "kissed")
/obj/item/toy/plush/mammal/robin
icon_state = "robin"
@@ -839,8 +841,10 @@
item_state = "rae"
/obj/item/toy/plush/mammal/zed
+ desc = "A masked stuffed toy that resembles a fierce miner. He even comes with his own little crusher!"
icon_state = "zed"
item_state = "zed"
+ attack_verb = list("ENDED", "CRUSHED", "GNOMED")
/obj/item/toy/plush/mammal/justin
icon_state = "justin"
@@ -852,6 +856,12 @@
item_state = "reece"
attack_verb = list("healed", "cured", "demoted")
+/obj/item/toy/plush/mammal/redwood
+ desc = "An adorable stuffed toy resembling a Nanotrasen Captain. That just happens to be a bunny."
+ icon_state = "redwood"
+ item_state = "redwood"
+ attack_verb = list("ordered", "bapped", "reprimanded")
+
/obj/item/toy/plush/mammal/dog
desc = "An adorable stuffed toy that resembles a canine."
icon_state = "katlin"
@@ -898,6 +908,12 @@
obj_flags = UNIQUE_RENAME
unique_reskin = list("Goodboye" = "fritz", "Badboye" = "fritz_bad")
+/obj/item/toy/plush/mammal/dog/jesse
+ desc = "An adorable wolf toy that resembles a cream-colored wolf. He has a little pride flag!"
+ icon_state = "jesse"
+ item_state = "jesse"
+ attack_verb = list("greeted", "merc'd", "howdy'd")
+
/obj/item/toy/plush/catgirl
name = "feline plushie"
desc = "An adorable stuffed toy that resembles a feline."
@@ -935,3 +951,15 @@
item_state = "fermis"
attack_verb = list("cuddled", "petpatted", "wigglepurred")
squeak_override = list('modular_citadel/sound/voice/merowr.ogg' = 1)
+
+/obj/item/toy/plush/catgirl/mariaf
+ desc = "An adorable stuffed toy that resembles a very tall cat girl."
+ icon_state = "mariaf"
+ item_state = "mariaf"
+ attack_verb = list("hugged", "stabbed", "licked")
+
+/obj/item/toy/plush/catgirl/maya
+ desc = "An adorable stuffed toy that resembles an angry cat girl. She has her own tiny nuke disk!"
+ icon_state = "maya"
+ item_state = "maya"
+ attack_verb = list("nuked", "arrested", "harmbatonned")
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index 6d7c3036f9..5454b0fdb8 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -282,11 +282,13 @@
var/cooldown = 0
/obj/item/harmalarm/emag_act(mob/user)
+ . = ..()
obj_flags ^= EMAGGED
if(obj_flags & EMAGGED)
to_chat(user, "You short out the safeties on [src]!")
else
to_chat(user, "You reset the safeties on [src]!")
+ return TRUE
/obj/item/harmalarm/attack_self(mob/user)
var/safety = !(obj_flags & EMAGGED)
diff --git a/code/game/objects/items/singularityhammer.dm b/code/game/objects/items/singularityhammer.dm
index 1fe57d151f..b6559c9091 100644
--- a/code/game/objects/items/singularityhammer.dm
+++ b/code/game/objects/items/singularityhammer.dm
@@ -16,6 +16,7 @@
armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
resistance_flags = FIRE_PROOF | ACID_PROOF
force_string = "LORD SINGULOTH HIMSELF"
+ total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
/obj/item/twohanded/singularityhammer/New()
..()
@@ -84,6 +85,7 @@
throwforce = 30
throw_range = 7
w_class = WEIGHT_CLASS_HUGE
+ total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
/obj/item/twohanded/mjollnir/proc/shock(mob/living/target)
target.Stun(60)
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index cf967e25ba..47c881bbdf 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -23,7 +23,7 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 100)
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/glass
- grind_results = list("silicon" = 20)
+ grind_results = list(/datum/reagent/silicon = 20)
point_value = 1
/obj/item/stack/sheet/glass/suicide_act(mob/living/carbon/user)
@@ -87,7 +87,7 @@ GLOBAL_LIST_INIT(pglass_recipes, list ( \
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 75, "acid" = 100)
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/plasmaglass
- grind_results = list("silicon" = 20, "plasma" = 10)
+ grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/toxin/plasma = 10)
/obj/item/stack/sheet/plasmaglass/fifty
amount = 50
@@ -138,7 +138,7 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 100)
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/rglass
- grind_results = list("silicon" = 20, "iron" = 10)
+ grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/iron = 10)
point_value = 4
/obj/item/stack/sheet/rglass/attackby(obj/item/W, mob/user, params)
@@ -177,11 +177,11 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \
singular_name = "reinforced plasma glass sheet"
icon_state = "sheet-prglass"
item_state = "sheet-prglass"
- materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS=MINERAL_MATERIAL_AMOUNT, MAT_METAL = MINERAL_MATERIAL_AMOUNT * 0.5,)
+ materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS=MINERAL_MATERIAL_AMOUNT, MAT_METAL=MINERAL_MATERIAL_AMOUNT * 0.5,)
armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/plasmarglass
- grind_results = list("silicon" = 20, "plasma" = 10, "iron" = 10)
+ grind_results = list(/datum/reagent/silicon = 20, /datum/reagent/toxin/plasma = 10, /datum/reagent/iron = 10)
point_value = 23
/obj/item/stack/sheet/plasmarglass/Initialize(mapload, new_amount, merge = TRUE)
@@ -243,8 +243,9 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
resistance_flags = ACID_PROOF
armor = list("melee" = 100, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 100)
max_integrity = 40
- var/cooldown = 0
sharpness = IS_SHARP
+ var/icon_prefix
+
/obj/item/shard/suicide_act(mob/user)
user.visible_message("[user] is slitting [user.p_their()] [pick("wrists", "throat")] with the shard of glass! It looks like [user.p_theyre()] trying to commit suicide.")
@@ -266,9 +267,19 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
if("large")
pixel_x = rand(-5, 5)
pixel_y = rand(-5, 5)
- var/matrix/M = matrix(transform)
- M.Turn(rand(-170, 170))
- transform = M
+ if (icon_prefix)
+ icon_state = "[icon_prefix][icon_state]"
+
+ var/turf/T = get_turf(src)
+ if(T && is_station_level(T.z))
+ SSblackbox.record_feedback("tally", "station_mess_created", 1, name)
+
+/obj/item/shard/Destroy()
+ . = ..()
+
+ var/turf/T = get_turf(src)
+ if(T && is_station_level(T.z))
+ SSblackbox.record_feedback("tally", "station_mess_destroyed", 1, name)
/obj/item/shard/afterattack(atom/A as mob|obj, mob/user, proximity)
. = ..()
@@ -298,6 +309,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
return ..()
/obj/item/shard/welder_act(mob/living/user, obj/item/I)
+ ..()
if(I.use_tool(src, user, 0, volume=50))
var/obj/item/stack/sheet/glass/NG = new (user.loc)
for(var/obj/item/stack/sheet/glass/G in user.loc)
@@ -316,4 +328,13 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
playsound(loc, 'sound/effects/glass_step.ogg', 30, 1)
else
playsound(loc, 'sound/effects/glass_step.ogg', 50, 1)
- . = ..()
+ return ..()
+
+/obj/item/shard/plasma
+ name = "purple shard"
+ desc = "A nasty looking shard of plasma glass."
+ force = 6
+ throwforce = 11
+ icon_state = "plasmalarge"
+ materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT * 0.5, MAT_GLASS=MINERAL_MATERIAL_AMOUNT)
+ icon_prefix = "plasma"
\ No newline at end of file
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index c65129ec85..8c808d0e5f 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -201,6 +201,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
new/datum/stack_recipe("dresser", /obj/structure/dresser, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("picture frame", /obj/item/wallframe/picture, 1, time = 10),\
new/datum/stack_recipe("display case chassis", /obj/structure/displaycase_chassis, 5, one_per_turf = TRUE, on_floor = TRUE), \
+ new/datum/stack_recipe("loom", /obj/structure/loom, 10, time = 15, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), \
new/datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50),\
new/datum/stack_recipe("tiki mask", /obj/item/clothing/mask/gas/tiki_mask, 2), \
@@ -278,6 +279,31 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
/obj/item/stack/sheet/cloth/ten
amount = 10
+//Durathread fuck slash-asterisk comments
+ GLOBAL_LIST_INIT(durathread_recipes, list ( \
+ new/datum/stack_recipe("durathread jumpsuit", /obj/item/clothing/under/durathread, 4, time = 40),
+ new/datum/stack_recipe("durathread beret", /obj/item/clothing/head/beret/durathread, 2, time = 40), \
+ new/datum/stack_recipe("durathread beanie", /obj/item/clothing/head/beanie/durathread, 2, time = 40), \
+ new/datum/stack_recipe("durathread bandana", /obj/item/clothing/mask/bandana/durathread, 1, time = 25), \
+ ))
+
+/obj/item/stack/sheet/durathread
+ name = "durathread"
+ desc = "A fabric sown from incredibly durable threads, known for its usefulness in armor production."
+ singular_name = "durathread roll"
+ icon_state = "sheet-durathread"
+ item_state = "sheet-cloth"
+ resistance_flags = FLAMMABLE
+ force = 0
+ throwforce = 0
+ merge_type = /obj/item/stack/sheet/durathread
+
+/obj/item/stack/sheet/durathread/Initialize(mapload, new_amount, merge = TRUE)
+ recipes = GLOB.durathread_recipes
+ return ..()
+
+
+
/*
* Cardboard
*/
@@ -603,3 +629,29 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
amount = 20
/obj/item/stack/sheet/paperframes/fifty
amount = 50
+
+
+//durathread and cotton raw
+/obj/item/stack/sheet/cotton
+ name = "raw cotton bundle"
+ desc = "A bundle of raw cotton ready to be spun on the loom."
+ singular_name = "raw cotton ball"
+ icon_state = "sheet-cotton"
+ is_fabric = TRUE
+ resistance_flags = FLAMMABLE
+ force = 0
+ throwforce = 0
+ merge_type = /obj/item/stack/sheet/cotton
+ pull_effort = 30
+ loom_result = /obj/item/stack/sheet/cloth
+
+/obj/item/stack/sheet/cotton/durathread
+ name = "raw durathread bundle"
+ desc = "A bundle of raw durathread ready to be spun on the loom."
+ singular_name = "raw durathread ball"
+ icon_state = "sheet-durathreadraw"
+ merge_type = /obj/item/stack/sheet/cotton/durathread
+ pull_effort = 70
+ loom_result = /obj/item/stack/sheet/durathread
+
+
diff --git a/code/game/objects/items/stacks/sheets/sheets.dm b/code/game/objects/items/stacks/sheets/sheets.dm
index 21b43eba20..908fc88383 100644
--- a/code/game/objects/items/stacks/sheets/sheets.dm
+++ b/code/game/objects/items/stacks/sheets/sheets.dm
@@ -12,4 +12,7 @@
novariants = FALSE
var/perunit = MINERAL_MATERIAL_AMOUNT
var/sheettype = null //this is used for girders in the creation of walls/false walls
- var/point_value = 0 //turn-in value for the gulag stacker - loosely relative to its rarity.
\ No newline at end of file
+ var/point_value = 0 //turn-in value for the gulag stacker - loosely relative to its rarity
+ var/is_fabric = FALSE //is this a valid material for the loom?
+ var/loom_result //result from pulling on the loom
+ var/pull_effort = 0 //amount of delay when pulling on the loom
\ No newline at end of file
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index eb71311c96..b5d7282b07 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -248,12 +248,13 @@
desc = "A bone satchel fashend with watcher wings and large bones from goliath. Can be worn on the belt."
icon = 'icons/obj/mining.dmi'
icon_state = "goliath_saddle"
- slot_flags = ITEM_SLOT_BACK | ITEM_SLOT_BELT
+ slot_flags = ITEM_SLOT_BACK
/obj/item/storage/backpack/satchel/bone/ComponentInitialize()
. = ..()
GET_COMPONENT(STR, /datum/component/storage)
- STR.max_combined_w_class = 10
+ STR.max_combined_w_class = 20
+ STR.max_items = 15
/obj/item/storage/backpack/satchel/cap
name = "captain's satchel"
@@ -355,6 +356,7 @@
new /obj/item/cautery(src)
new /obj/item/surgical_drapes(src)
new /obj/item/clothing/mask/surgical(src)
+ new /obj/item/reagent_containers/medspray/sterilizine(src)
new /obj/item/razor(src)
/obj/item/storage/backpack/duffelbag/sec
@@ -376,6 +378,7 @@
new /obj/item/cautery(src)
new /obj/item/surgical_drapes(src)
new /obj/item/clothing/mask/surgical(src)
+ new /obj/item/reagent_containers/medspray/sterilizine(src)
/obj/item/storage/backpack/duffelbag/engineering
name = "industrial duffel bag"
@@ -383,6 +386,14 @@
icon_state = "duffel-eng"
item_state = "duffel-eng"
+/obj/item/storage/backpack/duffelbag/durathread
+ name = "durathread duffel bag"
+ desc = "A lightweight duffel bag made out of durathread."
+ icon_state = "duffel-durathread"
+ item_state = "duffel-durathread"
+ resistance_flags = FIRE_PROOF
+ slowdown = 0
+
/obj/item/storage/backpack/duffelbag/drone
name = "drone duffel bag"
desc = "A large duffel bag for holding tools and hats."
@@ -398,6 +409,7 @@
new /obj/item/stack/cable_coil/random(src)
new /obj/item/wirecutters(src)
new /obj/item/multitool(src)
+ new /obj/item/pipe_dispenser(src)
/obj/item/storage/backpack/duffelbag/clown
name = "clown's duffel bag"
@@ -460,6 +472,7 @@
new /obj/item/mmi/syndie(src)
new /obj/item/implantcase(src)
new /obj/item/implanter(src)
+ new /obj/item/reagent_containers/medspray/sterilizine(src)
/obj/item/storage/backpack/duffelbag/syndie/surgery_adv
name = "advanced surgery duffel bag"
@@ -479,6 +492,7 @@
new /obj/item/mmi/syndie(src)
new /obj/item/implantcase(src)
new /obj/item/implanter(src)
+ new /obj/item/reagent_containers/medspray/sterilizine(src)
/obj/item/storage/backpack/duffelbag/syndie/ammo
name = "ammunition duffel bag"
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index d71b91c8dc..4495e9da14 100755
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -431,6 +431,48 @@
GET_COMPONENT(STR, /datum/component/storage)
STR.max_items = 6
+/obj/item/storage/belt/durathread
+ name = "durathread toolbelt"
+ desc = "A toolbelt made out of durathread, it seems resistant enough to hold even big tools like an RCD, it also has higher capacity."
+ icon_state = "webbing-durathread"
+ item_state = "webbing-durathread"
+ resistance_flags = FIRE_PROOF
+
+/obj/item/storage/belt/durathread/ComponentInitialize()
+ . = ..()
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
+ STR.max_items = 14
+ STR.max_combined_w_class = 32
+ STR.max_w_class = WEIGHT_CLASS_NORMAL
+ STR.can_hold = typecacheof(list(
+ /obj/item/crowbar,
+ /obj/item/screwdriver,
+ /obj/item/weldingtool,
+ /obj/item/wirecutters,
+ /obj/item/wrench,
+ /obj/item/multitool,
+ /obj/item/flashlight,
+ /obj/item/stack/cable_coil,
+ /obj/item/t_scanner,
+ /obj/item/analyzer,
+ /obj/item/geiger_counter,
+ /obj/item/extinguisher/mini,
+ /obj/item/radio,
+ /obj/item/clothing/gloves,
+ /obj/item/holosign_creator/atmos,
+ /obj/item/holosign_creator/engineering,
+ /obj/item/forcefield_projector,
+ /obj/item/assembly/signaler,
+ /obj/item/lightreplacer,
+ /obj/item/rcd_ammo,
+ /obj/item/construction/rcd,
+ /obj/item/pipe_dispenser,
+ /obj/item/stack/rods,
+ /obj/item/stack/tile/plasteel,
+ /obj/item/grenade/chem_grenade/metalfoam,
+ /obj/item/grenade/chem_grenade/smart_metal_foam
+ ))
+
/obj/item/storage/belt/grenade
name = "grenadier belt"
desc = "A belt for holding grenades."
@@ -524,12 +566,15 @@
/obj/item/grenade/chem_grenade,
/obj/item/lightreplacer,
/obj/item/flashlight,
+ /obj/item/reagent_containers/glass/beaker,
+ /obj/item/reagent_containers/glass/bottle,
/obj/item/reagent_containers/spray,
/obj/item/soap,
/obj/item/holosign_creator,
/obj/item/key/janitor,
/obj/item/clothing/gloves,
/obj/item/melee/flyswatter,
+ /obj/item/paint/paint_remover,
/obj/item/assembly/mousetrap
))
@@ -548,6 +593,22 @@
/obj/item/ammo_casing/shotgun
))
+/obj/item/storage/belt/bandolier/durathread
+ name = "durathread bandolier"
+ desc = "An double stacked bandolier made out of durathread."
+ icon_state = "bandolier-durathread"
+ item_state = "bandolier-durathread"
+ resistance_flags = FIRE_PROOF
+
+/obj/item/storage/belt/bandolier/durathread/ComponentInitialize()
+ . = ..()
+ GET_COMPONENT(STR, /datum/component/storage)
+ STR.max_items = 32
+ STR.display_numerical_stacking = TRUE
+ STR.can_hold = typecacheof(list(
+ /obj/item/ammo_casing
+ ))
+
/obj/item/storage/belt/medolier
name = "medolier"
desc = "A medical bandolier for holding smartdarts."
diff --git a/code/game/objects/items/storage/briefcase.dm b/code/game/objects/items/storage/briefcase.dm
index bca13f2a45..ed547bc17d 100644
--- a/code/game/objects/items/storage/briefcase.dm
+++ b/code/game/objects/items/storage/briefcase.dm
@@ -40,9 +40,18 @@
/obj/item/storage/briefcase/lawyer/family
name = "battered briefcase"
- desc = "An old briefcase, this one has seen better days in its time. It's clear they don't make them nowadays as good as they used to. Comes with an added belt clip!"
+ icon_state = "gbriefcase"
+ lefthand_file = 'icons/mob/inhands/equipment/briefcase_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/briefcase_righthand.dmi'
+ desc = "An old briefcase with a golden trim. It's clear they don't make them as good as they used to. Comes with an added belt clip!"
slot_flags = ITEM_SLOT_BELT
+/obj/item/storage/briefcase/lawyer/family/ComponentInitialize()
+ . = ..()
+ GET_COMPONENT(STR, /datum/component/storage)
+ STR.max_w_class = WEIGHT_CLASS_NORMAL
+ STR.max_combined_w_class = 14
+
/obj/item/storage/briefcase/lawyer/family/PopulateContents()
new /obj/item/stamp/law(src)
new /obj/item/pen/fountain(src)
diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm
index e9b074d40c..312ef35430 100644
--- a/code/game/objects/items/storage/firstaid.dm
+++ b/code/game/objects/items/storage/firstaid.dm
@@ -1,365 +1,391 @@
-/* First aid storage
- * Contains:
- * First Aid Kits
- * Pill Bottles
- * Dice Pack (in a pill bottle)
- */
-
-/*
- * First Aid Kits
- */
-/obj/item/storage/firstaid
- name = "first-aid kit"
- desc = "It's an emergency medical kit for those serious boo-boos."
- icon_state = "firstaid"
- lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
- throw_speed = 3
- throw_range = 7
- var/empty = FALSE
-
-/obj/item/storage/firstaid/regular
- icon_state = "firstaid"
- desc = "A first aid kit with the ability to heal common types of injuries."
-
-/obj/item/storage/firstaid/regular/suicide_act(mob/living/carbon/user)
- user.visible_message("[user] begins giving [user.p_them()]self aids with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return BRUTELOSS
-
-/obj/item/storage/firstaid/regular/PopulateContents()
- if(empty)
- return
- new /obj/item/stack/medical/gauze(src)
- new /obj/item/stack/medical/bruise_pack(src)
- new /obj/item/stack/medical/bruise_pack(src)
- new /obj/item/stack/medical/ointment(src)
- new /obj/item/stack/medical/ointment(src)
- new /obj/item/reagent_containers/hypospray/medipen(src)
- new /obj/item/healthanalyzer(src)
-
-/obj/item/storage/firstaid/ancient
- icon_state = "firstaid"
- desc = "A first aid kit with the ability to heal common types of injuries."
-
-/obj/item/storage/firstaid/ancient/PopulateContents()
- if(empty)
- return
- new /obj/item/stack/medical/gauze(src)
- new /obj/item/stack/medical/bruise_pack(src)
- new /obj/item/stack/medical/bruise_pack(src)
- new /obj/item/stack/medical/bruise_pack(src)
- new /obj/item/stack/medical/ointment(src)
- new /obj/item/stack/medical/ointment(src)
- new /obj/item/stack/medical/ointment(src)
-
-/obj/item/storage/firstaid/fire
- name = "burn treatment kit"
- desc = "A specialized medical kit for when the toxins lab -spontaneously- burns down."
- icon_state = "ointment"
- item_state = "firstaid-ointment"
-
-/obj/item/storage/firstaid/fire/suicide_act(mob/living/carbon/user)
- user.visible_message("[user] begins rubbing \the [src] against [user.p_them()]self! It looks like [user.p_theyre()] trying to start a fire!")
- return FIRELOSS
-
-/obj/item/storage/firstaid/fire/Initialize(mapload)
- . = ..()
- icon_state = pick("ointment","firefirstaid")
-
-/obj/item/storage/firstaid/fire/PopulateContents()
- if(empty)
- return
- for(var/i in 1 to 3)
- new /obj/item/reagent_containers/pill/patch/silver_sulf(src)
- new /obj/item/reagent_containers/pill/oxandrolone(src)
- new /obj/item/reagent_containers/pill/oxandrolone(src)
- new /obj/item/reagent_containers/hypospray/medipen(src)
- new /obj/item/healthanalyzer(src)
-
-/obj/item/storage/firstaid/toxin
- name = "toxin treatment kit"
- desc = "Used to treat toxic blood content and radiation poisoning."
- icon_state = "antitoxin"
- item_state = "firstaid-toxin"
-
-/obj/item/storage/firstaid/toxin/suicide_act(mob/living/carbon/user)
- user.visible_message("[user] begins licking the lead paint off \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return TOXLOSS
-
-/obj/item/storage/firstaid/toxin/Initialize(mapload)
- . = ..()
- icon_state = pick("antitoxin","antitoxfirstaid","antitoxfirstaid2","antitoxfirstaid3")
-
-/obj/item/storage/firstaid/toxin/PopulateContents()
- if(empty)
- return
- for(var/i in 1 to 4)
- new /obj/item/reagent_containers/syringe/charcoal(src)
- for(var/i in 1 to 2)
- new /obj/item/storage/pill_bottle/charcoal(src)
- new /obj/item/healthanalyzer(src)
-
-/obj/item/storage/firstaid/radbgone
- name = "radiation treatment kit"
- desc = "Used to treat minor toxic blood content and major radiation poisoning."
- icon_state = "antitoxin"
- item_state = "firstaid-toxin"
-
-/obj/item/storage/firstaid/radbgone/suicide_act(mob/living/carbon/user)
- user.visible_message("[user] begins licking the lead paint off \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return TOXLOSS
-
-/obj/item/storage/firstaid/radbgone/PopulateContents()
- if(empty)
- return
- if(prob(50))
- new /obj/item/reagent_containers/pill/mutarad(src)
- if(prob(80))
- new /obj/item/reagent_containers/pill/antirad_plus(src)
- new /obj/item/reagent_containers/syringe/charcoal(src)
- new /obj/item/storage/pill_bottle/charcoal(src)
- new /obj/item/reagent_containers/pill/mutadone(src)
- new /obj/item/reagent_containers/pill/antirad(src)
- new /obj/item/reagent_containers/food/drinks/bottle/vodka(src)
- new /obj/item/healthanalyzer(src)
-
-
-/obj/item/storage/firstaid/o2
- name = "oxygen deprivation treatment kit"
- desc = "A box full of oxygen goodies."
- icon_state = "o2"
- item_state = "firstaid-o2"
-
-/obj/item/storage/firstaid/o2/suicide_act(mob/living/carbon/user)
- user.visible_message("[user] begins hitting [user.p_their()] neck with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return OXYLOSS
-
-/obj/item/storage/firstaid/o2/PopulateContents()
- if(empty)
- return
- for(var/i in 1 to 4)
- new /obj/item/reagent_containers/pill/salbutamol(src)
- new /obj/item/reagent_containers/hypospray/medipen(src)
- new /obj/item/reagent_containers/hypospray/medipen(src)
- new /obj/item/healthanalyzer(src)
-
-/obj/item/storage/firstaid/brute
- name = "brute trauma treatment kit"
- desc = "A first aid kit for when you get toolboxed."
- icon_state = "brute"
- item_state = "firstaid-brute"
-
-/obj/item/storage/firstaid/brute/suicide_act(mob/living/carbon/user)
- user.visible_message("[user] begins beating [user.p_them()]self over the head with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return BRUTELOSS
-
-/obj/item/storage/firstaid/brute/PopulateContents()
- if(empty)
- return
- for(var/i in 1 to 4)
- new /obj/item/reagent_containers/pill/patch/styptic(src)
- new /obj/item/stack/medical/gauze(src)
- new /obj/item/stack/medical/gauze(src)
- new /obj/item/healthanalyzer(src)
-
-/obj/item/storage/firstaid/tactical
- name = "combat medical kit"
- desc = "I hope you've got insurance."
- icon_state = "bezerk"
-
-/obj/item/storage/firstaid/tactical/ComponentInitialize()
- . = ..()
- GET_COMPONENT(STR, /datum/component/storage)
- STR.max_w_class = WEIGHT_CLASS_NORMAL
-
-/obj/item/storage/firstaid/tactical/PopulateContents()
- if(empty)
- return
- new /obj/item/stack/medical/gauze(src)
- new /obj/item/defibrillator/compact/combat/loaded(src)
- new /obj/item/reagent_containers/hypospray/combat(src)
- new /obj/item/reagent_containers/pill/patch/styptic(src)
- new /obj/item/reagent_containers/pill/patch/silver_sulf(src)
- new /obj/item/reagent_containers/syringe/lethal/choral(src)
- new /obj/item/clothing/glasses/hud/health/night(src)
-
-/*
- * Pill Bottles
- */
-
-/obj/item/storage/pill_bottle
- name = "pill bottle"
- desc = "It's an airtight container for storing medication."
- icon_state = "pill_canister"
- icon = 'icons/obj/chemical.dmi'
- item_state = "contsolid"
- lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
- w_class = WEIGHT_CLASS_SMALL
-
-/obj/item/storage/pill_bottle/ComponentInitialize()
- . = ..()
- GET_COMPONENT(STR, /datum/component/storage)
- STR.allow_quick_gather = TRUE
- STR.click_gather = TRUE
- STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/dice))
-
-/obj/item/storage/pill_bottle/suicide_act(mob/user)
- user.visible_message("[user] is trying to get the cap off [src]! It looks like [user.p_theyre()] trying to commit suicide!")
- return (TOXLOSS)
-
-/obj/item/storage/pill_bottle/charcoal
- name = "bottle of charcoal pills"
- desc = "Contains pills used to counter toxins."
-
-/obj/item/storage/pill_bottle/charcoal/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/pill/charcoal(src)
-
-/obj/item/storage/pill_bottle/antirad
- name = "bottle of charcoal pills"
- desc = "Contains pills used to counter radiation poisoning."
-
-/obj/item/storage/pill_bottle/anitrad/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/pill/antirad(src)
-
-/obj/item/storage/pill_bottle/epinephrine
- name = "bottle of epinephrine pills"
- desc = "Contains pills used to stabilize patients."
-
-/obj/item/storage/pill_bottle/epinephrine/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/pill/epinephrine(src)
-
-/obj/item/storage/pill_bottle/mutadone
- name = "bottle of mutadone pills"
- desc = "Contains pills used to treat genetic abnormalities."
-
-/obj/item/storage/pill_bottle/mutadone/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/pill/mutadone(src)
-
-/obj/item/storage/pill_bottle/mannitol
- name = "bottle of mannitol pills"
- desc = "Contains pills used to treat brain damage."
-
-/obj/item/storage/pill_bottle/mannitol/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/pill/mannitol(src)
-
-/obj/item/storage/pill_bottle/stimulant
- name = "bottle of stimulant pills"
- desc = "Guaranteed to give you that extra burst of energy during a long shift!"
-
-/obj/item/storage/pill_bottle/stimulant/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/pill/stimulant(src)
-
-/obj/item/storage/pill_bottle/mining
- name = "bottle of patches"
- desc = "Contains patches used to treat brute and burn damage."
-
-/obj/item/storage/pill_bottle/mining/PopulateContents()
- new /obj/item/reagent_containers/pill/patch/silver_sulf(src)
- for(var/i in 1 to 3)
- new /obj/item/reagent_containers/pill/patch/styptic(src)
-
-/obj/item/storage/pill_bottle/zoom
- name = "suspicious pill bottle"
- desc = "The label is pretty old and almost unreadable, you recognize some chemical compounds."
-
-/obj/item/storage/pill_bottle/zoom/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/pill/zoom(src)
-
-/obj/item/storage/pill_bottle/happy
- name = "suspicious pill bottle"
- desc = "There is a smiley on the top."
-
-/obj/item/storage/pill_bottle/happy/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/pill/happy(src)
-
-/obj/item/storage/pill_bottle/lsd
- name = "suspicious pill bottle"
- desc = "There is a badly drawn thing with the shape of a mushroom."
-
-/obj/item/storage/pill_bottle/lsd/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/pill/lsd(src)
-
-/obj/item/storage/pill_bottle/aranesp
- name = "suspicious pill bottle"
- desc = "The label says 'gotta go fast'."
-
-/obj/item/storage/pill_bottle/aranesp/PopulateContents()
- for(var/i in 1 to 5)
- new /obj/item/reagent_containers/pill/aranesp(src)
-
-/obj/item/storage/pill_bottle/antirad_plus
- name = "anti radiation deluxe pill bottle"
- desc = "The label says 'Med-Co branded pills'."
-
-/obj/item/storage/pill_bottle/antirad_plus/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/pill/antirad_plus(src)
-
-/obj/item/storage/pill_bottle/mutarad
- name = "radiation treatment deluxe pill bottle"
- desc = "The label says 'Med-Co branded pills' and below that 'Contains Mutadone in each pill!`."
-
-/obj/item/storage/pill_bottle/mutarad/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/pill/mutarad(src)
-
-/obj/item/storage/pill_bottle/penis_enlargement
- name = "penis enlargement pills"
- desc = "You want penis enlargement pills?"
-
-/obj/item/storage/pill_bottle/penis_enlargement/PopulateContents()
- for(var/i in 1 to 7)
- new /obj/item/reagent_containers/pill/penis_enlargement(src)
-
-/////////////
-//Organ Box//
-/////////////
-
-/obj/item/storage/belt/organbox
- name = "Organ Storge"
- desc = "A compact box that helps hold massive amounts of implants, organs, and some tools. Has a belt clip for easy carrying"
- w_class = WEIGHT_CLASS_BULKY
- icon = 'icons/obj/mysterybox.dmi'
- icon_state = "organbox_open"
- lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
- throw_speed = 1
- throw_range = 1
-
-/obj/item/storage/belt/organbox/ComponentInitialize()
- . = ..()
- GET_COMPONENT(STR, /datum/component/storage)
- STR.max_items = 16
- STR.max_w_class = WEIGHT_CLASS_BULKY
- STR.max_combined_w_class = 20
- STR.can_hold = typecacheof(list(
- /obj/item/storage/pill_bottle,
- /obj/item/reagent_containers/hypospray,
- /obj/item/healthanalyzer,
- /obj/item/reagent_containers/syringe,
- /obj/item/clothing/glasses/hud/health,
- /obj/item/hemostat,
- /obj/item/scalpel,
- /obj/item/retractor,
- /obj/item/cautery,
- /obj/item/surgical_drapes,
- /obj/item/autosurgeon,
- /obj/item/organ,
- /obj/item/implant,
- /obj/item/implantpad,
- /obj/item/implantcase,
- /obj/item/implanter,
- /obj/item/circuitboard/computer/operating,
- /obj/item/stack/sheet/mineral/silver,
- /obj/item/organ_storage
- ))
+
+/* First aid storage
+ * Contains:
+ * First Aid Kits
+ * Pill Bottles
+ * Dice Pack (in a pill bottle)
+ */
+
+/*
+ * First Aid Kits
+ */
+/obj/item/storage/firstaid
+ name = "first-aid kit"
+ desc = "It's an emergency medical kit for those serious boo-boos."
+ icon_state = "firstaid"
+ lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
+ throw_speed = 3
+ throw_range = 7
+ var/empty = FALSE
+
+/obj/item/storage/firstaid/regular
+ icon_state = "firstaid"
+ desc = "A first aid kit with the ability to heal common types of injuries."
+
+/obj/item/storage/firstaid/regular/suicide_act(mob/living/carbon/user)
+ user.visible_message("[user] begins giving [user.p_them()]self aids with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
+ return BRUTELOSS
+
+/obj/item/storage/firstaid/regular/PopulateContents()
+ if(empty)
+ return
+ new /obj/item/stack/medical/gauze(src)
+ new /obj/item/stack/medical/bruise_pack(src)
+ new /obj/item/stack/medical/bruise_pack(src)
+ new /obj/item/stack/medical/ointment(src)
+ new /obj/item/stack/medical/ointment(src)
+ new /obj/item/reagent_containers/hypospray/medipen(src)
+ new /obj/item/healthanalyzer(src)
+
+/obj/item/storage/firstaid/ancient
+ icon_state = "firstaid"
+ desc = "A first aid kit with the ability to heal common types of injuries."
+
+/obj/item/storage/firstaid/ancient/PopulateContents()
+ if(empty)
+ return
+ new /obj/item/stack/medical/gauze(src)
+ new /obj/item/stack/medical/bruise_pack(src)
+ new /obj/item/stack/medical/bruise_pack(src)
+ new /obj/item/stack/medical/bruise_pack(src)
+ new /obj/item/stack/medical/ointment(src)
+ new /obj/item/stack/medical/ointment(src)
+ new /obj/item/stack/medical/ointment(src)
+
+/obj/item/storage/firstaid/fire
+ name = "burn treatment kit"
+ desc = "A specialized medical kit for when the toxins lab -spontaneously- burns down."
+ icon_state = "ointment"
+ item_state = "firstaid-ointment"
+
+/obj/item/storage/firstaid/fire/suicide_act(mob/living/carbon/user)
+ user.visible_message("[user] begins rubbing \the [src] against [user.p_them()]self! It looks like [user.p_theyre()] trying to start a fire!")
+ return FIRELOSS
+
+/obj/item/storage/firstaid/fire/Initialize(mapload)
+ . = ..()
+ icon_state = pick("ointment","firefirstaid")
+
+/obj/item/storage/firstaid/fire/PopulateContents()
+ if(empty)
+ return
+ for(var/i in 1 to 3)
+ new /obj/item/reagent_containers/pill/patch/silver_sulf(src)
+ new /obj/item/reagent_containers/pill/oxandrolone(src)
+ new /obj/item/reagent_containers/pill/oxandrolone(src)
+ new /obj/item/reagent_containers/hypospray/medipen(src)
+ new /obj/item/healthanalyzer(src)
+
+/obj/item/storage/firstaid/toxin
+ name = "toxin treatment kit"
+ desc = "Used to treat toxic blood content and radiation poisoning."
+ icon_state = "antitoxin"
+ item_state = "firstaid-toxin"
+
+/obj/item/storage/firstaid/toxin/suicide_act(mob/living/carbon/user)
+ user.visible_message("[user] begins licking the lead paint off \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
+ return TOXLOSS
+
+/obj/item/storage/firstaid/toxin/Initialize(mapload)
+ . = ..()
+ icon_state = pick("antitoxin","antitoxfirstaid","antitoxfirstaid2","antitoxfirstaid3")
+
+/obj/item/storage/firstaid/toxin/PopulateContents()
+ if(empty)
+ return
+ for(var/i in 1 to 4)
+ new /obj/item/reagent_containers/syringe/charcoal(src)
+ for(var/i in 1 to 2)
+ new /obj/item/storage/pill_bottle/charcoal(src)
+ new /obj/item/healthanalyzer(src)
+
+/obj/item/storage/firstaid/radbgone
+ name = "radiation treatment kit"
+ desc = "Used to treat minor toxic blood content and major radiation poisoning."
+ icon_state = "antitoxin"
+ item_state = "firstaid-toxin"
+
+/obj/item/storage/firstaid/radbgone/suicide_act(mob/living/carbon/user)
+ user.visible_message("[user] begins licking the lead paint off \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
+ return TOXLOSS
+
+/obj/item/storage/firstaid/radbgone/PopulateContents()
+ if(empty)
+ return
+ if(prob(50))
+ new /obj/item/reagent_containers/pill/mutarad(src)
+ if(prob(80))
+ new /obj/item/reagent_containers/pill/antirad_plus(src)
+ new /obj/item/reagent_containers/syringe/charcoal(src)
+ new /obj/item/storage/pill_bottle/charcoal(src)
+ new /obj/item/reagent_containers/pill/mutadone(src)
+ new /obj/item/reagent_containers/pill/antirad(src)
+ new /obj/item/reagent_containers/food/drinks/bottle/vodka(src)
+ new /obj/item/healthanalyzer(src)
+
+
+/obj/item/storage/firstaid/o2
+ name = "oxygen deprivation treatment kit"
+ desc = "A box full of oxygen goodies."
+ icon_state = "o2"
+ item_state = "firstaid-o2"
+
+/obj/item/storage/firstaid/o2/suicide_act(mob/living/carbon/user)
+ user.visible_message("[user] begins hitting [user.p_their()] neck with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
+ return OXYLOSS
+
+/obj/item/storage/firstaid/o2/PopulateContents()
+ if(empty)
+ return
+ for(var/i in 1 to 4)
+ new /obj/item/reagent_containers/pill/salbutamol(src)
+ new /obj/item/reagent_containers/hypospray/medipen(src)
+ new /obj/item/reagent_containers/hypospray/medipen(src)
+ new /obj/item/healthanalyzer(src)
+
+/obj/item/storage/firstaid/brute
+ name = "brute trauma treatment kit"
+ desc = "A first aid kit for when you get toolboxed."
+ icon_state = "brute"
+ item_state = "firstaid-brute"
+
+/obj/item/storage/firstaid/brute/suicide_act(mob/living/carbon/user)
+ user.visible_message("[user] begins beating [user.p_them()]self over the head with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!")
+ return BRUTELOSS
+
+/obj/item/storage/firstaid/brute/PopulateContents()
+ if(empty)
+ return
+ for(var/i in 1 to 4)
+ new /obj/item/reagent_containers/pill/patch/styptic(src)
+ new /obj/item/stack/medical/gauze(src)
+ new /obj/item/stack/medical/gauze(src)
+ new /obj/item/healthanalyzer(src)
+
+/obj/item/storage/firstaid/tactical
+ name = "combat medical kit"
+ desc = "I hope you've got insurance."
+ icon_state = "bezerk"
+
+/obj/item/storage/firstaid/tactical/ComponentInitialize()
+ . = ..()
+ GET_COMPONENT(STR, /datum/component/storage)
+ STR.max_w_class = WEIGHT_CLASS_NORMAL
+
+/obj/item/storage/firstaid/tactical/PopulateContents()
+ if(empty)
+ return
+ new /obj/item/stack/medical/gauze(src)
+ new /obj/item/defibrillator/compact/combat/loaded(src)
+ new /obj/item/reagent_containers/hypospray/combat(src)
+ new /obj/item/reagent_containers/pill/patch/styptic(src)
+ new /obj/item/reagent_containers/pill/patch/silver_sulf(src)
+ new /obj/item/reagent_containers/syringe/lethal/choral(src)
+ new /obj/item/clothing/glasses/hud/health/night(src)
+
+/*
+ * Pill Bottles
+ */
+
+/obj/item/storage/pill_bottle
+ name = "pill bottle"
+ desc = "It's an airtight container for storing medication."
+ icon_state = "pill_canister"
+ icon = 'icons/obj/chemical.dmi'
+ item_state = "contsolid"
+ lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
+ w_class = WEIGHT_CLASS_SMALL
+
+/obj/item/storage/pill_bottle/ComponentInitialize()
+ . = ..()
+ GET_COMPONENT(STR, /datum/component/storage)
+ STR.allow_quick_gather = TRUE
+ STR.click_gather = TRUE
+ STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/dice))
+
+/obj/item/storage/pill_bottle/suicide_act(mob/user)
+ user.visible_message("[user] is trying to get the cap off [src]! It looks like [user.p_theyre()] trying to commit suicide!")
+ return (TOXLOSS)
+
+/obj/item/storage/pill_bottle/charcoal
+ name = "bottle of charcoal pills"
+ desc = "Contains pills used to counter toxins."
+
+/obj/item/storage/pill_bottle/charcoal/PopulateContents()
+ for(var/i in 1 to 7)
+ new /obj/item/reagent_containers/pill/charcoal(src)
+
+/obj/item/storage/pill_bottle/antirad
+ name = "bottle of charcoal pills"
+ desc = "Contains pills used to counter radiation poisoning."
+
+/obj/item/storage/pill_bottle/anitrad/PopulateContents()
+ for(var/i in 1 to 5)
+ new /obj/item/reagent_containers/pill/antirad(src)
+
+/obj/item/storage/pill_bottle/epinephrine
+ name = "bottle of epinephrine pills"
+ desc = "Contains pills used to stabilize patients."
+
+/obj/item/storage/pill_bottle/epinephrine/PopulateContents()
+ for(var/i in 1 to 7)
+ new /obj/item/reagent_containers/pill/epinephrine(src)
+
+/obj/item/storage/pill_bottle/mutadone
+ name = "bottle of mutadone pills"
+ desc = "Contains pills used to treat genetic abnormalities."
+
+/obj/item/storage/pill_bottle/mutadone/PopulateContents()
+ for(var/i in 1 to 7)
+ new /obj/item/reagent_containers/pill/mutadone(src)
+
+/obj/item/storage/pill_bottle/mannitol
+ name = "bottle of mannitol pills"
+ desc = "Contains pills used to treat brain damage."
+
+/obj/item/storage/pill_bottle/mannitol/PopulateContents()
+ for(var/i in 1 to 7)
+ new /obj/item/reagent_containers/pill/mannitol(src)
+
+/obj/item/storage/pill_bottle/stimulant
+ name = "bottle of stimulant pills"
+ desc = "Guaranteed to give you that extra burst of energy during a long shift!"
+
+/obj/item/storage/pill_bottle/stimulant/PopulateContents()
+ for(var/i in 1 to 5)
+ new /obj/item/reagent_containers/pill/stimulant(src)
+
+/obj/item/storage/pill_bottle/mining
+ name = "bottle of patches"
+ desc = "Contains patches used to treat brute and burn damage."
+
+/obj/item/storage/pill_bottle/mining/PopulateContents()
+ new /obj/item/reagent_containers/pill/patch/silver_sulf(src)
+ for(var/i in 1 to 3)
+ new /obj/item/reagent_containers/pill/patch/styptic(src)
+
+/obj/item/storage/pill_bottle/zoom
+ name = "suspicious pill bottle"
+ desc = "The label is pretty old and almost unreadable, you recognize some chemical compounds."
+
+/obj/item/storage/pill_bottle/zoom/PopulateContents()
+ for(var/i in 1 to 5)
+ new /obj/item/reagent_containers/pill/zoom(src)
+
+/obj/item/storage/pill_bottle/happy
+ name = "suspicious pill bottle"
+ desc = "There is a smiley on the top."
+
+/obj/item/storage/pill_bottle/happy/PopulateContents()
+ for(var/i in 1 to 5)
+ new /obj/item/reagent_containers/pill/happy(src)
+
+/obj/item/storage/pill_bottle/lsd
+ name = "suspicious pill bottle"
+ desc = "There is a badly drawn thing with the shape of a mushroom."
+
+/obj/item/storage/pill_bottle/lsd/PopulateContents()
+ for(var/i in 1 to 5)
+ new /obj/item/reagent_containers/pill/lsd(src)
+
+/obj/item/storage/pill_bottle/aranesp
+ name = "suspicious pill bottle"
+ desc = "The label says 'gotta go fast'."
+
+/obj/item/storage/pill_bottle/aranesp/PopulateContents()
+ for(var/i in 1 to 5)
+ new /obj/item/reagent_containers/pill/aranesp(src)
+
+/obj/item/storage/pill_bottle/psicodine
+ name = "bottle of psicodine pills"
+ desc = "Contains pills used to treat mental distress and traumas."
+
+/obj/item/storage/pill_bottle/psicodine/PopulateContents()
+ for(var/i in 1 to 7)
+ new /obj/item/reagent_containers/pill/psicodine(src)
+
+/obj/item/storage/pill_bottle/happiness
+ name = "happiness pill bottle"
+ desc = "The label is long gone, in its place an 'H' written with a marker."
+
+/obj/item/storage/pill_bottle/happiness/PopulateContents()
+ for(var/i in 1 to 5)
+ new /obj/item/reagent_containers/pill/happiness(src)
+
+/obj/item/storage/pill_bottle/antirad_plus
+ name = "anti radiation deluxe pill bottle"
+ desc = "The label says 'Med-Co branded pills'."
+
+/obj/item/storage/pill_bottle/antirad_plus/PopulateContents()
+ for(var/i in 1 to 7)
+ new /obj/item/reagent_containers/pill/antirad_plus(src)
+
+/obj/item/storage/pill_bottle/mutarad
+ name = "radiation treatment deluxe pill bottle"
+ desc = "The label says 'Med-Co branded pills' and below that 'Contains Mutadone in each pill!`."
+
+/obj/item/storage/pill_bottle/mutarad/PopulateContents()
+ for(var/i in 1 to 7)
+ new /obj/item/reagent_containers/pill/mutarad(src)
+
+/obj/item/storage/pill_bottle/penis_enlargement
+ name = "penis enlargement pills"
+ desc = "You want penis enlargement pills?"
+
+/obj/item/storage/pill_bottle/penis_enlargement/PopulateContents()
+ for(var/i in 1 to 7)
+ new /obj/item/reagent_containers/pill/penis_enlargement(src)
+
+/obj/item/storage/pill_bottle/breast_enlargement
+ name = "breast enlargement pills"
+ desc = "Made by Fermichem - They have a woman with breasts larger than she is on them. The warming states not to take more than 10u at a time."
+
+/obj/item/storage/pill_bottle/breast_enlargement/PopulateContents()
+ for(var/i in 1 to 7)
+ new /obj/item/reagent_containers/pill/breast_enlargement(src)
+
+/////////////
+//Organ Box//
+/////////////
+
+/obj/item/storage/belt/organbox
+ name = "Organ Storge"
+ desc = "A compact box that helps hold massive amounts of implants, organs, and some tools. Has a belt clip for easy carrying"
+ w_class = WEIGHT_CLASS_BULKY
+ icon = 'icons/obj/mysterybox.dmi'
+ icon_state = "organbox_open"
+ lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
+ throw_speed = 1
+ throw_range = 1
+
+/obj/item/storage/belt/organbox/ComponentInitialize()
+ . = ..()
+ GET_COMPONENT(STR, /datum/component/storage)
+ STR.max_items = 16
+ STR.max_w_class = WEIGHT_CLASS_BULKY
+ STR.max_combined_w_class = 20
+ STR.can_hold = typecacheof(list(
+ /obj/item/storage/pill_bottle,
+ /obj/item/reagent_containers/hypospray,
+ /obj/item/healthanalyzer,
+ /obj/item/reagent_containers/syringe,
+ /obj/item/clothing/glasses/hud/health,
+ /obj/item/hemostat,
+ /obj/item/scalpel,
+ /obj/item/retractor,
+ /obj/item/cautery,
+ /obj/item/surgical_drapes,
+ /obj/item/autosurgeon,
+ /obj/item/organ,
+ /obj/item/implant,
+ /obj/item/implantpad,
+ /obj/item/implantcase,
+ /obj/item/implanter,
+ /obj/item/circuitboard/computer/operating,
+ /obj/item/stack/sheet/mineral/silver,
+ /obj/item/organ_storage
+ ))
+
diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm
index 4924051855..eeebc6f4c5 100644
--- a/code/game/objects/items/storage/lockbox.dm
+++ b/code/game/objects/items/storage/lockbox.dm
@@ -48,14 +48,16 @@
to_chat(user, "It's locked!")
/obj/item/storage/lockbox/emag_act(mob/user)
- if(!broken)
- broken = TRUE
- SEND_SIGNAL(src, COMSIG_TRY_STORAGE_SET_LOCKSTATE, FALSE)
- desc += "It appears to be broken."
- icon_state = src.icon_broken
- if(user)
- visible_message("\The [src] has been broken by [user] with an electromagnetic card!")
- return
+ . = ..()
+ if(broken)
+ return
+ broken = TRUE
+ SEND_SIGNAL(src, COMSIG_TRY_STORAGE_SET_LOCKSTATE, FALSE)
+ desc += "It appears to be broken."
+ icon_state = src.icon_broken
+ if(user)
+ visible_message("\The [src] has been broken by [user] with an electromagnetic card!")
+ return TRUE
/obj/item/storage/lockbox/Entered()
. = ..()
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
index a6a3cea373..6e41527b24 100644
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ b/code/game/objects/items/storage/uplink_kits.dm
@@ -132,7 +132,7 @@
new /obj/item/card/emag(src) // 6 tc
if("ninja") // 40~ tc worth
- new /obj/item/katana(src) // Unique , basicly a better esword. 10 tc?
+ new /obj/item/katana(src) // Unique , basicly a better esword. 10 tc?
new /obj/item/implanter/adrenalin(src) // 8 tc
new /obj/item/throwing_star(src) // ~5 tc for all 6
new /obj/item/throwing_star(src)
@@ -294,6 +294,7 @@
new /obj/item/radio/headset/chameleon(src)
new /obj/item/stamp/chameleon(src)
new /obj/item/pda/chameleon(src)
+ new /obj/item/clothing/neck/cloak/chameleon(src)
//5*(2*4) = 5*8 = 45, 45 damage if you hit one person with all 5 stars.
//Not counting the damage it will do while embedded (2*4 = 8, at 15% chance)
diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm
index c263c2669d..cb5790e45f 100644
--- a/code/game/objects/items/storage/wallets.dm
+++ b/code/game/objects/items/storage/wallets.dm
@@ -36,7 +36,8 @@
/obj/item/reagent_containers/syringe,
/obj/item/screwdriver,
/obj/item/valentine,
- /obj/item/stamp))
+ /obj/item/stamp,
+ /obj/item/key))
/obj/item/storage/wallet/Exited(atom/movable/AM)
. = ..()
@@ -60,7 +61,7 @@
/obj/item/storage/wallet/update_icon()
var/new_state = "wallet"
if(front_id)
- new_state = "wallet_[front_id.icon_state]"
+ new_state = "wallet_id"
if(new_state != icon_state) //avoid so many icon state changes.
icon_state = new_state
diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm
index 1245b7de94..d409e40575 100644
--- a/code/game/objects/items/tanks/tanks.dm
+++ b/code/game/objects/items/tanks/tanks.dm
@@ -23,7 +23,7 @@
toggle_internals(user)
/obj/item/tank/proc/toggle_internals(mob/user)
- var/mob/living/carbon/human/H = user
+ var/mob/living/carbon/H = user
if(!istype(H))
return
@@ -33,13 +33,19 @@
H.update_internals_hud_icon(0)
else
if(!H.getorganslot(ORGAN_SLOT_BREATHING_TUBE))
- if(!H.wear_mask)
- to_chat(H, "You need a mask!")
- return
- if(H.wear_mask.mask_adjusted)
- H.wear_mask.adjustmask(H)
- if(!(H.wear_mask.clothing_flags & MASKINTERNALS))
- to_chat(H, "[H.wear_mask] can't use [src]!")
+ var/obj/item/clothing/check
+ var/internals = FALSE
+
+ for(check in GET_INTERNAL_SLOTS(H))
+ if(istype(check, /obj/item/clothing/mask))
+ var/obj/item/clothing/mask/M = check
+ if(M.mask_adjusted)
+ M.adjustmask(H)
+ if(CHECK_BITFIELD(check.clothing_flags, ALLOWINTERNALS))
+ internals = TRUE
+
+ if(!internals)
+ to_chat(H, "You are not wearing an internals mask!")
return
if(H.internal)
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 9ac5261e5f..46fabea8b0 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -30,6 +30,7 @@
throw_speed = 3
throw_range = 7
force = 0
+ total_mass = TOTAL_MASS_TINY_ITEM
/*
@@ -112,10 +113,6 @@
/obj/item/toy/syndicateballoon
name = "syndicate balloon"
desc = "There is a tag on the back that reads \"FUK NT!11!\"."
- throwforce = 0
- throw_speed = 3
- throw_range = 7
- force = 0
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "syndballoon"
item_state = "syndballoon"
@@ -225,6 +222,8 @@
w_class = WEIGHT_CLASS_SMALL
attack_verb = list("attacked", "struck", "hit")
var/hacked = FALSE
+ total_mass = 0.4
+ var/total_mass_on = TOTAL_MASS_TOY_SWORD
/obj/item/toy/sword/attack_self(mob/user)
active = !( active )
@@ -274,6 +273,9 @@
else
return ..()
+/obj/item/toy/sword/getweight()
+ return (active ? total_mass_on : total_mass) || w_class *1.25
+
/*
* Foam armblade
*/
@@ -327,12 +329,13 @@
force_unwielded = 0
force_wielded = 0
attack_verb = list("attacked", "struck", "hit")
+ total_mass_on = TOTAL_MASS_TOY_SWORD
/obj/item/twohanded/dualsaber/toy/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
- return 0
+ return FALSE
/obj/item/twohanded/dualsaber/toy/IsReflect()//Stops Toy Dualsabers from reflecting energy projectiles
- return 0
+ return FALSE
/obj/item/toy/katana
name = "replica katana"
@@ -346,6 +349,7 @@
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
force = 5
throwforce = 5
+ total_mass = null
w_class = WEIGHT_CLASS_NORMAL
attack_verb = list("attacked", "slashed", "stabbed", "sliced")
hitsound = 'sound/weapons/bladeslice.ogg'
diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm
index bf63a96f05..82bf2c6b5f 100644
--- a/code/game/objects/items/twohanded.dm
+++ b/code/game/objects/items/twohanded.dm
@@ -28,6 +28,8 @@
var/force_wielded = 0
var/wieldsound = null
var/unwieldsound = null
+ var/slowdown_wielded = 0
+ item_flags = SLOWS_WHILE_IN_HAND
/obj/item/twohanded/proc/unwield(mob/living/carbon/user, show_message = TRUE)
if(!wielded || !user)
@@ -55,7 +57,7 @@
var/obj/item/twohanded/offhand/O = user.get_inactive_held_item()
if(O && istype(O))
O.unwield()
- return
+ slowdown -= slowdown_wielded
/obj/item/twohanded/proc/wield(mob/living/carbon/user)
if(wielded)
@@ -85,7 +87,7 @@
O.desc = "Your second grip on [src]."
O.wielded = TRUE
user.put_in_inactive_hand(O)
- return
+ slowdown += slowdown_wielded
/obj/item/twohanded/dropped(mob/user)
. = ..()
@@ -279,6 +281,7 @@
wieldsound = 'sound/weapons/saberon.ogg'
unwieldsound = 'sound/weapons/saberoff.ogg'
hitsound = "swing_hit"
+ var/hitsound_on = 'sound/weapons/blade1.ogg'
armour_penetration = 35
item_color = "green"
light_color = "#00ff00"//green
@@ -290,8 +293,10 @@
var/hacked = FALSE
var/brightness_on = 6 //TWICE AS BRIGHT AS A REGULAR ESWORD
var/list/possible_colors = list("red", "blue", "green", "purple")
- total_mass = 0.375 //Survival flashlights typically weigh around 5 ounces.
- var/total_mass_on = 3.4 //The typical medieval sword, on the other hand, weighs roughly 3 pounds. //Values copied from the regular e-sword
+ var/list/rainbow_colors = list(LIGHT_COLOR_RED, LIGHT_COLOR_GREEN, LIGHT_COLOR_LIGHT_CYAN, LIGHT_COLOR_LAVENDER)
+ var/spinnable = TRUE
+ total_mass = 0.4 //Survival flashlights typically weigh around 5 ounces.
+ var/total_mass_on = 3.4
/obj/item/twohanded/dualsaber/suicide_act(mob/living/carbon/user)
if(wielded)
@@ -353,7 +358,7 @@
if(HAS_TRAIT(user, TRAIT_CLUMSY) && (wielded) && prob(40))
impale(user)
return
- if((wielded) && prob(50))
+ if(spinnable && (wielded) && prob(50))
INVOKE_ASYNC(src, .proc/jedi_spin, user)
/obj/item/twohanded/dualsaber/proc/jedi_spin(mob/living/user)
@@ -406,11 +411,14 @@
/obj/item/twohanded/dualsaber/process()
if(wielded)
if(hacked)
- light_color = pick(LIGHT_COLOR_RED, LIGHT_COLOR_GREEN, LIGHT_COLOR_LIGHT_CYAN, LIGHT_COLOR_LAVENDER)
+ rainbow_process()
open_flame()
else
STOP_PROCESSING(SSobj, src)
+/obj/item/twohanded/dualsaber/proc/rainbow_process()
+ light_color = pick(rainbow_colors)
+
/obj/item/twohanded/dualsaber/IsReflect()
if(wielded)
return 1
@@ -428,7 +436,8 @@
playsound(loc, hitsound, get_clamped_volume(), 1, -1)
add_fingerprint(user)
// Light your candles while spinning around the room
- INVOKE_ASYNC(src, .proc/jedi_spin, user)
+ if(spinnable)
+ INVOKE_ASYNC(src, .proc/jedi_spin, user)
/obj/item/twohanded/dualsaber/green
possible_colors = list("green")
@@ -478,6 +487,7 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30)
var/obj/item/grenade/explosive = null
var/war_cry = "AAAAARGH!!!"
+ var/icon_prefix = "spearglass"
/obj/item/twohanded/spear/Initialize()
. = ..()
@@ -520,7 +530,7 @@
if(explosive)
icon_state = "spearbomb[wielded]"
else
- icon_state = "spearglass[wielded]"
+ icon_state = "[icon_prefix][wielded]"
/obj/item/twohanded/spear/afterattack(atom/movable/AM, mob/user, proximity)
. = ..()
@@ -547,6 +557,13 @@
src.war_cry = input
/obj/item/twohanded/spear/CheckParts(list/parts_list)
+ var/obj/item/shard/tip = locate() in parts_list
+ if (istype(tip, /obj/item/shard/plasma))
+ force_wielded = 19
+ force_unwielded = 11
+ throwforce = 21
+ icon_prefix = "spearplasma"
+ qdel(tip)
var/obj/item/twohanded/spear/S = locate() in parts_list
if(S)
if(S.explosive)
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index 48681c3d6d..c6384e7438 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -69,6 +69,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
+ total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
/obj/item/claymore/Initialize()
. = ..()
@@ -223,11 +224,12 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
+ total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
/obj/item/katana/cursed
slot_flags = null
-/obj/item/katana/Initialize()
+/obj/item/katana/cursed/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NODROP, CURSED_ITEM_TRAIT)
@@ -253,7 +255,9 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
var/obj/item/twohanded/spear/S = new /obj/item/twohanded/spear
remove_item_from_storage(user)
- qdel(I)
+ if (!user.transferItemToLoc(I, S))
+ return
+ S.CheckParts(list(I))
qdel(src)
user.put_in_hands(S)
@@ -431,6 +435,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
sharpness = IS_SHARP
attack_verb = list("sawed", "torn", "cut", "chopped", "diced")
hitsound = 'sound/weapons/chainsawhit.ogg'
+ total_mass = TOTAL_MASS_HAND_REPLACEMENT
/obj/item/mounted_chainsaw/Initialize()
. = ..()
@@ -510,6 +515,19 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
var/homerun_able = 0
total_mass = 2.7 //a regular wooden major league baseball bat weighs somewhere between 2 to 3.4 pounds, according to google
+/obj/item/melee/baseball_bat/chaplain
+ name = "blessed baseball bat"
+ desc = "There ain't a cult in the league that can withstand a swatter."
+ force = 14
+ throwforce = 14
+ obj_flags = UNIQUE_RENAME
+ var/chaplain_spawnable = TRUE
+ total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
+
+/obj/item/melee/baseball_bat/chaplain/Initialize()
+ . = ..()
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+
/obj/item/melee/baseball_bat/homerun
name = "home run bat"
desc = "This thing looks dangerous... Dangerously good at baseball, that is."
diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm
index 1ab28a33de..2093ae5660 100644
--- a/code/game/objects/structures/barsigns.dm
+++ b/code/game/objects/structures/barsigns.dm
@@ -112,12 +112,16 @@
/obj/structure/sign/barsign/emag_act(mob/user)
+ . = ..()
if(broken || (obj_flags & EMAGGED))
to_chat(user, "Nothing interesting happens!")
return
obj_flags |= EMAGGED
to_chat(user, "You emag the barsign. Takeover in progress...")
- sleep(10 SECONDS)
+ addtimer(CALLBACK(src, .proc/syndie_bar_good), 10 SECONDS)
+ return TRUE
+
+/obj/structure/sign/barsign/proc/syndie_bar_good()
set_sign(new /datum/barsign/hiddensigns/syndibarsign)
req_access = list(ACCESS_SYNDICATE)
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index eedb49f2c3..edcb4a6181 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -36,6 +36,9 @@
var/icon_welded = "welded"
var/obj/item/electronics/airlock/lockerelectronics //Installed electronics
var/lock_in_use = FALSE //Someone is doing some stuff with the lock here, better not proceed further
+ var/eigen_teleport = FALSE //If the closet leads to Mr Tumnus.
+ var/obj/structure/closet/eigen_target //Where you go to.
+
/obj/structure/closet/Initialize(mapload)
. = ..()
@@ -144,6 +147,8 @@
/obj/structure/closet/proc/togglelock(mob/living/user)
add_fingerprint(user)
+ if(eigen_target)
+ return
if(opened)
return
if(!can_lock(user))
@@ -186,7 +191,12 @@
if(contents.len >= storage_capacity)
return -1
if(insertion_allowed(AM))
- AM.forceMove(src)
+ if(eigen_teleport) // For teleporting people with linked lockers.
+ do_teleport(AM, get_turf(eigen_target), 0)
+ if(eigen_target.opened == FALSE)
+ eigen_target.bust_open()
+ else
+ AM.forceMove(src)
return TRUE
else
return FALSE
@@ -339,6 +349,9 @@
to_chat(user, "You begin cutting \the [src] apart...")
if(W.use_tool(src, user, 40, volume=50))
+ if(eigen_teleport)
+ to_chat(user, "The unstable nature of \the [src] makes it impossible to cut!")
+ return
if(!opened)
return
user.visible_message("[user] slices apart \the [src].",
@@ -363,6 +376,9 @@
to_chat(user, "You begin [welded ? "unwelding":"welding"] \the [src]...")
if(W.use_tool(src, user, 40, volume=50))
+ if(eigen_teleport)
+ to_chat(user, "The unstable nature of \the [src] makes it impossible to weld!")
+ return
if(opened)
return
welded = !welded
@@ -525,17 +541,18 @@
dive_into(user)
/obj/structure/closet/emag_act(mob/user)
- if(secure && !broken)
- user.visible_message("Sparks fly from [src]!",
- "You scramble [src]'s lock, breaking it open!",
- "You hear a faint electrical spark.")
- playsound(src, "sparks", 50, 1)
- broken = TRUE
- locked = FALSE
- if(!QDELETED(lockerelectronics))
- qdel(lockerelectronics)
- lockerelectronics = null
- update_icon()
+ . = ..()
+ if(!secure || broken)
+ return
+ user.visible_message("Sparks fly from [src]!",
+ "You scramble [src]'s lock, breaking it open!",
+ "You hear a faint electrical spark.")
+ playsound(src, "sparks", 50, 1)
+ broken = TRUE
+ locked = FALSE
+ if(!QDELETED(lockerelectronics))
+ QDEL_NULL(lockerelectronics)
+ update_icon()
/obj/structure/closet/get_remote_view_fullscreens(mob/user)
if(user.stat == DEAD || !(user.sight & (SEEOBJS|SEEMOBS)))
diff --git a/code/game/objects/structures/crates_lockers/closets/job_closets.dm b/code/game/objects/structures/crates_lockers/closets/job_closets.dm
index d2ab9ea6fb..b49d0a77d5 100644
--- a/code/game/objects/structures/crates_lockers/closets/job_closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets/job_closets.dm
@@ -111,9 +111,9 @@
new /obj/item/clothing/accessory/pocketprotector/cosmetology(src)
new /obj/item/clothing/under/rank/chaplain(src)
new /obj/item/clothing/shoes/sneakers/black(src)
- new /obj/item/clothing/suit/nun(src)
+ new /obj/item/clothing/suit/chaplain/nun(src)
new /obj/item/clothing/head/nun_hood(src)
- new /obj/item/clothing/suit/holidaypriest(src)
+ new /obj/item/clothing/suit/chaplain/holidaypriest(src)
new /obj/item/storage/backpack/cultpack(src)
new /obj/item/storage/fancy/candle_box(src)
new /obj/item/storage/fancy/candle_box(src)
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
index 167823b9be..a7adafdad4 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
@@ -33,6 +33,7 @@
new /obj/item/extinguisher/advanced(src)
new /obj/item/storage/photo_album/CE(src)
new /obj/item/storage/lockbox/medal/engineering(src)
+ new /obj/item/construction/rcd/loaded/upgraded(src)
/obj/structure/closet/secure_closet/engineering_electrical
name = "electrical supplies locker"
diff --git a/code/game/objects/structures/dresser.dm b/code/game/objects/structures/dresser.dm
index 8dc560b936..05e62c196f 100644
--- a/code/game/objects/structures/dresser.dm
+++ b/code/game/objects/structures/dresser.dm
@@ -79,4 +79,4 @@
var/n_color = input(H, "Choose your [garment_type]'\s color.", "Character Preference", default_color) as color|null
if(!n_color || !H.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return default_color
- return sanitize_hexcolor(n_color, include_crunch= TRUE)
+ return sanitize_hexcolor(n_color, 3, FALSE, default_color)
diff --git a/code/game/objects/structures/femur_breaker.dm b/code/game/objects/structures/femur_breaker.dm
index 077eb25688..e3002a8fae 100644
--- a/code/game/objects/structures/femur_breaker.dm
+++ b/code/game/objects/structures/femur_breaker.dm
@@ -83,8 +83,9 @@
icon_state = "breaker_drop"
/obj/structure/femur_breaker/proc/damage_leg(mob/living/carbon/human/H)
- H.say("AAAAAAAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHH!!", forced = "femur broken")
+ H.emote("scream")
H.apply_damage(150, BRUTE, pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
+ H.adjustBruteLoss(rand(5,20) + (max(0, H.health))) //Make absolutely sure they end up in crit, so that they can succumb if they wish.
/obj/structure/femur_breaker/proc/raise_slat()
slat_status = BREAKER_SLAT_RAISED
@@ -171,4 +172,4 @@
#undef BREAKER_ACTIVATE_DELAY
#undef BREAKER_WRENCH_DELAY
#undef BREAKER_ACTION_INUSE
-#undef BREAKER_ACTION_WRENCH
\ No newline at end of file
+#undef BREAKER_ACTION_WRENCH
diff --git a/code/game/objects/structures/loom.dm b/code/game/objects/structures/loom.dm
new file mode 100644
index 0000000000..c4e1968e59
--- /dev/null
+++ b/code/game/objects/structures/loom.dm
@@ -0,0 +1,21 @@
+//Loom, turns raw cotton and durathread into their respective fabrics.
+
+/obj/structure/loom
+ name = "loom"
+ desc = "A simple device used to weave cloth and other thread-based fabrics together into usable material."
+ icon = 'icons/obj/hydroponics/equipment.dmi'
+ icon_state = "loom"
+ density = TRUE
+ anchored = TRUE
+
+/obj/structure/loom/attackby(obj/item/stack/sheet/W, mob/user)
+ if(W.is_fabric && W.amount > 1)
+ user.show_message("You start weaving the [W.name] through the loom..", 1)
+ if(W.use_tool(src, user, W.pull_effort))
+ new W.loom_result(drop_location())
+ user.show_message("You weave the [W.name] into a workable fabric.", 1)
+ W.amount = (W.amount - 2)
+ if(W.amount < 1)
+ qdel(W)
+ else
+ user.show_message("You need a valid fabric and at least 2 of said fabric before using this.", 1)
\ No newline at end of file
diff --git a/code/game/objects/structures/table_frames.dm b/code/game/objects/structures/table_frames.dm
index e979d4f18e..226d279288 100644
--- a/code/game/objects/structures/table_frames.dm
+++ b/code/game/objects/structures/table_frames.dm
@@ -100,6 +100,14 @@
to_chat(user, "You start adding [B] to [src]...")
if(do_after(user, 20, target = src) && B.use(1))
make_new_table(/obj/structure/table/bronze)
+ else if(istype(I, /obj/item/stack/sheet/plasmaglass))
+ var/obj/item/stack/sheet/plasmaglass/G = I
+ if(G.get_amount() < 1)
+ to_chat(user, "You need one plasmaglass sheet to do this!")
+ return
+ to_chat(user, "You start adding [G] to [src]...")
+ if(do_after(user, 20, target = src) && G.use(1))
+ make_new_table(/obj/structure/table/plasmaglass)
else
return ..()
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 8c29c1b2c5..fcffafb262 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -258,6 +258,53 @@
for(var/obj/item/shard/S in debris)
S.color = NARSIE_WINDOW_COLOUR
+/*
+ * Plasmaglass tables
+ */
+/obj/structure/table/plasmaglass
+ name = "plasmaglass table"
+ desc = "A glasstable, but it's pink and more sturdy. What will Nanotrasen design next with plasma?"
+ icon = 'icons/obj/smooth_structures/plasmaglass_table.dmi'
+ icon_state = "plasmaglass_table"
+ climbable = TRUE
+ buildstack = /obj/item/stack/sheet/plasmaglass
+ canSmoothWith = null
+ max_integrity = 270
+ resistance_flags = ACID_PROOF
+ armor = list("melee" = 10, "bullet" = 5, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
+ var/list/debris = list()
+
+/obj/structure/table/plasmaglass/New()
+ . = ..()
+ debris += new frame
+ debris += new /obj/item/shard/plasma
+
+/obj/structure/table/plasmaglass/Destroy()
+ QDEL_LIST(debris)
+ . = ..()
+
+/obj/structure/table/plasmaglass/proc/check_break(mob/living/M)
+ return
+
+/obj/structure/table/plasmaglass/deconstruct(disassembled = TRUE, wrench_disassembly = 0)
+ if(!(flags_1 & NODECONSTRUCT_1))
+ if(disassembled)
+ ..()
+ return
+ else
+ var/turf/T = get_turf(src)
+ playsound(T, "shatter", 50, 1)
+ for(var/X in debris)
+ var/atom/movable/AM = X
+ AM.forceMove(T)
+ debris -= AM
+ qdel(src)
+
+/obj/structure/table/plasmaglass/narsie_act()
+ color = NARSIE_WINDOW_COLOUR
+ for(var/obj/item/shard/S in debris)
+ S.color = NARSIE_WINDOW_COLOUR
+
/*
* Wooden tables
*/
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index a26d57e3e1..9fc055c2ba 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -281,6 +281,8 @@
. += new /obj/effect/decal/cleanable/glass(location)
if (reinf)
. += new /obj/item/stack/rods(location, (fulltile ? 2 : 1))
+ if (fulltile)
+ . += new /obj/item/shard(location)
/obj/structure/window/proc/can_be_rotated(mob/user,rotation_type)
if(anchored)
@@ -409,6 +411,15 @@
glass_type = /obj/item/stack/sheet/plasmaglass
rad_insulation = RAD_NO_INSULATION
+/obj/structure/window/plasma/spawnDebris(location)
+ . = list()
+ . += new /obj/item/shard/plasma(location)
+ . += new /obj/effect/decal/cleanable/glass/plasma(location)
+ if (reinf)
+ . += new /obj/item/stack/rods(location, (fulltile ? 2 : 1))
+ if (fulltile)
+ . += new /obj/item/shard/plasma(location)
+
/obj/structure/window/plasma/spawner/east
dir = EAST
diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm
index b00efc7ed6..194014b61a 100644
--- a/code/game/turfs/simulated/floor.dm
+++ b/code/game/turfs/simulated/floor.dm
@@ -236,6 +236,10 @@
return list("mode" = RCD_DECONSTRUCT, "delay" = 50, "cost" = 33)
if(RCD_WINDOWGRILLE)
return list("mode" = RCD_WINDOWGRILLE, "delay" = 10, "cost" = 4)
+ if(RCD_MACHINE)
+ return list("mode" = RCD_MACHINE, "delay" = 20, "cost" = 25)
+ if(RCD_COMPUTER)
+ return list("mode" = RCD_COMPUTER, "delay" = 20, "cost" = 25)
return FALSE
/turf/open/floor/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
@@ -274,4 +278,20 @@
var/obj/structure/grille/G = new(src)
G.anchored = TRUE
return TRUE
+ if(RCD_MACHINE)
+ if(locate(/obj/structure/frame/machine) in src)
+ return FALSE
+ var/obj/structure/frame/machine/M = new(src)
+ M.state = 2
+ M.icon_state = "box_1"
+ M.anchored = TRUE
+ return TRUE
+ if(RCD_COMPUTER)
+ if(locate(/obj/structure/frame/computer) in src)
+ return FALSE
+ var/obj/structure/frame/computer/C = new(src)
+ C.anchored = TRUE
+ C.setDir(the_rcd.computer_dir)
+ return TRUE
+
return FALSE
diff --git a/code/game/turfs/simulated/wall/misc_walls.dm b/code/game/turfs/simulated/wall/misc_walls.dm
index dfc6972578..8b63d60939 100644
--- a/code/game/turfs/simulated/wall/misc_walls.dm
+++ b/code/game/turfs/simulated/wall/misc_walls.dm
@@ -7,6 +7,7 @@
smooth = SMOOTH_MORE
sheet_type = /obj/item/stack/sheet/runed_metal
sheet_amount = 1
+ explosion_block = 10
girder_type = /obj/structure/girder/cult
/turf/closed/wall/mineral/cult/Initialize()
@@ -49,7 +50,7 @@
/turf/closed/wall/clockwork
name = "clockwork wall"
desc = "A huge chunk of warm metal. The clanging of machinery emanates from within."
- explosion_block = 2
+ explosion_block = 5
hardness = 10
slicing_duration = 80
sheet_type = /obj/item/stack/tile/brass
diff --git a/code/game/world.dm b/code/game/world.dm
index dedf822597..e9c8433006 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -137,7 +137,7 @@ GLOBAL_VAR(restart_counter)
// but those are both private, so let's put the commit info in the runtime
// log which is ultimately public.
log_runtime(GLOB.revdata.get_log_message())
-
+
/world/Topic(T, addr, master, key)
TGS_TOPIC //redirect to server tools if necessary
@@ -270,7 +270,8 @@ GLOBAL_VAR(restart_counter)
if (M.client)
n++
- features += "[SSmapping.config.map_name]" //CIT CHANGE - makes the hub entry display the current map
+ if(SSmapping.config) // this just stops the runtime, honk.
+ features += "[SSmapping.config.map_name]" //CIT CHANGE - makes the hub entry display the current map
if(get_security_level())//CIT CHANGE - makes the hub entry show the security level
features += "[get_security_level()] alert"
diff --git a/code/modules/VR/vr_sleeper.dm b/code/modules/VR/vr_sleeper.dm
index bfbf6b5b79..89e9c33ecc 100644
--- a/code/modules/VR/vr_sleeper.dm
+++ b/code/modules/VR/vr_sleeper.dm
@@ -54,12 +54,16 @@
only_current_user_can_interact = TRUE
/obj/machinery/vr_sleeper/hugbox/emag_act(mob/user)
- return
+ return SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
/obj/machinery/vr_sleeper/emag_act(mob/user)
+ . = ..()
+ if(you_die_in_the_game_you_die_for_real)
+ return
you_die_in_the_game_you_die_for_real = TRUE
sparks.start()
addtimer(CALLBACK(src, .proc/emagNotify), 150)
+ return TRUE
/obj/machinery/vr_sleeper/update_icon()
icon_state = "[initial(icon_state)][state_open ? "-open" : ""]"
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index b400f44b98..555c35980d 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -423,6 +423,25 @@
if(GLOB.master_mode == "secret")
dat += "(Force Secret Mode) "
+ if(GLOB.master_mode == "dynamic")
+ if(SSticker.current_state <= GAME_STATE_PREGAME)
+ dat += "(Force Roundstart Rulesets) "
+ if (GLOB.dynamic_forced_roundstart_ruleset.len > 0)
+ for(var/datum/dynamic_ruleset/roundstart/rule in GLOB.dynamic_forced_roundstart_ruleset)
+ dat += {"-> [rule.name] <- "}
+ dat += "(Clear Rulesets) "
+ dat += "(Dynamic mode options) "
+ else if (SSticker.IsRoundInProgress())
+ dat += "(Force Next Latejoin Ruleset) "
+ if (SSticker && SSticker.mode && istype(SSticker.mode,/datum/game_mode/dynamic))
+ var/datum/game_mode/dynamic/mode = SSticker.mode
+ if (mode.forced_latejoin_rule)
+ dat += {"-> [mode.forced_latejoin_rule.name] <- "}
+ dat += "(Execute Midround Ruleset!) "
+ dat += " "
+ if(SSticker.IsRoundInProgress())
+ dat += "(Game Mode Panel) "
+
dat += {"
Create Object
@@ -839,6 +858,44 @@
browser.set_content(dat.Join())
browser.open()
+/datum/admins/proc/dynamic_mode_options(mob/user)
+ var/dat = {"
+ Dynamic Mode Options
+
+ Common options
+ All these options can be changed midround.
+
+ Force extended: - Option is [GLOB.dynamic_forced_extended ? "ON" : "OFF"].
+ This will force the round to be extended. No rulesets will be drafted.
+
+ No stacking: - Option is [GLOB.dynamic_no_stacking ? "ON" : "OFF"].
+ Unless the threat goes above [GLOB.dynamic_stacking_limit], only one "round-ender" ruleset will be drafted.
+
+ Classic secret mode: - Option is [GLOB.dynamic_classic_secret ? "ON" : "OFF"].
+ Only one roundstart ruleset will be drafted. Only traitors and minor roles will latespawn.
+
+
+ Forced threat level: Current value : [GLOB.dynamic_forced_threat_level].
+ The value threat is set to if it is higher than -1.
+
+ High population limit: Current value : [GLOB.dynamic_high_pop_limit].
+ The threshold at which "high population override" will be in effect.
+
+ Stacking threeshold: Current value : [GLOB.dynamic_stacking_limit].
+ The threshold at which "round-ender" rulesets will stack. A value higher than 100 ensure this never happens.
+ Advanced parameters
+ Curve centre: -> [GLOB.dynamic_curve_centre] <-
+ Curve width: -> [GLOB.dynamic_curve_width] <-
+ Latejoin injection delay:
+ Minimum: -> [GLOB.dynamic_latejoin_delay_min / 60 / 10] <- Minutes
+ Maximum: -> [GLOB.dynamic_latejoin_delay_max / 60 / 10] <- Minutes
+ Midround injection delay:
+ Minimum: -> [GLOB.dynamic_midround_delay_min / 60 / 10] <- Minutes
+ Maximum: -> [GLOB.dynamic_midround_delay_max / 60 / 10] <- Minutes
+ "}
+
+ user << browse(dat, "window=dyn_mode_options;size=900x650")
+
/datum/admins/proc/create_or_modify_area()
set category = "Debug"
set name = "Create or modify area"
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index d881044757..91df9ef85c 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -291,6 +291,11 @@
else if(href_list["editrights"])
edit_rights_topic(href_list)
+ else if(href_list["gamemode_panel"])
+ if(!check_rights(R_ADMIN))
+ return
+ SSticker.mode.admin_panel()
+
else if(href_list["call_shuttle"])
if(!check_rights(R_ADMIN))
return
@@ -1342,6 +1347,291 @@
else if(href_list["f_secret"])
return HandleFSecret()
+
+ else if(href_list["f_dynamic_roundstart"])
+ if(!check_rights(R_ADMIN))
+ return
+ if(SSticker && SSticker.mode)
+ return alert(usr, "The game has already started.", null, null, null, null)
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode.", null, null, null, null)
+ var/roundstart_rules = list()
+ for (var/rule in subtypesof(/datum/dynamic_ruleset/roundstart))
+ var/datum/dynamic_ruleset/roundstart/newrule = new rule()
+ roundstart_rules[newrule.name] = newrule
+ var/added_rule = input(usr,"What ruleset do you want to force? This will bypass threat level and population restrictions.", "Rigging Roundstart", null) as null|anything in roundstart_rules
+ if (added_rule)
+ GLOB.dynamic_forced_roundstart_ruleset += roundstart_rules[added_rule]
+ log_admin("[key_name(usr)] set [added_rule] to be a forced roundstart ruleset.")
+ message_admins("[key_name(usr)] set [added_rule] to be a forced roundstart ruleset.", 1)
+ Game()
+
+ else if(href_list["f_dynamic_roundstart_clear"])
+ if(!check_rights(R_ADMIN))
+ return
+ GLOB.dynamic_forced_roundstart_ruleset = list()
+ Game()
+ log_admin("[key_name(usr)] cleared the rigged roundstart rulesets. The mode will pick them as normal.")
+ message_admins("[key_name(usr)] cleared the rigged roundstart rulesets. The mode will pick them as normal.", 1)
+
+ else if(href_list["f_dynamic_roundstart_remove"])
+ if(!check_rights(R_ADMIN))
+ return
+ var/datum/dynamic_ruleset/roundstart/rule = locate(href_list["f_dynamic_roundstart_remove"])
+ GLOB.dynamic_forced_roundstart_ruleset -= rule
+ Game()
+ log_admin("[key_name(usr)] removed [rule] from the forced roundstart rulesets.")
+ message_admins("[key_name(usr)] removed [rule] from the forced roundstart rulesets.", 1)
+
+ else if(href_list["f_dynamic_latejoin"])
+ if(!check_rights(R_ADMIN))
+ return
+ if(!SSticker || !SSticker.mode)
+ return alert(usr, "The game must start first.", null, null, null, null)
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+ var/latejoin_rules = list()
+ for (var/rule in subtypesof(/datum/dynamic_ruleset/latejoin))
+ var/datum/dynamic_ruleset/latejoin/newrule = new rule()
+ latejoin_rules[newrule.name] = newrule
+ var/added_rule = input(usr,"What ruleset do you want to force upon the next latejoiner? This will bypass threat level and population restrictions.", "Rigging Latejoin", null) as null|anything in latejoin_rules
+ if (added_rule)
+ var/datum/game_mode/dynamic/mode = SSticker.mode
+ mode.forced_latejoin_rule = latejoin_rules[added_rule]
+ log_admin("[key_name(usr)] set [added_rule] to proc on the next latejoin.")
+ message_admins("[key_name(usr)] set [added_rule] to proc on the next latejoin.", 1)
+ Game()
+
+ else if(href_list["f_dynamic_latejoin_clear"])
+ if(!check_rights(R_ADMIN))
+ return
+ if (SSticker && SSticker.mode && istype(SSticker.mode,/datum/game_mode/dynamic))
+ var/datum/game_mode/dynamic/mode = SSticker.mode
+ mode.forced_latejoin_rule = null
+ Game()
+ log_admin("[key_name(usr)] cleared the forced latejoin ruleset.")
+ message_admins("[key_name(usr)] cleared the forced latejoin ruleset.", 1)
+
+ else if(href_list["f_dynamic_midround"])
+ if(!check_rights(R_ADMIN))
+ return
+ if(!SSticker || !SSticker.mode)
+ return alert(usr, "The game must start first.", null, null, null, null)
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+ var/midround_rules = list()
+ for (var/rule in subtypesof(/datum/dynamic_ruleset/midround))
+ var/datum/dynamic_ruleset/midround/newrule = new rule()
+ midround_rules[newrule.name] = rule
+ var/added_rule = input(usr,"What ruleset do you want to force right now? This will bypass threat level and population restrictions.", "Execute Ruleset", null) as null|anything in midround_rules
+ if (added_rule)
+ var/datum/game_mode/dynamic/mode = SSticker.mode
+ log_admin("[key_name(usr)] executed the [added_rule] ruleset.")
+ message_admins("[key_name(usr)] executed the [added_rule] ruleset.", 1)
+ mode.picking_specific_rule(midround_rules[added_rule],1)
+
+ else if (href_list["f_dynamic_options"])
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(SSticker && SSticker.mode)
+ return alert(usr, "The game has already started.", null, null, null, null)
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+
+ dynamic_mode_options(usr)
+
+ else if(href_list["f_dynamic_roundstart_centre"])
+ if(!check_rights(R_ADMIN))
+ return
+ if(SSticker && SSticker.mode)
+ return alert(usr, "The game has already started.", null, null, null, null)
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+
+ var/new_centre = input(usr,"Change the centre of the dynamic mode threat curve. A negative value will give a more peaceful round ; a positive value, a round with higher threat. Any number between -5 and +5 is allowed.", "Change curve centre", null) as num
+ if (new_centre < -5 || new_centre > 5)
+ return alert(usr, "Only values between -5 and +5 are allowed.", null, null, null, null)
+
+ log_admin("[key_name(usr)] changed the distribution curve center to [new_centre].")
+ message_admins("[key_name(usr)] changed the distribution curve center to [new_centre]", 1)
+ GLOB.dynamic_curve_centre = new_centre
+ dynamic_mode_options(usr)
+
+ else if(href_list["f_dynamic_roundstart_width"])
+ if(!check_rights(R_ADMIN))
+ return
+ if(SSticker && SSticker.mode)
+ return alert(usr, "The game has already started.", null, null, null, null)
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+
+ var/new_width = input(usr,"Change the width of the dynamic mode threat curve. A higher value will favour extreme rounds ; a lower value, a round closer to the average. Any Number between 0.5 and 4 are allowed.", "Change curve width", null) as num
+ if (new_width < 0.5 || new_width > 4)
+ return alert(usr, "Only values between 0.5 and +2.5 are allowed.", null, null, null, null)
+
+ log_admin("[key_name(usr)] changed the distribution curve width to [new_width].")
+ message_admins("[key_name(usr)] changed the distribution curve width to [new_width]", 1)
+ GLOB.dynamic_curve_width = new_width
+ dynamic_mode_options(usr)
+
+ else if(href_list["f_dynamic_roundstart_latejoin_min"])
+ if(!check_rights(R_ADMIN))
+ return
+ if(SSticker && SSticker.mode)
+ return alert(usr, "The game has already started.", null, null, null, null)
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+ var/new_min = input(usr,"Change the minimum delay of latejoin injection in minutes.", "Change latejoin injection delay minimum", null) as num
+ if(new_min <= 0)
+ return alert(usr, "The minimum can't be zero or lower.", null, null, null, null)
+ if((new_min MINUTES) > GLOB.dynamic_latejoin_delay_max)
+ return alert(usr, "The minimum must be lower than the maximum.", null, null, null, null)
+
+ log_admin("[key_name(usr)] changed the latejoin injection minimum delay to [new_min] minutes.")
+ message_admins("[key_name(usr)] changed the latejoin injection minimum delay to [new_min] minutes", 1)
+ GLOB.dynamic_latejoin_delay_min = (new_min MINUTES)
+ dynamic_mode_options(usr)
+
+ else if(href_list["f_dynamic_roundstart_latejoin_max"])
+ if(!check_rights(R_ADMIN))
+ return
+ if(SSticker && SSticker.mode)
+ return alert(usr, "The game has already started.", null, null, null, null)
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+ var/new_max = input(usr,"Change the maximum delay of latejoin injection in minutes.", "Change latejoin injection delay maximum", null) as num
+ if(new_max <= 0)
+ return alert(usr, "The maximum can't be zero or lower.", null, null, null, null)
+ if((new_max MINUTES) < GLOB.dynamic_latejoin_delay_min)
+ return alert(usr, "The maximum must be higher than the minimum.", null, null, null, null)
+
+ log_admin("[key_name(usr)] changed the latejoin injection maximum delay to [new_max] minutes.")
+ message_admins("[key_name(usr)] changed the latejoin injection maximum delay to [new_max] minutes", 1)
+ GLOB.dynamic_latejoin_delay_max = (new_max MINUTES)
+ dynamic_mode_options(usr)
+
+ else if(href_list["f_dynamic_roundstart_midround_min"])
+ if(!check_rights(R_ADMIN))
+ return
+ if(SSticker && SSticker.mode)
+ return alert(usr, "The game has already started.", null, null, null, null)
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+ var/new_min = input(usr,"Change the minimum delay of midround injection in minutes.", "Change midround injection delay minimum", null) as num
+ if(new_min <= 0)
+ return alert(usr, "The minimum can't be zero or lower.", null, null, null, null)
+ if((new_min MINUTES) > GLOB.dynamic_midround_delay_max)
+ return alert(usr, "The minimum must be lower than the maximum.", null, null, null, null)
+
+ log_admin("[key_name(usr)] changed the midround injection minimum delay to [new_min] minutes.")
+ message_admins("[key_name(usr)] changed the midround injection minimum delay to [new_min] minutes", 1)
+ GLOB.dynamic_midround_delay_min = (new_min MINUTES)
+ dynamic_mode_options(usr)
+
+ else if(href_list["f_dynamic_roundstart_midround_max"])
+ if(!check_rights(R_ADMIN))
+ return
+ if(SSticker && SSticker.mode)
+ return alert(usr, "The game has already started.", null, null, null, null)
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+ var/new_max = input(usr,"Change the maximum delay of midround injection in minutes.", "Change midround injection delay maximum", null) as num
+ if(new_max <= 0)
+ return alert(usr, "The maximum can't be zero or lower.", null, null, null, null)
+ if((new_max MINUTES) > GLOB.dynamic_midround_delay_max)
+ return alert(usr, "The maximum must be higher than the minimum.", null, null, null, null)
+
+ log_admin("[key_name(usr)] changed the midround injection maximum delay to [new_max] minutes.")
+ message_admins("[key_name(usr)] changed the midround injection maximum delay to [new_max] minutes", 1)
+ GLOB.dynamic_midround_delay_max = (new_max MINUTES)
+ dynamic_mode_options(usr)
+
+ else if(href_list["f_dynamic_force_extended"])
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+
+ GLOB.dynamic_forced_extended = !GLOB.dynamic_forced_extended
+ log_admin("[key_name(usr)] set 'forced_extended' to [GLOB.dynamic_forced_extended].")
+ message_admins("[key_name(usr)] set 'forced_extended' to [GLOB.dynamic_forced_extended].")
+ dynamic_mode_options(usr)
+
+ else if(href_list["f_dynamic_no_stacking"])
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+
+ GLOB.dynamic_no_stacking = !GLOB.dynamic_no_stacking
+ log_admin("[key_name(usr)] set 'no_stacking' to [GLOB.dynamic_no_stacking].")
+ message_admins("[key_name(usr)] set 'no_stacking' to [GLOB.dynamic_no_stacking].")
+ dynamic_mode_options(usr)
+
+ else if(href_list["f_dynamic_classic_secret"])
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+
+ GLOB.dynamic_classic_secret = !GLOB.dynamic_classic_secret
+ log_admin("[key_name(usr)] set 'classic_secret' to [GLOB.dynamic_classic_secret].")
+ message_admins("[key_name(usr)] set 'classic_secret' to [GLOB.dynamic_classic_secret].")
+ dynamic_mode_options(usr)
+
+ else if(href_list["f_dynamic_stacking_limit"])
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+
+ GLOB.dynamic_stacking_limit = input(usr,"Change the threat limit at which round-endings rulesets will start to stack.", "Change stacking limit", null) as num
+ log_admin("[key_name(usr)] set 'stacking_limit' to [GLOB.dynamic_stacking_limit].")
+ message_admins("[key_name(usr)] set 'stacking_limit' to [GLOB.dynamic_stacking_limit].")
+ dynamic_mode_options(usr)
+
+ else if(href_list["f_dynamic_high_pop_limit"])
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(SSticker && SSticker.mode)
+ return alert(usr, "The game has already started.", null, null, null, null)
+
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+
+ var/new_value = input(usr, "Enter the high-pop override threshold for dynamic mode.", "High pop override") as num
+ if (new_value < 0)
+ return alert(usr, "Only positive values allowed!", null, null, null, null)
+ GLOB.dynamic_high_pop_limit = new_value
+
+ log_admin("[key_name(usr)] set 'high_pop_limit' to [GLOB.dynamic_high_pop_limit].")
+ message_admins("[key_name(usr)] set 'high_pop_limit' to [GLOB.dynamic_high_pop_limit].")
+ dynamic_mode_options(usr)
+
+ else if(href_list["f_dynamic_forced_threat"])
+ if(!check_rights(R_ADMIN))
+ return
+
+ if(SSticker && SSticker.mode)
+ return alert(usr, "The game has already started.", null, null, null, null)
+
+ if(GLOB.master_mode != "dynamic")
+ return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
+
+ var/new_value = input(usr, "Enter the forced threat level for dynamic mode.", "Forced threat level") as num
+ if (new_value > 100)
+ return alert(usr, "The value must be be under 100.", null, null, null, null)
+ GLOB.dynamic_forced_threat_level = new_value
+
+ log_admin("[key_name(usr)] set 'forced_threat_level' to [GLOB.dynamic_forced_threat_level].")
+ message_admins("[key_name(usr)] set 'forced_threat_level' to [GLOB.dynamic_forced_threat_level].")
+ dynamic_mode_options(usr)
else if(href_list["c_mode2"])
if(!check_rights(R_ADMIN|R_SERVER))
diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm
index 8e29b38fe1..0fca957ffe 100644
--- a/code/modules/antagonists/abductor/abductor.dm
+++ b/code/modules/antagonists/abductor/abductor.dm
@@ -56,6 +56,7 @@
/datum/antagonist/abductor/greet()
to_chat(owner.current, "You are the [owner.special_role]!")
to_chat(owner.current, "With the help of your teammate, kidnap and experiment on station crew members!")
+ to_chat(owner.current, "Try not to disturb the habitat, it could lead to dead specimens.")
to_chat(owner.current, "[greet_text]")
owner.announce_objectives()
diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm
index 99d8ae797b..c428c56d45 100644
--- a/code/modules/antagonists/changeling/powers/mutations.dm
+++ b/code/modules/antagonists/changeling/powers/mutations.dm
@@ -161,11 +161,13 @@
throwforce = 0 //Just to be on the safe side
throw_range = 0
throw_speed = 0
+ armour_penetration = 20
hitsound = 'sound/weapons/bladeslice.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
sharpness = IS_SHARP
var/can_drop = FALSE
var/fake = FALSE
+ total_mass = TOTAL_MASS_HAND_REPLACEMENT
/obj/item/melee/arm_blade/Initialize(mapload,silent,synthetic)
. = ..()
diff --git a/code/modules/antagonists/changeling/powers/strained_muscles.dm b/code/modules/antagonists/changeling/powers/strained_muscles.dm
index baeed8b0b2..bdbd38b92d 100644
--- a/code/modules/antagonists/changeling/powers/strained_muscles.dm
+++ b/code/modules/antagonists/changeling/powers/strained_muscles.dm
@@ -5,7 +5,7 @@
name = "Strained Muscles"
desc = "We evolve the ability to reduce the acid buildup in our muscles, allowing us to move much faster."
helptext = "The strain will make us tired, and we will rapidly become fatigued. Standard weight restrictions, like hardsuits, still apply. Cannot be used in lesser form."
- chemical_cost = 0
+ chemical_cost = 15
dna_cost = 1
req_human = 1
var/stacks = 0 //Increments every 5 seconds; damage increases over time
@@ -15,13 +15,16 @@
action_background_icon_state = "bg_ling"
/obj/effect/proc_holder/changeling/strained_muscles/sting_action(mob/living/carbon/user)
+ var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
active = !active
if(active)
to_chat(user, "Our muscles tense and strengthen.")
+ changeling.chem_recharge_slowdown += 0.5
else
REMOVE_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
to_chat(user, "Our muscles relax.")
- if(stacks >= 10)
+ changeling.chem_recharge_slowdown -= 0.5
+ if(stacks >= 20)
to_chat(user, "We collapse in exhaustion.")
user.Knockdown(60)
user.emote("gasp")
@@ -42,9 +45,9 @@
stacks++
//user.take_bodypart_damage(stacks * 0.03, 0)
- user.staminaloss += stacks * 1.3 //At first the changeling may regenerate stamina fast enough to nullify fatigue, but it will stack
+ user.adjustStaminaLoss(stacks*1.3) //At first the changeling may regenerate stamina fast enough to nullify fatigue, but it will stack
- if(stacks == 11) //Warning message that the stacks are getting too high
+ if(stacks == 10) //Warning message that the stacks are getting too high
to_chat(user, "Our legs are really starting to hurt...")
sleep(40)
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
index 510c279f3c..6d6b1fa9d0 100644
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
+++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_drivers.dm
@@ -224,7 +224,7 @@
. = ..()
/datum/clockwork_scripture/abscond/scripture_effects()
- var/mob/living/pulled_mob = invoker.pulling && isliving(invoker.pulling) && get_clockwork_power(ABSCOND_ABDUCTION_COST)
+ var/mob/living/pulled_mob = (invoker.pulling && isliving(invoker.pulling) && get_clockwork_power(ABSCOND_ABDUCTION_COST)) ? invoker.pulling : null
var/turf/T
if(GLOB.ark_of_the_clockwork_justiciar)
T = get_step(GLOB.ark_of_the_clockwork_justiciar, SOUTH)
diff --git a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
index 4cf7c1ba60..f735d6bb29 100644
--- a/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/ark_of_the_clockwork_justicar.dm
@@ -131,12 +131,10 @@
if(!M || !M.current)
continue
if(isliving(M.current) && M.current.stat != DEAD)
- var/turf/t_turf
- if(isAI(M.current))
- t_turf = isAI(M.current) ? get_step(get_step(src, NORTH),NORTH) : get_turf(src) // AI too fat, must make sure it always ends up a 2 tiles north instead of on the ark.
- do_teleport(M, t_turf, channel = TELEPORT_CHANNEL_CULT, forced = TRUE)
- M.current.overlay_fullscreen("flash", /obj/screen/fullscreen/flash)
- M.current.clear_fullscreen("flash", 5)
+ var/turf/t_turf = isAI(M.current) ? get_step(get_step(src, NORTH),NORTH) : get_turf(src) // AI too fat, must make sure it always ends up a 2 tiles north instead of on the ark.
+ do_teleport(M.current, t_turf, channel = TELEPORT_CHANNEL_CULT, forced = TRUE)
+ M.current.overlay_fullscreen("flash", /obj/screen/fullscreen/flash)
+ M.current.clear_fullscreen("flash", 5)
playsound(src, 'sound/magic/clockwork/invoke_general.ogg', 50, FALSE)
recalls_remaining--
recalling = FALSE
diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm
index f58ffc56d2..1dbae4ca98 100644
--- a/code/modules/antagonists/cult/blood_magic.dm
+++ b/code/modules/antagonists/cult/blood_magic.dm
@@ -655,15 +655,15 @@
if(H.stat == DEAD)
to_chat(user,"Only a revive rune can bring back the dead!")
return
- if(H.blood_volume < BLOOD_VOLUME_SAFE)
- var/restore_blood = BLOOD_VOLUME_SAFE - H.blood_volume
+ if(H.blood_volume < (BLOOD_VOLUME_SAFE*H.blood_ratio))
+ var/restore_blood = (BLOOD_VOLUME_SAFE*H.blood_ratio) - H.blood_volume
if(uses*2 < restore_blood)
H.blood_volume += uses*2
to_chat(user,"You use the last of your blood rites to restore what blood you could!")
uses = 0
return ..()
else
- H.blood_volume = BLOOD_VOLUME_SAFE
+ H.blood_volume = (BLOOD_VOLUME_SAFE*H.blood_ratio)
uses -= round(restore_blood/2)
to_chat(user,"Your blood rites have restored [H == user ? "your" : "[H.p_their()]"] blood to safe levels!")
var/overall_damage = H.getBruteLoss() + H.getFireLoss() + H.getToxLoss() + H.getOxyLoss()
@@ -698,7 +698,7 @@
if(H.cultslurring)
to_chat(user,"[H.p_their(TRUE)] blood has been tainted by an even stronger form of blood magic, it's no use to us like this!")
return
- if(H.blood_volume > BLOOD_VOLUME_SAFE)
+ if(H.blood_volume > (BLOOD_VOLUME_SAFE*H.blood_ratio))
H.blood_volume -= 100
uses += 50
user.Beam(H,icon_state="drainbeam",time=10)
@@ -799,4 +799,4 @@
to_chat(user, "Your hands glow with POWER OVERWHELMING!!!")
else
to_chat(user, "You need a free hand for this rite!")
- qdel(rite)
\ No newline at end of file
+ qdel(rite)
diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index dc2c29eb6d..25e3663c0b 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -105,7 +105,6 @@
inhand_x_dimension = 64
inhand_y_dimension = 64
actions_types = list()
- item_flags = SLOWS_WHILE_IN_HAND
var/datum/action/innate/dash/cult/jaunt
var/datum/action/innate/cult/spin2win/linked_action
var/spinning = FALSE
diff --git a/code/modules/antagonists/cult/cult_structures.dm b/code/modules/antagonists/cult/cult_structures.dm
index 64d57c2f94..499d7a861e 100644
--- a/code/modules/antagonists/cult/cult_structures.dm
+++ b/code/modules/antagonists/cult/cult_structures.dm
@@ -188,7 +188,7 @@
var/mob/living/simple_animal/M = L
if(M.health < M.maxHealth)
M.adjustHealth(-3)
- if(ishuman(L) && L.blood_volume < BLOOD_VOLUME_NORMAL)
+ if(ishuman(L) && L.blood_volume < (BLOOD_VOLUME_NORMAL * L.blood_ratio))
L.blood_volume += 1.0
CHECK_TICK
if(last_corrupt <= world.time)
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index bbab86729b..29b4e4539c 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -61,8 +61,8 @@ Runes can either be invoked by one's self or with many different cultists. Each
if(do_after(user, 15, target = src))
to_chat(user, "You carefully erase the [lowertext(cultist_name)] rune.")
qdel(src)
- else if(istype(I, /obj/item/nullrod))
- user.say("BEGONE FOUL MAGIKS!!", forced = "nullrod")
+ else if(istype(I, /obj/item/storage/book/bible) || istype(I, /obj/item/nullrod))
+ user.say("BEGONE FOUL MAGICKS!!", forced = "bible")
to_chat(user, "You disrupt the magic of [src] with [I].")
qdel(src)
@@ -286,14 +286,14 @@ structure_check() searches for nearby cultist structures required for the invoca
/obj/effect/rune/convert/proc/optinalert(mob/living/convertee)
var/alert = alert(convertee, "Will you embrace the Geometer of Blood or perish in futile resistance?", "Choose your own fate", "Join the Blood Cult", "Suffer a horrible demise")
- if(alert == "Join the Blood Cult")
+ if(src && alert == "Join the Blood Cult")
signmeup(convertee)
/obj/effect/rune/convert/proc/signmeup(mob/living/convertee)
- if(currentconversionman == usr)
+ if(currentconversionman == convertee)
conversionresult = TRUE
else
- to_chat(usr, "Your fate has already been set in stone.")
+ to_chat(convertee, "Your fate has already been set in stone.")
/obj/effect/rune/convert/proc/do_sacrifice(mob/living/sacrificial, list/invokers, force_a_sac)
var/mob/living/first_invoker = invokers[1]
@@ -433,12 +433,12 @@ structure_check() searches for nearby cultist structures required for the invoca
continue
if(!A.anchored)
movedsomething = TRUE
- if(do_teleport(A, T, forceMove = TRUE, channel = TELEPORT_CHANNEL_CULT))
+ if(do_teleport(A, target, forceMove = TRUE, channel = TELEPORT_CHANNEL_CULT))
movesuccess = TRUE
if(movedsomething)
..()
if(moveuserlater)
- if(do_teleport(user, T, channel = TELEPORT_CHANNEL_CULT))
+ if(do_teleport(user, target, channel = TELEPORT_CHANNEL_CULT))
movesuccess = TRUE
if(movesuccess)
visible_message("There is a sharp crack of inrushing air, and everything above the rune disappears!", null, "You hear a sharp crack.")
diff --git a/code/modules/antagonists/disease/disease_disease.dm b/code/modules/antagonists/disease/disease_disease.dm
index 21d0381982..b4b8ac0956 100644
--- a/code/modules/antagonists/disease/disease_disease.dm
+++ b/code/modules/antagonists/disease/disease_disease.dm
@@ -51,7 +51,7 @@
if(cures.len)
return
var/list/not_used = advance_cures.Copy()
- cures = list(pick_n_take(not_used), pick_n_take(not_used))
+ cures = list(pick(pick_n_take(not_used)), pick(pick_n_take(not_used)))
// Get the cure name from the cure_id
var/datum/reagent/D1 = GLOB.chemical_reagents_list[cures[1]]
diff --git a/code/modules/antagonists/ert/ert.dm b/code/modules/antagonists/ert/ert.dm
index 53f8aa2da1..bb24af4f7a 100644
--- a/code/modules/antagonists/ert/ert.dm
+++ b/code/modules/antagonists/ert/ert.dm
@@ -36,30 +36,42 @@
/datum/antagonist/ert/security // kinda handled by the base template but here for completion
-/datum/antagonist/ert/security/red
+/datum/antagonist/ert/security/amber
outfit = /datum/outfit/ert/security/alert
+/datum/antagonist/ert/security/red
+ outfit = /datum/outfit/ert/security/alert/red
+
/datum/antagonist/ert/engineer
role = "Engineer"
outfit = /datum/outfit/ert/engineer
-/datum/antagonist/ert/engineer/red
+/datum/antagonist/ert/engineer/amber
outfit = /datum/outfit/ert/engineer/alert
+/datum/antagonist/ert/engineer/red
+ outfit = /datum/outfit/ert/engineer/alert/red
+
/datum/antagonist/ert/medic
role = "Medical Officer"
outfit = /datum/outfit/ert/medic
-/datum/antagonist/ert/medic/red
+/datum/antagonist/ert/medic/amber
outfit = /datum/outfit/ert/medic/alert
+/datum/antagonist/ert/medic/red
+ outfit = /datum/outfit/ert/medic/alert/red
+
/datum/antagonist/ert/commander
role = "Commander"
outfit = /datum/outfit/ert/commander
-/datum/antagonist/ert/commander/red
+/datum/antagonist/ert/commander/amber
outfit = /datum/outfit/ert/commander/alert
+/datum/antagonist/ert/commander/red
+ outfit = /datum/outfit/ert/commander/alert/red
+
/datum/antagonist/ert/deathsquad
name = "Deathsquad Trooper"
outfit = /datum/outfit/death_commando
diff --git a/code/modules/antagonists/greybois/greybois.dm b/code/modules/antagonists/greybois/greybois.dm
new file mode 100644
index 0000000000..b5e18045e8
--- /dev/null
+++ b/code/modules/antagonists/greybois/greybois.dm
@@ -0,0 +1,23 @@
+/datum/antagonist/greybois
+ name = "Emergency Assistant"
+ show_name_in_check_antagonists = TRUE
+ show_in_antagpanel = FALSE
+ var/mission = "Assist the station."
+ var/datum/outfit/outfit = /datum/outfit/ert/greybois
+
+/datum/antagonist/greybois/greygod
+ outfit = /datum/outfit/ert/greybois/greygod
+
+/datum/antagonist/greybois/greet()
+ to_chat(owner, "You are an Emergency Assistant.")
+ to_chat(owner, "Central Command is sending you to [station_name()] with the task: [mission]")
+
+/datum/antagonist/greybois/on_gain()
+ equipERT()
+ . = ..()
+
+/datum/antagonist/greybois/proc/equipERT()
+ var/mob/living/carbon/human/H = owner.current
+ if(!istype(H))
+ return
+ H.equipOutfit(outfit)
diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm
index b274283621..edae8a4240 100644
--- a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm
+++ b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm
@@ -5,6 +5,7 @@
#define CHALLENGE_SHUTTLE_DELAY 15000 // 25 minutes, so the ops have at least 5 minutes before the shuttle is callable.
GLOBAL_LIST_EMPTY(jam_on_wardec)
+GLOBAL_VAR_INIT(war_declared, FALSE)
/obj/item/nuclear_challenge
name = "Declaration of War (Challenge Mode)"
@@ -61,11 +62,13 @@ GLOBAL_LIST_EMPTY(jam_on_wardec)
for(var/obj/machinery/computer/camera_advanced/shuttle_docker/D in GLOB.jam_on_wardec)
D.jammed = TRUE
-
+
+ GLOB.war_declared = TRUE
var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop)
var/actual_players = GLOB.joined_player_list.len - nukeops.len
new uplink_type(get_turf(user), user.key, CHALLENGE_TELECRYSTALS + CEILING(PLAYER_SCALING * actual_players, 1))
+
CONFIG_SET(number/shuttle_refuel_delay, max(CONFIG_GET(number/shuttle_refuel_delay), CHALLENGE_SHUTTLE_DELAY))
SSblackbox.record_feedback("amount", "nuclear_challenge_mode", 1)
diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
index ade5458765..add3c1d9b0 100644
--- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
+++ b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm
@@ -373,6 +373,11 @@
S.switch_mode_to(TRACK_INFILTRATOR)
countdown.start()
set_security_level("delta")
+
+ if(GLOB.war_declared)
+ var/area/A = get_area(src)
+ priority_announce("Alert: Unexpected increase in radiation levels near [A.name] ([src.x],[src.y],[src.z]). Please send an authorized radiation specialist to investigate.", "Sensory Nuclear Indexer Telemetry Calculation Helper")
+
else
detonation_timer = null
set_security_level(previous_level)
diff --git a/code/modules/antagonists/traitor/IAA/internal_affairs.dm b/code/modules/antagonists/traitor/IAA/internal_affairs.dm
index 051bf74705..f2e6566e8f 100644
--- a/code/modules/antagonists/traitor/IAA/internal_affairs.dm
+++ b/code/modules/antagonists/traitor/IAA/internal_affairs.dm
@@ -244,10 +244,12 @@
to_chat(owner.current, "Your target has been framed for [crime], and you have been tasked with eliminating them to prevent them defending themselves in court.")
to_chat(owner.current, "Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.")
to_chat(owner.current, " You have been provided with a standard uplink to accomplish your task. ")
+ to_chat(owner.current, "By no means reveal that you, or any other NT employees, are undercover agents.")
else
to_chat(owner.current, "Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial.")
to_chat(owner.current, "While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.")
to_chat(owner.current, "For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink.")
+ to_chat(owner.current, "By no means reveal that you, or any other NT employees, are undercover agents.")
to_chat(owner.current, "Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.")
owner.announce_objectives()
diff --git a/code/modules/antagonists/valentines/valentine.dm b/code/modules/antagonists/valentines/valentine.dm
index 31e69b32c2..21e54374a4 100644
--- a/code/modules/antagonists/valentines/valentine.dm
+++ b/code/modules/antagonists/valentines/valentine.dm
@@ -27,6 +27,7 @@
var/mob/living/L = owner
L.remove_status_effect(STATUS_EFFECT_INLOVE)
+
/datum/antagonist/valentine/greet()
to_chat(owner, "You're on a date with [date.name]! Protect [date.p_them()] at all costs. This takes priority over all other loyalties.")
@@ -42,4 +43,21 @@
if(objectives_complete)
return "[owner.name] protected [owner.p_their()] date"
else
- return "[owner.name] date failed!"
\ No newline at end of file
+ return "[owner.name] date failed!"
+
+//Just so it's distinct, basically.
+/datum/antagonist/valentine/chem/greet()
+ to_chat(owner, "You're in love with [date.name]! Protect [date.p_them()] at all costs. This takes priority over all other loyalties.")
+
+/datum/antagonist/valentine/chem/roundend_report()
+ var/objectives_complete = TRUE
+ if(owner.objectives.len)
+ for(var/datum/objective/objective in owner.objectives)
+ if(!objective.check_completion())
+ objectives_complete = FALSE
+ break
+
+ if(objectives_complete)
+ return "[owner.name] protected [owner.p_their()] love: [date.name]! What a cutie!"
+ else
+ return "[owner.name] date failed!"
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index 08e00ea0f4..8642484895 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -405,8 +405,12 @@
var/breakout = 0
while(breakout < 50)
if(!T)
- break
+ end_effect(user)
+ return
var/turf/potential_T = find_safe_turf()
+ if(!potential_T)
+ end_effect(user)
+ return
if(T.z != potential_T.z || abs(get_dist_euclidian(potential_T,T)) > 50 - breakout)
do_teleport(user, potential_T, channel = TELEPORT_CHANNEL_MAGIC)
user.canmove = 0
diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm
index b1aa63c242..186eb1b024 100644
--- a/code/modules/assembly/flash.dm
+++ b/code/modules/assembly/flash.dm
@@ -12,6 +12,7 @@
crit_fail = FALSE //Is the flash burnt out?
light_color = LIGHT_COLOR_WHITE
light_power = FLASH_LIGHT_POWER
+ var/flashing_overlay = "flash-f"
var/times_used = 0 //Number of times it's been used.
var/burnout_resistance = 0
var/last_used = 0 //last world.time it was used.
@@ -36,8 +37,8 @@
add_overlay("flashburnt")
attached_overlays += "flashburnt"
if(flash)
- add_overlay("flash-f")
- attached_overlays += "flash-f"
+ add_overlay(flashing_overlay)
+ attached_overlays += flashing_overlay
addtimer(CALLBACK(src, .proc/update_icon), 5)
if(holder)
holder.update_icon()
@@ -313,3 +314,50 @@
/obj/item/assembly/flash/shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
activate()
return ..()
+
+//ported from tg - check to make sure it can't appear where it's not supposed to.
+/obj/item/assembly/flash/hypnotic
+ desc = "A modified flash device, programmed to emit a sequence of subliminal flashes that can send a vulnerable target into a hypnotic trance."
+ flashing_overlay = "flash-hypno" //I cannot find this icon no matter how hard I look in tg, so I might just make my own.
+ light_color = LIGHT_COLOR_PINK
+ cooldown = 20
+
+/obj/item/assembly/flash/hypnotic/burn_out()
+ return
+
+/obj/item/assembly/flash/hypnotic/flash_carbon(mob/living/carbon/M, mob/user, power = 15, targeted = TRUE, generic_message = FALSE)
+ if(!istype(M))
+ return
+ if(user)
+ log_combat(user, M, "[targeted? "hypno-flashed(targeted)" : "hypno-flashed(AOE)"]", src)
+ else //caused by emp/remote signal
+ M.log_message("was [targeted? "hypno-flashed(targeted)" : "hypno-flashed(AOE)"]",LOG_ATTACK)
+ if(generic_message && M != user)
+ to_chat(M, "[src] emits a soothing light...")
+ if(targeted)
+ if(M.flash_act(1, 1))
+ var/hypnosis = FALSE
+ if(M.hypnosis_vulnerable())
+ hypnosis = TRUE
+ if(user)
+ user.visible_message("[user] blinds [M] with the flash!", "You hypno-flash [M]!")
+
+ if(!hypnosis)
+ to_chat(M, "The light makes you feel oddly relaxed...")
+ M.confused += min(M.confused + 10, 20)
+ M.dizziness += min(M.dizziness + 10, 20)
+ M.drowsyness += min(M.drowsyness + 10, 20)
+ M.apply_status_effect(STATUS_EFFECT_PACIFY, 100)
+ else
+ M.apply_status_effect(/datum/status_effect/trance, 200, TRUE)
+
+ else if(user)
+ user.visible_message("[user] fails to blind [M] with the flash!", "You fail to hypno-flash [M]!")
+ else
+ to_chat(M, "[src] fails to blind you!")
+
+ else if(M.flash_act())
+ to_chat(M, "Such a pretty light...")
+ M.confused += min(M.confused + 4, 20)
+ M.dizziness += min(M.dizziness + 4, 20)
+ M.drowsyness += min(M.drowsyness + 4, 20)
diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm
index 5ad97fb7c8..8e320b2f3e 100644
--- a/code/modules/atmospherics/gasmixtures/reactions.dm
+++ b/code/modules/atmospherics/gasmixtures/reactions.dm
@@ -364,15 +364,10 @@
var/list/cached_gases = air.gases
var/temperature = air.temperature
var/pressure = air.return_pressure()
-
var/old_heat_capacity = air.heat_capacity()
var/reaction_efficency = min(1/((pressure/(0.1*ONE_ATMOSPHERE))*(max(cached_gases[/datum/gas/plasma]/cached_gases[/datum/gas/nitrous_oxide],1))),cached_gases[/datum/gas/nitrous_oxide],cached_gases[/datum/gas/plasma]/2)
var/energy_released = 2*reaction_efficency*FIRE_CARBON_ENERGY_RELEASED
- if(cached_gases[/datum/gas/miasma] && cached_gases[/datum/gas/miasma] > 0)
- energy_released /= cached_gases[/datum/gas/miasma]*0.1
- if(cached_gases[/datum/gas/bz] && cached_gases[/datum/gas/bz] > 0)
- energy_released *= cached_gases[/datum/gas/bz]*0.1
- if ((cached_gases[/datum/gas/nitrous_oxide] - reaction_efficency < 0 )|| (cached_gases[/datum/gas/plasma] - (2*reaction_efficency) < 0)) //Shouldn't produce gas from nothing.
+ if ((cached_gases[/datum/gas/nitrous_oxide] - reaction_efficency < 0 )|| (cached_gases[/datum/gas/plasma] - (2*reaction_efficency) < 0) || energy_released <= 0) //Shouldn't produce gas from nothing.
return NO_REACTION
cached_gases[/datum/gas/bz] += reaction_efficency
if(reaction_efficency == cached_gases[/datum/gas/nitrous_oxide])
@@ -381,7 +376,7 @@
cached_gases[/datum/gas/nitrous_oxide] -= reaction_efficency
cached_gases[/datum/gas/plasma] -= 2*reaction_efficency
- SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, (reaction_efficency**0.5)*BZ_RESEARCH_AMOUNT)
+ SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, min((reaction_efficency**2)*BZ_RESEARCH_SCALE),BZ_RESEARCH_MAX_AMOUNT)
if(energy_released > 0)
var/new_heat_capacity = air.heat_capacity()
@@ -477,4 +472,4 @@
//Possibly burning a bit of organic matter through maillard reaction, so a *tiny* bit more heat would be understandable
air.temperature += cleaned_air * 0.002
- SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, cleaned_air*MIASMA_RESEARCH_AMOUNT)//Turns out the burning of miasma is kinda interesting to scientists
\ No newline at end of file
+ SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, cleaned_air*MIASMA_RESEARCH_AMOUNT)//Turns out the burning of miasma is kinda interesting to scientists
diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm
index 3bf54a1178..6ca25c0d80 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -1,880 +1,882 @@
-/datum/tlv
- var/min2
- var/min1
- var/max1
- var/max2
-
-/datum/tlv/New(min2 as num, min1 as num, max1 as num, max2 as num)
- if(min2) src.min2 = min2
- if(min1) src.min1 = min1
- if(max1) src.max1 = max1
- if(max2) src.max2 = max2
-
-/datum/tlv/proc/get_danger_level(val as num)
- if(max2 != -1 && val >= max2)
- return 2
- if(min2 != -1 && val <= min2)
- return 2
- if(max1 != -1 && val >= max1)
- return 1
- if(min1 != -1 && val <= min1)
- return 1
- return 0
-
-/datum/tlv/no_checks
- min2 = -1
- min1 = -1
- max1 = -1
- max2 = -1
-
-/datum/tlv/dangerous
- min2 = -1
- min1 = -1
- max1 = 0.2
- max2 = 0.5
-
-/obj/item/electronics/airalarm
- name = "air alarm electronics"
- icon_state = "airalarm_electronics"
-
-/obj/item/wallframe/airalarm
- name = "air alarm frame"
- desc = "Used for building Air Alarms."
- icon = 'icons/obj/monitors.dmi'
- icon_state = "alarm_bitem"
- result_path = /obj/machinery/airalarm
-
-#define AALARM_MODE_SCRUBBING 1
-#define AALARM_MODE_VENTING 2 //makes draught
-#define AALARM_MODE_PANIC 3 //like siphon, but stronger (enables widenet)
-#define AALARM_MODE_REPLACEMENT 4 //sucks off all air, then refill and swithes to scrubbing
-#define AALARM_MODE_OFF 5
-#define AALARM_MODE_FLOOD 6 //Emagged mode; turns off scrubbers and pressure checks on vents
-#define AALARM_MODE_SIPHON 7 //Scrubbers suck air
-#define AALARM_MODE_CONTAMINATED 8 //Turns on all filtering and widenet scrubbing.
-#define AALARM_MODE_REFILL 9 //just like normal, but with triple the air output
-
-#define AALARM_REPORT_TIMEOUT 100
-
-#define AALARM_OVERLAY_OFF "alarm_off"
-#define AALARM_OVERLAY_GREEN "alarm_green"
-#define AALARM_OVERLAY_WARN "alarm_amber"
-#define AALARM_OVERLAY_DANGER "alarm_red"
-
-/obj/machinery/airalarm
- name = "air alarm"
- desc = "A machine that monitors atmosphere levels. Goes off if the area is dangerous."
- icon = 'icons/obj/monitors.dmi'
- icon_state = "alarm0"
- use_power = IDLE_POWER_USE
- idle_power_usage = 4
- active_power_usage = 8
- power_channel = ENVIRON
- req_access = list(ACCESS_ATMOSPHERICS)
- max_integrity = 250
- integrity_failure = 80
- armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30)
- resistance_flags = FIRE_PROOF
-
- var/danger_level = 0
- var/mode = AALARM_MODE_SCRUBBING
-
- var/locked = TRUE
- var/aidisabled = 0
- var/shorted = 0
- var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone
- var/brightness_on = 1
-
- var/frequency = FREQ_ATMOS_CONTROL
- var/alarm_frequency = FREQ_ATMOS_ALARMS
- var/datum/radio_frequency/radio_connection
-
- var/list/TLV = list( // Breathable air.
- "pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa
- "temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66),
- /datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
- /datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000),
- /datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10),
- /datum/gas/miasma = new/datum/tlv/(-1, -1, 2, 5),
- /datum/gas/plasma = new/datum/tlv/dangerous,
- /datum/gas/nitrous_oxide = new/datum/tlv/dangerous,
- /datum/gas/bz = new/datum/tlv/dangerous,
- /datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic
- /datum/gas/water_vapor = new/datum/tlv/dangerous,
- /datum/gas/tritium = new/datum/tlv/dangerous,
- /datum/gas/stimulum = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects
- /datum/gas/nitryl = new/datum/tlv/dangerous,
- /datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000) // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
- )
-
-/obj/machinery/airalarm/server // No checks here.
- TLV = list(
- "pressure" = new/datum/tlv/no_checks,
- "temperature" = new/datum/tlv/no_checks,
- /datum/gas/oxygen = new/datum/tlv/no_checks,
- /datum/gas/nitrogen = new/datum/tlv/no_checks,
- /datum/gas/carbon_dioxide = new/datum/tlv/no_checks,
- /datum/gas/miasma = new/datum/tlv/no_checks,
- /datum/gas/plasma = new/datum/tlv/no_checks,
- /datum/gas/nitrous_oxide = new/datum/tlv/no_checks,
- /datum/gas/bz = new/datum/tlv/no_checks,
- /datum/gas/hypernoblium = new/datum/tlv/no_checks,
- /datum/gas/water_vapor = new/datum/tlv/no_checks,
- /datum/gas/tritium = new/datum/tlv/no_checks,
- /datum/gas/stimulum = new/datum/tlv/no_checks,
- /datum/gas/nitryl = new/datum/tlv/no_checks,
- /datum/gas/pluoxium = new/datum/tlv/no_checks
- )
-
-/obj/machinery/airalarm/kitchen_cold_room // Copypasta: to check temperatures.
- TLV = list(
- "pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa
- "temperature" = new/datum/tlv(T0C-73.15, T0C-63.15, T0C, T0C+10),
- /datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
- /datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000),
- /datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10),
- /datum/gas/miasma = new/datum/tlv/(-1, -1, 2, 5),
- /datum/gas/plasma = new/datum/tlv/dangerous,
- /datum/gas/nitrous_oxide = new/datum/tlv/dangerous,
- /datum/gas/bz = new/datum/tlv/dangerous,
- /datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic
- /datum/gas/water_vapor = new/datum/tlv/dangerous,
- /datum/gas/tritium = new/datum/tlv/dangerous,
- /datum/gas/stimulum = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects
- /datum/gas/nitryl = new/datum/tlv/dangerous,
- /datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000) // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
- )
-
-/obj/machinery/airalarm/unlocked
- locked = FALSE
-
-/obj/machinery/airalarm/engine
- name = "engine air alarm"
- locked = FALSE
- req_access = null
- req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_ENGINE)
-
-/obj/machinery/airalarm/mixingchamber
- name = "chamber air alarm"
- locked = FALSE
- req_access = null
- req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_TOX, ACCESS_TOX_STORAGE)
-
-/obj/machinery/airalarm/all_access
- name = "all-access air alarm"
- desc = "This particular atmos control unit appears to have no access restrictions."
- locked = FALSE
- req_access = null
- req_one_access = null
-
-/obj/machinery/airalarm/syndicate //general syndicate access
- req_access = list(ACCESS_SYNDICATE)
-
-/obj/machinery/airalarm/directional/north //Pixel offsets get overwritten on New()
- dir = SOUTH
- pixel_y = 24
-
-/obj/machinery/airalarm/directional/south
- dir = NORTH
- pixel_y = -24
-
-/obj/machinery/airalarm/directional/east
- dir = WEST
- pixel_x = 24
-
-/obj/machinery/airalarm/directional/west
- dir = EAST
- pixel_x = -24
-
-//all air alarms in area are connected via magic
-/area
- var/list/air_vent_names = list()
- var/list/air_scrub_names = list()
- var/list/air_vent_info = list()
- var/list/air_scrub_info = list()
-
-/obj/machinery/airalarm/Initialize(mapload, ndir, nbuild)
- . = ..()
- wires = new /datum/wires/airalarm(src)
-
- if(ndir)
- setDir(ndir)
-
- if(nbuild)
- buildstage = 0
- panel_open = TRUE
- pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
- pixel_y = (dir & 3)? (dir == 1 ? -24 : 24) : 0
-
- if(name == initial(name))
- name = "[get_area_name(src)] Air Alarm"
-
- power_change()
- set_frequency(frequency)
-
-/obj/machinery/airalarm/Destroy()
- SSradio.remove_object(src, frequency)
- qdel(wires)
- wires = null
- return ..()
-
-/obj/machinery/airalarm/examine(mob/user)
- . = ..()
- switch(buildstage)
- if(0)
- to_chat(user, "It is missing air alarm electronics.")
- if(1)
- to_chat(user, "It is missing wiring.")
- if(2)
- to_chat(user, "Alt-click to [locked ? "unlock" : "lock"] the interface.")
-
-/obj/machinery/airalarm/ui_status(mob/user)
- if(user.has_unlimited_silicon_privilege && aidisabled)
- to_chat(user, "AI control has been disabled.")
- else if(!shorted)
- return ..()
- return UI_CLOSE
-
-/obj/machinery/airalarm/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
- datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
- ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
- if(!ui)
- ui = new(user, src, ui_key, "airalarm", name, 440, 650, master_ui, state)
- ui.open()
-
-/obj/machinery/airalarm/ui_data(mob/user)
- var/data = list(
- "locked" = locked,
- "siliconUser" = user.has_unlimited_silicon_privilege,
- "emagged" = (obj_flags & EMAGGED ? 1 : 0),
- "danger_level" = danger_level,
- )
-
- var/area/A = get_area(src)
- data["atmos_alarm"] = A.atmosalm
- data["fire_alarm"] = A.fire
-
- var/turf/T = get_turf(src)
- var/datum/gas_mixture/environment = T.return_air()
- var/datum/tlv/cur_tlv
-
- data["environment_data"] = list()
- var/pressure = environment.return_pressure()
- cur_tlv = TLV["pressure"]
- data["environment_data"] += list(list(
- "name" = "Pressure",
- "value" = pressure,
- "unit" = "kPa",
- "danger_level" = cur_tlv.get_danger_level(pressure)
- ))
- var/temperature = environment.temperature
- cur_tlv = TLV["temperature"]
- data["environment_data"] += list(list(
- "name" = "Temperature",
- "value" = temperature,
- "unit" = "K ([round(temperature - T0C, 0.1)]C)",
- "danger_level" = cur_tlv.get_danger_level(temperature)
- ))
- var/total_moles = environment.total_moles()
- var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume
- for(var/gas_id in environment.gases)
- if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
- continue
- cur_tlv = TLV[gas_id]
- data["environment_data"] += list(list(
- "name" = GLOB.meta_gas_names[gas_id],
- "value" = environment.gases[gas_id] / total_moles * 100,
- "unit" = "%",
- "danger_level" = cur_tlv.get_danger_level(environment.gases[gas_id] * partial_pressure)
- ))
-
- if(!locked || user.has_unlimited_silicon_privilege)
- data["vents"] = list()
- for(var/id_tag in A.air_vent_names)
- var/long_name = A.air_vent_names[id_tag]
- var/list/info = A.air_vent_info[id_tag]
- if(!info || info["frequency"] != frequency)
- continue
- data["vents"] += list(list(
- "id_tag" = id_tag,
- "long_name" = sanitize(long_name),
- "power" = info["power"],
- "checks" = info["checks"],
- "excheck" = info["checks"]&1,
- "incheck" = info["checks"]&2,
- "direction" = info["direction"],
- "external" = info["external"],
- "internal" = info["internal"],
- "extdefault"= (info["external"] == ONE_ATMOSPHERE),
- "intdefault"= (info["internal"] == 0)
- ))
- data["scrubbers"] = list()
- for(var/id_tag in A.air_scrub_names)
- var/long_name = A.air_scrub_names[id_tag]
- var/list/info = A.air_scrub_info[id_tag]
- if(!info || info["frequency"] != frequency)
- continue
- data["scrubbers"] += list(list(
- "id_tag" = id_tag,
- "long_name" = sanitize(long_name),
- "power" = info["power"],
- "scrubbing" = info["scrubbing"],
- "widenet" = info["widenet"],
- "filter_types" = info["filter_types"]
- ))
- data["mode"] = mode
- data["modes"] = list()
- data["modes"] += list(list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0))
- data["modes"] += list(list("name" = "Contaminated - Scrubs out ALL contaminants quickly","mode" = AALARM_MODE_CONTAMINATED, "selected" = mode == AALARM_MODE_CONTAMINATED, "danger" = 0))
- data["modes"] += list(list("name" = "Draught - Siphons out air while replacing", "mode" = AALARM_MODE_VENTING, "selected" = mode == AALARM_MODE_VENTING, "danger" = 0))
- data["modes"] += list(list("name" = "Refill - Triple vent output", "mode" = AALARM_MODE_REFILL, "selected" = mode == AALARM_MODE_REFILL, "danger" = 1))
- data["modes"] += list(list("name" = "Cycle - Siphons air before replacing", "mode" = AALARM_MODE_REPLACEMENT, "selected" = mode == AALARM_MODE_REPLACEMENT, "danger" = 1))
- data["modes"] += list(list("name" = "Siphon - Siphons air out of the room", "mode" = AALARM_MODE_SIPHON, "selected" = mode == AALARM_MODE_SIPHON, "danger" = 1))
- data["modes"] += list(list("name" = "Panic Siphon - Siphons air out of the room quickly","mode" = AALARM_MODE_PANIC, "selected" = mode == AALARM_MODE_PANIC, "danger" = 1))
- data["modes"] += list(list("name" = "Off - Shuts off vents and scrubbers", "mode" = AALARM_MODE_OFF, "selected" = mode == AALARM_MODE_OFF, "danger" = 0))
- if(obj_flags & EMAGGED)
- data["modes"] += list(list("name" = "Flood - Shuts off scrubbers and opens vents", "mode" = AALARM_MODE_FLOOD, "selected" = mode == AALARM_MODE_FLOOD, "danger" = 1))
-
- var/datum/tlv/selected
- var/list/thresholds = list()
-
- selected = TLV["pressure"]
- thresholds += list(list("name" = "Pressure", "settings" = list()))
- thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min2", "selected" = selected.min2))
- thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min1", "selected" = selected.min1))
- thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max1", "selected" = selected.max1))
- thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max2", "selected" = selected.max2))
-
- selected = TLV["temperature"]
- thresholds += list(list("name" = "Temperature", "settings" = list()))
- thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min2", "selected" = selected.min2))
- thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min1", "selected" = selected.min1))
- thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max1", "selected" = selected.max1))
- thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max2", "selected" = selected.max2))
-
- for(var/gas_id in GLOB.meta_gas_names)
- if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
- continue
- selected = TLV[gas_id]
- thresholds += list(list("name" = GLOB.meta_gas_names[gas_id], "settings" = list()))
- thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min2", "selected" = selected.min2))
- thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min1", "selected" = selected.min1))
- thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max1", "selected" = selected.max1))
- thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max2", "selected" = selected.max2))
-
- data["thresholds"] = thresholds
- return data
-
-/obj/machinery/airalarm/ui_act(action, params)
- if(..() || buildstage != 2)
- return
- if((locked && !usr.has_unlimited_silicon_privilege) || (usr.has_unlimited_silicon_privilege && aidisabled))
- return
- var/device_id = params["id_tag"]
- switch(action)
- if("lock")
- if(usr.has_unlimited_silicon_privilege && !wires.is_cut(WIRE_IDSCAN))
- locked = !locked
- . = TRUE
- if("power", "toggle_filter", "widenet", "scrubbing")
- send_signal(device_id, list("[action]" = params["val"]), usr)
- . = TRUE
- if("excheck")
- send_signal(device_id, list("checks" = text2num(params["val"])^1), usr)
- . = TRUE
- if("incheck")
- send_signal(device_id, list("checks" = text2num(params["val"])^2), usr)
- . = TRUE
- if("set_external_pressure", "set_internal_pressure")
- var/area/A = get_area(src)
- var/target = input("New target pressure:", name, A.air_vent_info[device_id][(action == "set_external_pressure" ? "external" : "internal")]) as num|null
- if(!isnull(target) && !..())
- send_signal(device_id, list("[action]" = target), usr)
- . = TRUE
- if("reset_external_pressure")
- send_signal(device_id, list("reset_external_pressure"), usr)
- . = TRUE
- if("reset_internal_pressure")
- send_signal(device_id, list("reset_internal_pressure"), usr)
- . = TRUE
- if("threshold")
- var/env = params["env"]
- if(text2path(env))
- env = text2path(env)
-
- var/name = params["var"]
- var/datum/tlv/tlv = TLV[env]
- if(isnull(tlv))
- return
- var/value = input("New [name] for [env]:", name, tlv.vars[name]) as num|null
- if(!isnull(value) && !..())
- if(value < 0)
- tlv.vars[name] = -1
- else
- tlv.vars[name] = round(value, 0.01)
- investigate_log(" treshold value for [env]:[name] was set to [value] by [key_name(usr)]",INVESTIGATE_ATMOS)
- . = TRUE
- if("mode")
- mode = text2num(params["mode"])
- investigate_log("was turned to [get_mode_name(mode)] mode by [key_name(usr)]",INVESTIGATE_ATMOS)
- apply_mode()
- . = TRUE
- if("alarm")
- var/area/A = get_area(src)
- if(A.atmosalert(2, src))
- post_alert(2)
- . = TRUE
- if("reset")
- var/area/A = get_area(src)
- if(A.atmosalert(0, src))
- post_alert(0)
- . = TRUE
- update_icon()
-
-/obj/machinery/airalarm/proc/reset(wire)
- switch(wire)
- if(WIRE_POWER)
- if(!wires.is_cut(WIRE_POWER))
- shorted = FALSE
- update_icon()
- if(WIRE_AI)
- if(!wires.is_cut(WIRE_AI))
- aidisabled = FALSE
-
-
-/obj/machinery/airalarm/proc/shock(mob/user, prb)
- if((stat & (NOPOWER))) // unpowered, no shock
- return 0
- if(!prob(prb))
- return 0 //you lucked out, no shock for you
- var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
- s.set_up(5, 1, src)
- s.start() //sparks always.
- if (electrocute_mob(user, get_area(src), src, 1, TRUE))
- return 1
- else
- return 0
-
-/obj/machinery/airalarm/proc/refresh_all()
- var/area/A = get_area(src)
- for(var/id_tag in A.air_vent_names)
- var/list/I = A.air_vent_info[id_tag]
- if(I && I["timestamp"] + AALARM_REPORT_TIMEOUT / 2 > world.time)
- continue
- send_signal(id_tag, list("status"))
- for(var/id_tag in A.air_scrub_names)
- var/list/I = A.air_scrub_info[id_tag]
- if(I && I["timestamp"] + AALARM_REPORT_TIMEOUT / 2 > world.time)
- continue
- send_signal(id_tag, list("status"))
-
-/obj/machinery/airalarm/proc/set_frequency(new_frequency)
- SSradio.remove_object(src, frequency)
- frequency = new_frequency
- radio_connection = SSradio.add_object(src, frequency, RADIO_TO_AIRALARM)
-
-/obj/machinery/airalarm/proc/send_signal(target, list/command, mob/user)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise
- if(!radio_connection)
- return 0
-
- var/datum/signal/signal = new(command)
- signal.data["tag"] = target
- signal.data["sigtype"] = "command"
- signal.data["user"] = user
- radio_connection.post_signal(src, signal, RADIO_FROM_AIRALARM)
-
- return 1
-
-/obj/machinery/airalarm/proc/get_mode_name(mode_value)
- switch(mode_value)
- if(AALARM_MODE_SCRUBBING)
- return "Filtering"
- if(AALARM_MODE_CONTAMINATED)
- return "Contaminated"
- if(AALARM_MODE_VENTING)
- return "Draught"
- if(AALARM_MODE_REFILL)
- return "Refill"
- if(AALARM_MODE_PANIC)
- return "Panic Siphon"
- if(AALARM_MODE_REPLACEMENT)
- return "Cycle"
- if(AALARM_MODE_SIPHON)
- return "Siphon"
- if(AALARM_MODE_OFF)
- return "Off"
- if(AALARM_MODE_FLOOD)
- return "Flood"
-
-/obj/machinery/airalarm/proc/apply_mode()
- var/area/A = get_area(src)
- switch(mode)
- if(AALARM_MODE_SCRUBBING)
- for(var/device_id in A.air_scrub_names)
- send_signal(device_id, list(
- "power" = 1,
- "set_filters" = list(/datum/gas/carbon_dioxide, /datum/gas/miasma),
- "scrubbing" = 1,
- "widenet" = 0,
- ))
- for(var/device_id in A.air_vent_names)
- send_signal(device_id, list(
- "power" = 1,
- "checks" = 1,
- "set_external_pressure" = ONE_ATMOSPHERE
- ))
- if(AALARM_MODE_CONTAMINATED)
- for(var/device_id in A.air_scrub_names)
- send_signal(device_id, list(
- "power" = 1,
- "set_filters" = list(
- /datum/gas/carbon_dioxide,
- /datum/gas/miasma,
- /datum/gas/plasma,
- /datum/gas/water_vapor,
- /datum/gas/hypernoblium,
- /datum/gas/nitrous_oxide,
- /datum/gas/nitryl,
- /datum/gas/tritium,
- /datum/gas/bz,
- /datum/gas/stimulum,
- /datum/gas/pluoxium
- ),
- "scrubbing" = 1,
- "widenet" = 1,
- ))
- for(var/device_id in A.air_vent_names)
- send_signal(device_id, list(
- "power" = 1,
- "checks" = 1,
- "set_external_pressure" = ONE_ATMOSPHERE
- ))
- if(AALARM_MODE_VENTING)
- for(var/device_id in A.air_scrub_names)
- send_signal(device_id, list(
- "power" = 1,
- "widenet" = 0,
- "scrubbing" = 0
- ))
- for(var/device_id in A.air_vent_names)
- send_signal(device_id, list(
- "power" = 1,
- "checks" = 1,
- "set_external_pressure" = ONE_ATMOSPHERE*2
- ))
- if(AALARM_MODE_REFILL)
- for(var/device_id in A.air_scrub_names)
- send_signal(device_id, list(
- "power" = 1,
- "set_filters" = list(/datum/gas/carbon_dioxide, /datum/gas/miasma),
- "scrubbing" = 1,
- "widenet" = 0,
- ))
- for(var/device_id in A.air_vent_names)
- send_signal(device_id, list(
- "power" = 1,
- "checks" = 1,
- "set_external_pressure" = ONE_ATMOSPHERE * 3
- ))
- if(AALARM_MODE_PANIC,
- AALARM_MODE_REPLACEMENT)
- for(var/device_id in A.air_scrub_names)
- send_signal(device_id, list(
- "power" = 1,
- "widenet" = 1,
- "scrubbing" = 0
- ))
- for(var/device_id in A.air_vent_names)
- send_signal(device_id, list(
- "power" = 0
- ))
- if(AALARM_MODE_SIPHON)
- for(var/device_id in A.air_scrub_names)
- send_signal(device_id, list(
- "power" = 1,
- "widenet" = 0,
- "scrubbing" = 0
- ))
- for(var/device_id in A.air_vent_names)
- send_signal(device_id, list(
- "power" = 0
- ))
-
- if(AALARM_MODE_OFF)
- for(var/device_id in A.air_scrub_names)
- send_signal(device_id, list(
- "power" = 0
- ))
- for(var/device_id in A.air_vent_names)
- send_signal(device_id, list(
- "power" = 0
- ))
- if(AALARM_MODE_FLOOD)
- for(var/device_id in A.air_scrub_names)
- send_signal(device_id, list(
- "power" = 0
- ))
- for(var/device_id in A.air_vent_names)
- send_signal(device_id, list(
- "power" = 1,
- "checks" = 2,
- "set_internal_pressure" = 0
- ))
-
-/obj/machinery/airalarm/update_icon()
- set_light(0)
- cut_overlays()
- SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
- if(stat & NOPOWER)
- icon_state = "alarm0"
- return
-
- if(stat & BROKEN)
- icon_state = "alarmx"
- return
-
- if(panel_open)
- switch(buildstage)
- if(2)
- icon_state = "alarmx"
- if(1)
- icon_state = "alarm_b2"
- if(0)
- icon_state = "alarm_b1"
- return
-
- icon_state = "alarm1"
- var/overlay_state = AALARM_OVERLAY_OFF
- var/area/A = get_area(src)
- switch(max(danger_level, A.atmosalm))
- if(0)
- add_overlay(AALARM_OVERLAY_GREEN)
- overlay_state = AALARM_OVERLAY_GREEN
- light_color = LIGHT_COLOR_GREEN
- set_light(brightness_on)
- if(1)
- add_overlay(AALARM_OVERLAY_WARN)
- overlay_state = AALARM_OVERLAY_WARN
- light_color = LIGHT_COLOR_LAVA
- set_light(brightness_on)
- if(2)
- add_overlay(AALARM_OVERLAY_DANGER)
- overlay_state = AALARM_OVERLAY_DANGER
- light_color = LIGHT_COLOR_RED
- set_light(brightness_on)
-
- SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
- update_light()
-
-/obj/machinery/airalarm/process()
- if((stat & (NOPOWER|BROKEN)) || shorted)
- return
-
- var/turf/location = get_turf(src)
- if(!location)
- return
-
- var/datum/tlv/cur_tlv
-
- var/datum/gas_mixture/environment = location.return_air()
- var/list/env_gases = environment.gases
- var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume
-
- cur_tlv = TLV["pressure"]
- var/environment_pressure = environment.return_pressure()
- var/pressure_dangerlevel = cur_tlv.get_danger_level(environment_pressure)
-
- cur_tlv = TLV["temperature"]
- var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature)
-
- var/gas_dangerlevel = 0
- for(var/gas_id in env_gases)
- if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
- continue
- cur_tlv = TLV[gas_id]
- gas_dangerlevel = max(gas_dangerlevel, cur_tlv.get_danger_level(env_gases[gas_id] * partial_pressure))
-
- GAS_GARBAGE_COLLECT(environment.gases)
-
- var/old_danger_level = danger_level
- danger_level = max(pressure_dangerlevel, temperature_dangerlevel, gas_dangerlevel)
-
- if(old_danger_level != danger_level)
- apply_danger_level()
- if(mode == AALARM_MODE_REPLACEMENT && environment_pressure < ONE_ATMOSPHERE * 0.05)
- mode = AALARM_MODE_SCRUBBING
- apply_mode()
-
- return
-
-
-/obj/machinery/airalarm/proc/post_alert(alert_level)
- var/datum/radio_frequency/frequency = SSradio.return_frequency(alarm_frequency)
-
- if(!frequency)
- return
-
- var/datum/signal/alert_signal = new(list(
- "zone" = get_area_name(src),
- "type" = "Atmospheric"
- ))
- if(alert_level==2)
- alert_signal.data["alert"] = "severe"
- else if (alert_level==1)
- alert_signal.data["alert"] = "minor"
- else if (alert_level==0)
- alert_signal.data["alert"] = "clear"
-
- frequency.post_signal(src, alert_signal, range = -1)
-
-/obj/machinery/airalarm/proc/apply_danger_level()
- var/area/A = get_area(src)
-
- var/new_area_danger_level = 0
- for(var/obj/machinery/airalarm/AA in A)
- if (!(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted)
- new_area_danger_level = max(new_area_danger_level,AA.danger_level)
- if(A.atmosalert(new_area_danger_level,src)) //if area was in normal state or if area was in alert state
- post_alert(new_area_danger_level)
-
- update_icon()
-
-/obj/machinery/airalarm/attackby(obj/item/W, mob/user, params)
- switch(buildstage)
- if(2)
- if(istype(W, /obj/item/wirecutters) && panel_open && wires.is_all_cut())
- W.play_tool_sound(src)
- to_chat(user, "You cut the final wires.")
- new /obj/item/stack/cable_coil(loc, 5)
- buildstage = 1
- update_icon()
- return
- else if(istype(W, /obj/item/screwdriver)) // Opening that Air Alarm up.
- W.play_tool_sound(src)
- panel_open = !panel_open
- to_chat(user, "The wires have been [panel_open ? "exposed" : "unexposed"].")
- update_icon()
- return
- else if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda))// trying to unlock the interface with an ID card
- togglelock(user)
- else if(panel_open && is_wire_tool(W))
- wires.interact(user)
- return
- if(1)
- if(istype(W, /obj/item/crowbar))
- user.visible_message("[user.name] removes the electronics from [src.name].",\
- "You start prying out the circuit...")
- W.play_tool_sound(src)
- if (W.use_tool(src, user, 20))
- if (buildstage == 1)
- to_chat(user, "You remove the air alarm electronics.")
- new /obj/item/electronics/airalarm( src.loc )
- playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
- buildstage = 0
- update_icon()
- return
-
- if(istype(W, /obj/item/stack/cable_coil))
- var/obj/item/stack/cable_coil/cable = W
- if(cable.get_amount() < 5)
- to_chat(user, "You need five lengths of cable to wire the air alarm!")
- return
- user.visible_message("[user.name] wires the air alarm.", \
- "You start wiring the air alarm...")
- if (do_after(user, 20, target = src))
- if (cable.get_amount() >= 5 && buildstage == 1)
- cable.use(5)
- to_chat(user, "You wire the air alarm.")
- wires.repair()
- aidisabled = 0
- locked = FALSE
- mode = 1
- shorted = 0
- post_alert(0)
- buildstage = 2
- update_icon()
- return
- if(0)
- if(istype(W, /obj/item/electronics/airalarm))
- if(user.temporarilyRemoveItemFromInventory(W))
- to_chat(user, "You insert the circuit.")
- buildstage = 1
- update_icon()
- qdel(W)
- return
-
- if(istype(W, /obj/item/electroadaptive_pseudocircuit))
- var/obj/item/electroadaptive_pseudocircuit/P = W
- if(!P.adapt_circuit(user, 25))
- return
- user.visible_message("[user] fabricates a circuit and places it into [src].", \
- "You adapt an air alarm circuit and slot it into the assembly.")
- buildstage = 1
- update_icon()
- return
-
- if(istype(W, /obj/item/wrench))
- to_chat(user, "You detach \the [src] from the wall.")
- W.play_tool_sound(src)
- new /obj/item/wallframe/airalarm( user.loc )
- qdel(src)
- return
-
- return ..()
-
-/obj/machinery/airalarm/AltClick(mob/user)
- ..()
- if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc))
- return
- else
- togglelock(user)
-
-/obj/machinery/airalarm/proc/togglelock(mob/living/user)
- if(stat & (NOPOWER|BROKEN))
- to_chat(user, "It does nothing!")
- else
- if(src.allowed(usr) && !wires.is_cut(WIRE_IDSCAN))
- locked = !locked
- updateUsrDialog()
- to_chat(user, "You [ locked ? "lock" : "unlock"] the air alarm interface.")
- else
- to_chat(user, "Access denied.")
- return
-
-/obj/machinery/airalarm/power_change()
- ..()
- if(stat & NOPOWER)
- set_light(0)
- update_icon()
-
-/obj/machinery/airalarm/emag_act(mob/user)
- if(obj_flags & EMAGGED)
- return
- obj_flags |= EMAGGED
- visible_message("Sparks fly out of [src]!", "You emag [src], disabling its safeties.")
- playsound(src, "sparks", 50, 1)
-
-/obj/machinery/airalarm/obj_break(damage_flag)
- ..()
- update_icon()
- set_light(0)
-
-/obj/machinery/airalarm/deconstruct(disassembled = TRUE)
- if(!(flags_1 & NODECONSTRUCT_1))
- new /obj/item/stack/sheet/metal(loc, 2)
- var/obj/item/I = new /obj/item/electronics/airalarm(loc)
- if(!disassembled)
- I.obj_integrity = I.max_integrity * 0.5
- new /obj/item/stack/cable_coil(loc, 3)
- qdel(src)
-
-#undef AALARM_MODE_SCRUBBING
-#undef AALARM_MODE_VENTING
-#undef AALARM_MODE_PANIC
-#undef AALARM_MODE_REPLACEMENT
-#undef AALARM_MODE_OFF
-#undef AALARM_MODE_FLOOD
-#undef AALARM_MODE_SIPHON
-#undef AALARM_MODE_CONTAMINATED
-#undef AALARM_MODE_REFILL
-#undef AALARM_REPORT_TIMEOUT
+/datum/tlv
+ var/min2
+ var/min1
+ var/max1
+ var/max2
+
+/datum/tlv/New(min2 as num, min1 as num, max1 as num, max2 as num)
+ if(min2) src.min2 = min2
+ if(min1) src.min1 = min1
+ if(max1) src.max1 = max1
+ if(max2) src.max2 = max2
+
+/datum/tlv/proc/get_danger_level(val as num)
+ if(max2 != -1 && val >= max2)
+ return 2
+ if(min2 != -1 && val <= min2)
+ return 2
+ if(max1 != -1 && val >= max1)
+ return 1
+ if(min1 != -1 && val <= min1)
+ return 1
+ return 0
+
+/datum/tlv/no_checks
+ min2 = -1
+ min1 = -1
+ max1 = -1
+ max2 = -1
+
+/datum/tlv/dangerous
+ min2 = -1
+ min1 = -1
+ max1 = 0.2
+ max2 = 0.5
+
+/obj/item/electronics/airalarm
+ name = "air alarm electronics"
+ icon_state = "airalarm_electronics"
+
+/obj/item/wallframe/airalarm
+ name = "air alarm frame"
+ desc = "Used for building Air Alarms."
+ icon = 'icons/obj/monitors.dmi'
+ icon_state = "alarm_bitem"
+ result_path = /obj/machinery/airalarm
+
+#define AALARM_MODE_SCRUBBING 1
+#define AALARM_MODE_VENTING 2 //makes draught
+#define AALARM_MODE_PANIC 3 //like siphon, but stronger (enables widenet)
+#define AALARM_MODE_REPLACEMENT 4 //sucks off all air, then refill and swithes to scrubbing
+#define AALARM_MODE_OFF 5
+#define AALARM_MODE_FLOOD 6 //Emagged mode; turns off scrubbers and pressure checks on vents
+#define AALARM_MODE_SIPHON 7 //Scrubbers suck air
+#define AALARM_MODE_CONTAMINATED 8 //Turns on all filtering and widenet scrubbing.
+#define AALARM_MODE_REFILL 9 //just like normal, but with triple the air output
+
+#define AALARM_REPORT_TIMEOUT 100
+
+#define AALARM_OVERLAY_OFF "alarm_off"
+#define AALARM_OVERLAY_GREEN "alarm_green"
+#define AALARM_OVERLAY_WARN "alarm_amber"
+#define AALARM_OVERLAY_DANGER "alarm_red"
+
+/obj/machinery/airalarm
+ name = "air alarm"
+ desc = "A machine that monitors atmosphere levels. Goes off if the area is dangerous."
+ icon = 'icons/obj/monitors.dmi'
+ icon_state = "alarm0"
+ use_power = IDLE_POWER_USE
+ idle_power_usage = 4
+ active_power_usage = 8
+ power_channel = ENVIRON
+ req_access = list(ACCESS_ATMOSPHERICS)
+ max_integrity = 250
+ integrity_failure = 80
+ armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30)
+ resistance_flags = FIRE_PROOF
+
+ var/danger_level = 0
+ var/mode = AALARM_MODE_SCRUBBING
+
+ var/locked = TRUE
+ var/aidisabled = 0
+ var/shorted = 0
+ var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone
+ var/brightness_on = 1
+
+ var/frequency = FREQ_ATMOS_CONTROL
+ var/alarm_frequency = FREQ_ATMOS_ALARMS
+ var/datum/radio_frequency/radio_connection
+
+ var/list/TLV = list( // Breathable air.
+ "pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa
+ "temperature" = new/datum/tlv(T0C, T0C+10, T0C+40, T0C+66),
+ /datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
+ /datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000),
+ /datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10),
+ /datum/gas/miasma = new/datum/tlv/(-1, -1, 2, 5),
+ /datum/gas/plasma = new/datum/tlv/dangerous,
+ /datum/gas/nitrous_oxide = new/datum/tlv/dangerous,
+ /datum/gas/bz = new/datum/tlv/dangerous,
+ /datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic
+ /datum/gas/water_vapor = new/datum/tlv/dangerous,
+ /datum/gas/tritium = new/datum/tlv/dangerous,
+ /datum/gas/stimulum = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects
+ /datum/gas/nitryl = new/datum/tlv/dangerous,
+ /datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000) // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
+ )
+
+/obj/machinery/airalarm/server // No checks here.
+ TLV = list(
+ "pressure" = new/datum/tlv/no_checks,
+ "temperature" = new/datum/tlv/no_checks,
+ /datum/gas/oxygen = new/datum/tlv/no_checks,
+ /datum/gas/nitrogen = new/datum/tlv/no_checks,
+ /datum/gas/carbon_dioxide = new/datum/tlv/no_checks,
+ /datum/gas/miasma = new/datum/tlv/no_checks,
+ /datum/gas/plasma = new/datum/tlv/no_checks,
+ /datum/gas/nitrous_oxide = new/datum/tlv/no_checks,
+ /datum/gas/bz = new/datum/tlv/no_checks,
+ /datum/gas/hypernoblium = new/datum/tlv/no_checks,
+ /datum/gas/water_vapor = new/datum/tlv/no_checks,
+ /datum/gas/tritium = new/datum/tlv/no_checks,
+ /datum/gas/stimulum = new/datum/tlv/no_checks,
+ /datum/gas/nitryl = new/datum/tlv/no_checks,
+ /datum/gas/pluoxium = new/datum/tlv/no_checks
+ )
+
+/obj/machinery/airalarm/kitchen_cold_room // Copypasta: to check temperatures.
+ TLV = list(
+ "pressure" = new/datum/tlv(ONE_ATMOSPHERE * 0.8, ONE_ATMOSPHERE* 0.9, ONE_ATMOSPHERE * 1.1, ONE_ATMOSPHERE * 1.2), // kPa
+ "temperature" = new/datum/tlv(T0C-73.15, T0C-63.15, T0C, T0C+10),
+ /datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
+ /datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000),
+ /datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10),
+ /datum/gas/miasma = new/datum/tlv/(-1, -1, 2, 5),
+ /datum/gas/plasma = new/datum/tlv/dangerous,
+ /datum/gas/nitrous_oxide = new/datum/tlv/dangerous,
+ /datum/gas/bz = new/datum/tlv/dangerous,
+ /datum/gas/hypernoblium = new/datum/tlv(-1, -1, 1000, 1000), // Hyper-Noblium is inert and nontoxic
+ /datum/gas/water_vapor = new/datum/tlv/dangerous,
+ /datum/gas/tritium = new/datum/tlv/dangerous,
+ /datum/gas/stimulum = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects
+ /datum/gas/nitryl = new/datum/tlv/dangerous,
+ /datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000) // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
+ )
+
+/obj/machinery/airalarm/unlocked
+ locked = FALSE
+
+/obj/machinery/airalarm/engine
+ name = "engine air alarm"
+ locked = FALSE
+ req_access = null
+ req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_ENGINE)
+
+/obj/machinery/airalarm/mixingchamber
+ name = "chamber air alarm"
+ locked = FALSE
+ req_access = null
+ req_one_access = list(ACCESS_ATMOSPHERICS, ACCESS_TOX, ACCESS_TOX_STORAGE)
+
+/obj/machinery/airalarm/all_access
+ name = "all-access air alarm"
+ desc = "This particular atmos control unit appears to have no access restrictions."
+ locked = FALSE
+ req_access = null
+ req_one_access = null
+
+/obj/machinery/airalarm/syndicate //general syndicate access
+ req_access = list(ACCESS_SYNDICATE)
+
+/obj/machinery/airalarm/directional/north //Pixel offsets get overwritten on New()
+ dir = SOUTH
+ pixel_y = 24
+
+/obj/machinery/airalarm/directional/south
+ dir = NORTH
+ pixel_y = -24
+
+/obj/machinery/airalarm/directional/east
+ dir = WEST
+ pixel_x = 24
+
+/obj/machinery/airalarm/directional/west
+ dir = EAST
+ pixel_x = -24
+
+//all air alarms in area are connected via magic
+/area
+ var/list/air_vent_names = list()
+ var/list/air_scrub_names = list()
+ var/list/air_vent_info = list()
+ var/list/air_scrub_info = list()
+
+/obj/machinery/airalarm/Initialize(mapload, ndir, nbuild)
+ . = ..()
+ wires = new /datum/wires/airalarm(src)
+
+ if(ndir)
+ setDir(ndir)
+
+ if(nbuild)
+ buildstage = 0
+ panel_open = TRUE
+ pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
+ pixel_y = (dir & 3)? (dir == 1 ? -24 : 24) : 0
+
+ if(name == initial(name))
+ name = "[get_area_name(src)] Air Alarm"
+
+ power_change()
+ set_frequency(frequency)
+
+/obj/machinery/airalarm/Destroy()
+ SSradio.remove_object(src, frequency)
+ qdel(wires)
+ wires = null
+ return ..()
+
+/obj/machinery/airalarm/examine(mob/user)
+ . = ..()
+ switch(buildstage)
+ if(0)
+ to_chat(user, "It is missing air alarm electronics.")
+ if(1)
+ to_chat(user, "It is missing wiring.")
+ if(2)
+ to_chat(user, "Alt-click to [locked ? "unlock" : "lock"] the interface.")
+
+/obj/machinery/airalarm/ui_status(mob/user)
+ if(user.has_unlimited_silicon_privilege && aidisabled)
+ to_chat(user, "AI control has been disabled.")
+ else if(!shorted)
+ return ..()
+ return UI_CLOSE
+
+/obj/machinery/airalarm/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
+ datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
+ ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
+ if(!ui)
+ ui = new(user, src, ui_key, "airalarm", name, 440, 650, master_ui, state)
+ ui.open()
+
+/obj/machinery/airalarm/ui_data(mob/user)
+ var/data = list(
+ "locked" = locked,
+ "siliconUser" = user.has_unlimited_silicon_privilege,
+ "emagged" = (obj_flags & EMAGGED ? 1 : 0),
+ "danger_level" = danger_level,
+ )
+
+ var/area/A = get_area(src)
+ data["atmos_alarm"] = A.atmosalm
+ data["fire_alarm"] = A.fire
+
+ var/turf/T = get_turf(src)
+ var/datum/gas_mixture/environment = T.return_air()
+ var/datum/tlv/cur_tlv
+
+ data["environment_data"] = list()
+ var/pressure = environment.return_pressure()
+ cur_tlv = TLV["pressure"]
+ data["environment_data"] += list(list(
+ "name" = "Pressure",
+ "value" = pressure,
+ "unit" = "kPa",
+ "danger_level" = cur_tlv.get_danger_level(pressure)
+ ))
+ var/temperature = environment.temperature
+ cur_tlv = TLV["temperature"]
+ data["environment_data"] += list(list(
+ "name" = "Temperature",
+ "value" = temperature,
+ "unit" = "K ([round(temperature - T0C, 0.1)]C)",
+ "danger_level" = cur_tlv.get_danger_level(temperature)
+ ))
+ var/total_moles = environment.total_moles()
+ var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume
+ for(var/gas_id in environment.gases)
+ if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
+ continue
+ cur_tlv = TLV[gas_id]
+ data["environment_data"] += list(list(
+ "name" = GLOB.meta_gas_names[gas_id],
+ "value" = environment.gases[gas_id] / total_moles * 100,
+ "unit" = "%",
+ "danger_level" = cur_tlv.get_danger_level(environment.gases[gas_id] * partial_pressure)
+ ))
+
+ if(!locked || user.has_unlimited_silicon_privilege)
+ data["vents"] = list()
+ for(var/id_tag in A.air_vent_names)
+ var/long_name = A.air_vent_names[id_tag]
+ var/list/info = A.air_vent_info[id_tag]
+ if(!info || info["frequency"] != frequency)
+ continue
+ data["vents"] += list(list(
+ "id_tag" = id_tag,
+ "long_name" = sanitize(long_name),
+ "power" = info["power"],
+ "checks" = info["checks"],
+ "excheck" = info["checks"]&1,
+ "incheck" = info["checks"]&2,
+ "direction" = info["direction"],
+ "external" = info["external"],
+ "internal" = info["internal"],
+ "extdefault"= (info["external"] == ONE_ATMOSPHERE),
+ "intdefault"= (info["internal"] == 0)
+ ))
+ data["scrubbers"] = list()
+ for(var/id_tag in A.air_scrub_names)
+ var/long_name = A.air_scrub_names[id_tag]
+ var/list/info = A.air_scrub_info[id_tag]
+ if(!info || info["frequency"] != frequency)
+ continue
+ data["scrubbers"] += list(list(
+ "id_tag" = id_tag,
+ "long_name" = sanitize(long_name),
+ "power" = info["power"],
+ "scrubbing" = info["scrubbing"],
+ "widenet" = info["widenet"],
+ "filter_types" = info["filter_types"]
+ ))
+ data["mode"] = mode
+ data["modes"] = list()
+ data["modes"] += list(list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0))
+ data["modes"] += list(list("name" = "Contaminated - Scrubs out ALL contaminants quickly","mode" = AALARM_MODE_CONTAMINATED, "selected" = mode == AALARM_MODE_CONTAMINATED, "danger" = 0))
+ data["modes"] += list(list("name" = "Draught - Siphons out air while replacing", "mode" = AALARM_MODE_VENTING, "selected" = mode == AALARM_MODE_VENTING, "danger" = 0))
+ data["modes"] += list(list("name" = "Refill - Triple vent output", "mode" = AALARM_MODE_REFILL, "selected" = mode == AALARM_MODE_REFILL, "danger" = 1))
+ data["modes"] += list(list("name" = "Cycle - Siphons air before replacing", "mode" = AALARM_MODE_REPLACEMENT, "selected" = mode == AALARM_MODE_REPLACEMENT, "danger" = 1))
+ data["modes"] += list(list("name" = "Siphon - Siphons air out of the room", "mode" = AALARM_MODE_SIPHON, "selected" = mode == AALARM_MODE_SIPHON, "danger" = 1))
+ data["modes"] += list(list("name" = "Panic Siphon - Siphons air out of the room quickly","mode" = AALARM_MODE_PANIC, "selected" = mode == AALARM_MODE_PANIC, "danger" = 1))
+ data["modes"] += list(list("name" = "Off - Shuts off vents and scrubbers", "mode" = AALARM_MODE_OFF, "selected" = mode == AALARM_MODE_OFF, "danger" = 0))
+ if(obj_flags & EMAGGED)
+ data["modes"] += list(list("name" = "Flood - Shuts off scrubbers and opens vents", "mode" = AALARM_MODE_FLOOD, "selected" = mode == AALARM_MODE_FLOOD, "danger" = 1))
+
+ var/datum/tlv/selected
+ var/list/thresholds = list()
+
+ selected = TLV["pressure"]
+ thresholds += list(list("name" = "Pressure", "settings" = list()))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min2", "selected" = selected.min2))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min1", "selected" = selected.min1))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max1", "selected" = selected.max1))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max2", "selected" = selected.max2))
+
+ selected = TLV["temperature"]
+ thresholds += list(list("name" = "Temperature", "settings" = list()))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min2", "selected" = selected.min2))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min1", "selected" = selected.min1))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max1", "selected" = selected.max1))
+ thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max2", "selected" = selected.max2))
+
+ for(var/gas_id in GLOB.meta_gas_names)
+ if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
+ continue
+ selected = TLV[gas_id]
+ thresholds += list(list("name" = GLOB.meta_gas_names[gas_id], "settings" = list()))
+ thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min2", "selected" = selected.min2))
+ thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min1", "selected" = selected.min1))
+ thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max1", "selected" = selected.max1))
+ thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max2", "selected" = selected.max2))
+
+ data["thresholds"] = thresholds
+ return data
+
+/obj/machinery/airalarm/ui_act(action, params)
+ if(..() || buildstage != 2)
+ return
+ if((locked && !usr.has_unlimited_silicon_privilege) || (usr.has_unlimited_silicon_privilege && aidisabled))
+ return
+ var/device_id = params["id_tag"]
+ switch(action)
+ if("lock")
+ if(usr.has_unlimited_silicon_privilege && !wires.is_cut(WIRE_IDSCAN))
+ locked = !locked
+ . = TRUE
+ if("power", "toggle_filter", "widenet", "scrubbing")
+ send_signal(device_id, list("[action]" = params["val"]), usr)
+ . = TRUE
+ if("excheck")
+ send_signal(device_id, list("checks" = text2num(params["val"])^1), usr)
+ . = TRUE
+ if("incheck")
+ send_signal(device_id, list("checks" = text2num(params["val"])^2), usr)
+ . = TRUE
+ if("set_external_pressure", "set_internal_pressure")
+ var/area/A = get_area(src)
+ var/target = input("New target pressure:", name, A.air_vent_info[device_id][(action == "set_external_pressure" ? "external" : "internal")]) as num|null
+ if(!isnull(target) && !..())
+ send_signal(device_id, list("[action]" = target), usr)
+ . = TRUE
+ if("reset_external_pressure")
+ send_signal(device_id, list("reset_external_pressure"), usr)
+ . = TRUE
+ if("reset_internal_pressure")
+ send_signal(device_id, list("reset_internal_pressure"), usr)
+ . = TRUE
+ if("threshold")
+ var/env = params["env"]
+ if(text2path(env))
+ env = text2path(env)
+
+ var/name = params["var"]
+ var/datum/tlv/tlv = TLV[env]
+ if(isnull(tlv))
+ return
+ var/value = input("New [name] for [env]:", name, tlv.vars[name]) as num|null
+ if(!isnull(value) && !..())
+ if(value < 0)
+ tlv.vars[name] = -1
+ else
+ tlv.vars[name] = round(value, 0.01)
+ investigate_log(" treshold value for [env]:[name] was set to [value] by [key_name(usr)]",INVESTIGATE_ATMOS)
+ . = TRUE
+ if("mode")
+ mode = text2num(params["mode"])
+ investigate_log("was turned to [get_mode_name(mode)] mode by [key_name(usr)]",INVESTIGATE_ATMOS)
+ apply_mode()
+ . = TRUE
+ if("alarm")
+ var/area/A = get_area(src)
+ if(A.atmosalert(2, src))
+ post_alert(2)
+ . = TRUE
+ if("reset")
+ var/area/A = get_area(src)
+ if(A.atmosalert(0, src))
+ post_alert(0)
+ . = TRUE
+ update_icon()
+
+/obj/machinery/airalarm/proc/reset(wire)
+ switch(wire)
+ if(WIRE_POWER)
+ if(!wires.is_cut(WIRE_POWER))
+ shorted = FALSE
+ update_icon()
+ if(WIRE_AI)
+ if(!wires.is_cut(WIRE_AI))
+ aidisabled = FALSE
+
+
+/obj/machinery/airalarm/proc/shock(mob/user, prb)
+ if((stat & (NOPOWER))) // unpowered, no shock
+ return 0
+ if(!prob(prb))
+ return 0 //you lucked out, no shock for you
+ var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
+ s.set_up(5, 1, src)
+ s.start() //sparks always.
+ if (electrocute_mob(user, get_area(src), src, 1, TRUE))
+ return 1
+ else
+ return 0
+
+/obj/machinery/airalarm/proc/refresh_all()
+ var/area/A = get_area(src)
+ for(var/id_tag in A.air_vent_names)
+ var/list/I = A.air_vent_info[id_tag]
+ if(I && I["timestamp"] + AALARM_REPORT_TIMEOUT / 2 > world.time)
+ continue
+ send_signal(id_tag, list("status"))
+ for(var/id_tag in A.air_scrub_names)
+ var/list/I = A.air_scrub_info[id_tag]
+ if(I && I["timestamp"] + AALARM_REPORT_TIMEOUT / 2 > world.time)
+ continue
+ send_signal(id_tag, list("status"))
+
+/obj/machinery/airalarm/proc/set_frequency(new_frequency)
+ SSradio.remove_object(src, frequency)
+ frequency = new_frequency
+ radio_connection = SSradio.add_object(src, frequency, RADIO_TO_AIRALARM)
+
+/obj/machinery/airalarm/proc/send_signal(target, list/command, mob/user)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise
+ if(!radio_connection)
+ return 0
+
+ var/datum/signal/signal = new(command)
+ signal.data["tag"] = target
+ signal.data["sigtype"] = "command"
+ signal.data["user"] = user
+ radio_connection.post_signal(src, signal, RADIO_FROM_AIRALARM)
+
+ return 1
+
+/obj/machinery/airalarm/proc/get_mode_name(mode_value)
+ switch(mode_value)
+ if(AALARM_MODE_SCRUBBING)
+ return "Filtering"
+ if(AALARM_MODE_CONTAMINATED)
+ return "Contaminated"
+ if(AALARM_MODE_VENTING)
+ return "Draught"
+ if(AALARM_MODE_REFILL)
+ return "Refill"
+ if(AALARM_MODE_PANIC)
+ return "Panic Siphon"
+ if(AALARM_MODE_REPLACEMENT)
+ return "Cycle"
+ if(AALARM_MODE_SIPHON)
+ return "Siphon"
+ if(AALARM_MODE_OFF)
+ return "Off"
+ if(AALARM_MODE_FLOOD)
+ return "Flood"
+
+/obj/machinery/airalarm/proc/apply_mode()
+ var/area/A = get_area(src)
+ switch(mode)
+ if(AALARM_MODE_SCRUBBING)
+ for(var/device_id in A.air_scrub_names)
+ send_signal(device_id, list(
+ "power" = 1,
+ "set_filters" = list(/datum/gas/carbon_dioxide, /datum/gas/miasma),
+ "scrubbing" = 1,
+ "widenet" = 0,
+ ))
+ for(var/device_id in A.air_vent_names)
+ send_signal(device_id, list(
+ "power" = 1,
+ "checks" = 1,
+ "set_external_pressure" = ONE_ATMOSPHERE
+ ))
+ if(AALARM_MODE_CONTAMINATED)
+ for(var/device_id in A.air_scrub_names)
+ send_signal(device_id, list(
+ "power" = 1,
+ "set_filters" = list(
+ /datum/gas/carbon_dioxide,
+ /datum/gas/miasma,
+ /datum/gas/plasma,
+ /datum/gas/water_vapor,
+ /datum/gas/hypernoblium,
+ /datum/gas/nitrous_oxide,
+ /datum/gas/nitryl,
+ /datum/gas/tritium,
+ /datum/gas/bz,
+ /datum/gas/stimulum,
+ /datum/gas/pluoxium
+ ),
+ "scrubbing" = 1,
+ "widenet" = 1,
+ ))
+ for(var/device_id in A.air_vent_names)
+ send_signal(device_id, list(
+ "power" = 1,
+ "checks" = 1,
+ "set_external_pressure" = ONE_ATMOSPHERE
+ ))
+ if(AALARM_MODE_VENTING)
+ for(var/device_id in A.air_scrub_names)
+ send_signal(device_id, list(
+ "power" = 1,
+ "widenet" = 0,
+ "scrubbing" = 0
+ ))
+ for(var/device_id in A.air_vent_names)
+ send_signal(device_id, list(
+ "power" = 1,
+ "checks" = 1,
+ "set_external_pressure" = ONE_ATMOSPHERE*2
+ ))
+ if(AALARM_MODE_REFILL)
+ for(var/device_id in A.air_scrub_names)
+ send_signal(device_id, list(
+ "power" = 1,
+ "set_filters" = list(/datum/gas/carbon_dioxide, /datum/gas/miasma),
+ "scrubbing" = 1,
+ "widenet" = 0,
+ ))
+ for(var/device_id in A.air_vent_names)
+ send_signal(device_id, list(
+ "power" = 1,
+ "checks" = 1,
+ "set_external_pressure" = ONE_ATMOSPHERE * 3
+ ))
+ if(AALARM_MODE_PANIC,
+ AALARM_MODE_REPLACEMENT)
+ for(var/device_id in A.air_scrub_names)
+ send_signal(device_id, list(
+ "power" = 1,
+ "widenet" = 1,
+ "scrubbing" = 0
+ ))
+ for(var/device_id in A.air_vent_names)
+ send_signal(device_id, list(
+ "power" = 0
+ ))
+ if(AALARM_MODE_SIPHON)
+ for(var/device_id in A.air_scrub_names)
+ send_signal(device_id, list(
+ "power" = 1,
+ "widenet" = 0,
+ "scrubbing" = 0
+ ))
+ for(var/device_id in A.air_vent_names)
+ send_signal(device_id, list(
+ "power" = 0
+ ))
+
+ if(AALARM_MODE_OFF)
+ for(var/device_id in A.air_scrub_names)
+ send_signal(device_id, list(
+ "power" = 0
+ ))
+ for(var/device_id in A.air_vent_names)
+ send_signal(device_id, list(
+ "power" = 0
+ ))
+ if(AALARM_MODE_FLOOD)
+ for(var/device_id in A.air_scrub_names)
+ send_signal(device_id, list(
+ "power" = 0
+ ))
+ for(var/device_id in A.air_vent_names)
+ send_signal(device_id, list(
+ "power" = 1,
+ "checks" = 2,
+ "set_internal_pressure" = 0
+ ))
+
+/obj/machinery/airalarm/update_icon()
+ set_light(0)
+ cut_overlays()
+ SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
+ if(stat & NOPOWER)
+ icon_state = "alarm0"
+ return
+
+ if(stat & BROKEN)
+ icon_state = "alarmx"
+ return
+
+ if(panel_open)
+ switch(buildstage)
+ if(2)
+ icon_state = "alarmx"
+ if(1)
+ icon_state = "alarm_b2"
+ if(0)
+ icon_state = "alarm_b1"
+ return
+
+ icon_state = "alarm1"
+ var/overlay_state = AALARM_OVERLAY_OFF
+ var/area/A = get_area(src)
+ switch(max(danger_level, A.atmosalm))
+ if(0)
+ add_overlay(AALARM_OVERLAY_GREEN)
+ overlay_state = AALARM_OVERLAY_GREEN
+ light_color = LIGHT_COLOR_GREEN
+ set_light(brightness_on)
+ if(1)
+ add_overlay(AALARM_OVERLAY_WARN)
+ overlay_state = AALARM_OVERLAY_WARN
+ light_color = LIGHT_COLOR_LAVA
+ set_light(brightness_on)
+ if(2)
+ add_overlay(AALARM_OVERLAY_DANGER)
+ overlay_state = AALARM_OVERLAY_DANGER
+ light_color = LIGHT_COLOR_RED
+ set_light(brightness_on)
+
+ SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
+ update_light()
+
+/obj/machinery/airalarm/process()
+ if((stat & (NOPOWER|BROKEN)) || shorted)
+ return
+
+ var/turf/location = get_turf(src)
+ if(!location)
+ return
+
+ var/datum/tlv/cur_tlv
+
+ var/datum/gas_mixture/environment = location.return_air()
+ var/list/env_gases = environment.gases
+ var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume
+
+ cur_tlv = TLV["pressure"]
+ var/environment_pressure = environment.return_pressure()
+ var/pressure_dangerlevel = cur_tlv.get_danger_level(environment_pressure)
+
+ cur_tlv = TLV["temperature"]
+ var/temperature_dangerlevel = cur_tlv.get_danger_level(environment.temperature)
+
+ var/gas_dangerlevel = 0
+ for(var/gas_id in env_gases)
+ if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
+ continue
+ cur_tlv = TLV[gas_id]
+ gas_dangerlevel = max(gas_dangerlevel, cur_tlv.get_danger_level(env_gases[gas_id] * partial_pressure))
+
+ GAS_GARBAGE_COLLECT(environment.gases)
+
+ var/old_danger_level = danger_level
+ danger_level = max(pressure_dangerlevel, temperature_dangerlevel, gas_dangerlevel)
+
+ if(old_danger_level != danger_level)
+ apply_danger_level()
+ if(mode == AALARM_MODE_REPLACEMENT && environment_pressure < ONE_ATMOSPHERE * 0.05)
+ mode = AALARM_MODE_SCRUBBING
+ apply_mode()
+
+ return
+
+
+/obj/machinery/airalarm/proc/post_alert(alert_level)
+ var/datum/radio_frequency/frequency = SSradio.return_frequency(alarm_frequency)
+
+ if(!frequency)
+ return
+
+ var/datum/signal/alert_signal = new(list(
+ "zone" = get_area_name(src),
+ "type" = "Atmospheric"
+ ))
+ if(alert_level==2)
+ alert_signal.data["alert"] = "severe"
+ else if (alert_level==1)
+ alert_signal.data["alert"] = "minor"
+ else if (alert_level==0)
+ alert_signal.data["alert"] = "clear"
+
+ frequency.post_signal(src, alert_signal, range = -1)
+
+/obj/machinery/airalarm/proc/apply_danger_level()
+ var/area/A = get_area(src)
+
+ var/new_area_danger_level = 0
+ for(var/obj/machinery/airalarm/AA in A)
+ if (!(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted)
+ new_area_danger_level = max(new_area_danger_level,AA.danger_level)
+ if(A.atmosalert(new_area_danger_level,src)) //if area was in normal state or if area was in alert state
+ post_alert(new_area_danger_level)
+
+ update_icon()
+
+/obj/machinery/airalarm/attackby(obj/item/W, mob/user, params)
+ switch(buildstage)
+ if(2)
+ if(istype(W, /obj/item/wirecutters) && panel_open && wires.is_all_cut())
+ W.play_tool_sound(src)
+ to_chat(user, "You cut the final wires.")
+ new /obj/item/stack/cable_coil(loc, 5)
+ buildstage = 1
+ update_icon()
+ return
+ else if(istype(W, /obj/item/screwdriver)) // Opening that Air Alarm up.
+ W.play_tool_sound(src)
+ panel_open = !panel_open
+ to_chat(user, "The wires have been [panel_open ? "exposed" : "unexposed"].")
+ update_icon()
+ return
+ else if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda))// trying to unlock the interface with an ID card
+ togglelock(user)
+ else if(panel_open && is_wire_tool(W))
+ wires.interact(user)
+ return
+ if(1)
+ if(istype(W, /obj/item/crowbar))
+ user.visible_message("[user.name] removes the electronics from [src.name].",\
+ "You start prying out the circuit...")
+ W.play_tool_sound(src)
+ if (W.use_tool(src, user, 20))
+ if (buildstage == 1)
+ to_chat(user, "You remove the air alarm electronics.")
+ new /obj/item/electronics/airalarm( src.loc )
+ playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
+ buildstage = 0
+ update_icon()
+ return
+
+ if(istype(W, /obj/item/stack/cable_coil))
+ var/obj/item/stack/cable_coil/cable = W
+ if(cable.get_amount() < 5)
+ to_chat(user, "You need five lengths of cable to wire the air alarm!")
+ return
+ user.visible_message("[user.name] wires the air alarm.", \
+ "You start wiring the air alarm...")
+ if (do_after(user, 20, target = src))
+ if (cable.get_amount() >= 5 && buildstage == 1)
+ cable.use(5)
+ to_chat(user, "You wire the air alarm.")
+ wires.repair()
+ aidisabled = 0
+ locked = FALSE
+ mode = 1
+ shorted = 0
+ post_alert(0)
+ buildstage = 2
+ update_icon()
+ return
+ if(0)
+ if(istype(W, /obj/item/electronics/airalarm))
+ if(user.temporarilyRemoveItemFromInventory(W))
+ to_chat(user, "You insert the circuit.")
+ buildstage = 1
+ update_icon()
+ qdel(W)
+ return
+
+ if(istype(W, /obj/item/electroadaptive_pseudocircuit))
+ var/obj/item/electroadaptive_pseudocircuit/P = W
+ if(!P.adapt_circuit(user, 25))
+ return
+ user.visible_message("[user] fabricates a circuit and places it into [src].", \
+ "You adapt an air alarm circuit and slot it into the assembly.")
+ buildstage = 1
+ update_icon()
+ return
+
+ if(istype(W, /obj/item/wrench))
+ to_chat(user, "You detach \the [src] from the wall.")
+ W.play_tool_sound(src)
+ new /obj/item/wallframe/airalarm( user.loc )
+ qdel(src)
+ return
+
+ return ..()
+
+/obj/machinery/airalarm/AltClick(mob/user)
+ ..()
+ if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc))
+ return
+ else
+ togglelock(user)
+
+/obj/machinery/airalarm/proc/togglelock(mob/living/user)
+ if(stat & (NOPOWER|BROKEN))
+ to_chat(user, "It does nothing!")
+ else
+ if(src.allowed(usr) && !wires.is_cut(WIRE_IDSCAN))
+ locked = !locked
+ updateUsrDialog()
+ to_chat(user, "You [ locked ? "lock" : "unlock"] the air alarm interface.")
+ else
+ to_chat(user, "Access denied.")
+ return
+
+/obj/machinery/airalarm/power_change()
+ ..()
+ if(stat & NOPOWER)
+ set_light(0)
+ update_icon()
+
+/obj/machinery/airalarm/emag_act(mob/user)
+ . = ..()
+ if(obj_flags & EMAGGED)
+ return
+ obj_flags |= EMAGGED
+ visible_message("Sparks fly out of [src]!", "You emag [src], disabling its safeties.")
+ playsound(src, "sparks", 50, 1)
+ return TRUE
+
+/obj/machinery/airalarm/obj_break(damage_flag)
+ ..()
+ update_icon()
+ set_light(0)
+
+/obj/machinery/airalarm/deconstruct(disassembled = TRUE)
+ if(!(flags_1 & NODECONSTRUCT_1))
+ new /obj/item/stack/sheet/metal(loc, 2)
+ var/obj/item/I = new /obj/item/electronics/airalarm(loc)
+ if(!disassembled)
+ I.obj_integrity = I.max_integrity * 0.5
+ new /obj/item/stack/cable_coil(loc, 3)
+ qdel(src)
+
+#undef AALARM_MODE_SCRUBBING
+#undef AALARM_MODE_VENTING
+#undef AALARM_MODE_PANIC
+#undef AALARM_MODE_REPLACEMENT
+#undef AALARM_MODE_OFF
+#undef AALARM_MODE_FLOOD
+#undef AALARM_MODE_SIPHON
+#undef AALARM_MODE_CONTAMINATED
+#undef AALARM_MODE_REFILL
+#undef AALARM_REPORT_TIMEOUT
diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm
index fcfdd7c455..84f08197b4 100644
--- a/code/modules/awaymissions/capture_the_flag.dm
+++ b/code/modules/awaymissions/capture_the_flag.dm
@@ -24,7 +24,6 @@
armour_penetration = 1000
resistance_flags = INDESTRUCTIBLE
anchored = TRUE
- item_flags = SLOWS_WHILE_IN_HAND
var/team = WHITE_TEAM
var/reset_cooldown = 0
var/anyonecanpickup = TRUE
diff --git a/code/modules/cargo/bounties/engineering.dm b/code/modules/cargo/bounties/engineering.dm
index e10d48f3bf..cf2cd7d93c 100644
--- a/code/modules/cargo/bounties/engineering.dm
+++ b/code/modules/cargo/bounties/engineering.dm
@@ -14,10 +14,10 @@
return FALSE
return T.air_contents.gases[gas_type] >= moles_required
-/datum/bounty/item/engineering/gas/nitryl_tank
- name = "Full Tank of Nitryl"
- description = "The non-human staff of Station 88 has been volunteered to test performance enhancing drugs. Ship them a tank full of Nitryl so they can get started."
- gas_type = /datum/gas/nitryl
+//datum/bounty/item/engineering/gas/nitryl_tank
+// name = "Full Tank of Nitryl"
+// description = "The non-human staff of Station 88 has been volunteered to test performance enhancing drugs. Ship them a tank full of Nitryl so they can get started."
+// gas_type = /datum/gas/nitryl
/datum/bounty/item/engineering/gas/tritium_tank
name = "Full Tank of Tritium"
@@ -37,6 +37,55 @@
required_count = 10 //easy to make
wanted_types = list(/obj/machinery/portable_atmospherics/canister)
+/datum/bounty/item/engineering/microwave
+ name = "Microwaves"
+ description = "Due to a shortage of microwaves, our chefs are incapable of keeping up with our sheer volume of orders. We need at least three microwaves to keep up with our crew's dietary habits."
+ reward = 2000
+ required_count = 3
+ wanted_types = list(/obj/machinery/microwave)
+
+/datum/bounty/item/engineering/hydroponicstrays
+ name = "Hydroponics Tray"
+ description = "The garden has become a hot spot of late, they need a few more hydroponics tray to grow more flowers."
+ reward = 2500
+ required_count = 5
+ wanted_types = list(/obj/machinery/hydroponics)
+
+/datum/bounty/item/engineering/rcd
+ name = "Spare RCD"
+ description = "Construction and repairs to are shuttles are going slowly. As it turns out, we're a little short on RCDs, can you send us a few?"
+ reward = 2500
+ required_count = 3
+ wanted_types = list(/obj/item/construction/rcd)
+
+/datum/bounty/item/engineering/rpd
+ name = "Spare RPD"
+ description = "Our Atmospheric Technicians are still living in the past, relying on stationary pipe dispensers to produce the pipes necessary to accomplish their strenuous tasks. They could use an upgrade. Could you send us some Rapid Pipe Dispensers?"
+ reward = 3000
+ required_count = 3
+ wanted_types = list(/obj/item/pipe_dispenser)
+
+/datum/bounty/item/engineering/heaters
+ name = "Space Heaters"
+ description = "The kitchen freezer was left open and now the whole place is frozen solid! We need a few space heaters to warm it back up before anyone gets hungry."
+ reward = 3000
+ required_count = 5
+ wanted_types = list(/obj/machinery/space_heater)
+
+/datum/bounty/item/engineering/arcadetrail
+ name = "Orion Trail Arcade Games"
+ description = "The staff have nothing to do when off-work. Can you send us some Orion Trail games to play?"
+ reward = 3000
+ required_count = 5
+ wanted_types = list(/obj/machinery/computer/arcade/orion_trail)
+
+/datum/bounty/item/engineering/arcadebattle
+ name = "Battle Arcade Games"
+ description = "The staff have nothing to do when off-work. Can you send us some Battle Arcade games to play?"
+ reward = 3000
+ required_count = 5
+ wanted_types = list(/obj/machinery/computer/arcade/battle)
+
/datum/bounty/item/engineering/energy_ball
name = "Contained Tesla Ball"
description = "Station 24 is being overrun by hordes of angry Mothpeople. They are requesting the ultimate bug zapper."
diff --git a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm
index b5b9a616d0..1a607b4b96 100644
--- a/code/modules/cargo/console.dm
+++ b/code/modules/cargo/console.dm
@@ -36,6 +36,7 @@
cat |= EXPORT_EMAG
/obj/machinery/computer/cargo/emag_act(mob/user)
+ . = ..()
if(obj_flags & EMAGGED)
return
user.visible_message("[user] swipes a suspicious card through [src]!",
@@ -48,6 +49,8 @@
var/obj/item/circuitboard/computer/cargo/board = circuit
board.contraband = TRUE
board.obj_flags |= EMAGGED
+ req_access = list()
+ return TRUE
/obj/machinery/computer/cargo/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm
index 5288c27ff6..0097346a34 100644
--- a/code/modules/cargo/expressconsole.dm
+++ b/code/modules/cargo/expressconsole.dm
@@ -54,6 +54,7 @@
..()
/obj/machinery/computer/cargo/express/emag_act(mob/living/user)
+ . = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
if(obj_flags & EMAGGED)
return
user.visible_message("[user] swipes a suspicious card through [src]!",
@@ -63,6 +64,8 @@
var/obj/item/circuitboard/computer/cargo/board = circuit
board.obj_flags |= EMAGGED
packin_up()
+ req_access = list()
+ return TRUE
/obj/machinery/computer/cargo/express/proc/packin_up() // oh shit, I'm sorry
meme_pack_data = list() // sorry for what?
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index 5656287c52..1087f1ebb5 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -1699,7 +1699,7 @@
/datum/supply_pack/service/janitor/janpremium
name = "Janitor Premium Supplies"
desc = "Do to the union for better supplies, we have desided to make a deal for you, In this crate you can get a brand new chem, Drying Angent this stuff is the work of slimes or magic! This crate also contains a rag to test out the Drying Angent magic, three wet floor signs, and some spare bottles of ammonia."
- cost = 3000
+ cost = 1750
access = ACCESS_JANITOR
contains = list(/obj/item/caution,
/obj/item/caution,
@@ -1707,9 +1707,20 @@
/obj/item/reagent_containers/rag,
/obj/item/reagent_containers/glass/bottle/ammonia,
/obj/item/reagent_containers/glass/bottle/ammonia,
+ /obj/item/reagent_containers/glass/bottle/ammonia,
/obj/item/reagent_containers/spray/drying_agent)
crate_name = "janitor backpack crate"
+/datum/supply_pack/service/janitor/janpimp
+ name = "Custodial Cruiser"
+ desc = "Clown steal your ride? Assistant lock it in the dorms? Order a new one and get back to cleaning in style!"
+ cost = 3000
+ access = ACCESS_JANITOR
+ contains = list(/obj/vehicle/ridden/janicart,
+ /obj/item/key/janitor)
+ crate_name = "janitor ride crate"
+ crate_type = /obj/structure/closet/crate/large
+
/datum/supply_pack/service/mule
name = "MULEbot Crate"
desc = "Pink-haired Quartermaster not doing her job? Replace her with this tireless worker, today!"
diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm
index 7216b73af6..a54584d6cc 100644
--- a/code/modules/client/client_defines.dm
+++ b/code/modules/client/client_defines.dm
@@ -75,3 +75,8 @@
var/datum/player_details/player_details //these persist between logins/logouts during the same round.
var/list/char_render_holders //Should only be a key-value list of north/south/east/west = obj/screen.
+
+ var/client_keysend_amount = 0
+ var/next_keysend_reset = 0
+ var/next_keysend_trip_reset = 0
+ var/keysend_tripped = FALSE
\ No newline at end of file
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index 06f23574e1..5442fcb932 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -817,6 +817,10 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
var/file = GLOB.vox_sounds[name]
Export("##action=load_rsc", file)
stoplag()
+ for (var/name in GLOB.vox_sounds_male)
+ var/file = GLOB.vox_sounds_male[name]
+ Export("##action=load_rsc", file)
+ stoplag()
#endif
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index cd22685952..88fd142c1e 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -72,11 +72,11 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/gender = MALE //gender of character (well duh)
var/age = 30 //age of character
var/underwear = "Nude" //underwear type
- var/undie_color = "#FFFFFF"
+ var/undie_color = "FFF"
var/undershirt = "Nude" //undershirt type
- var/shirt_color = "#FFFFFF"
+ var/shirt_color = "FFF"
var/socks = "Nude" //socks type
- var/socks_color = "#FFFFFF"
+ var/socks_color = "FFF"
var/backbag = DBACKPACK //backpack type
var/jumpsuit_style = PREF_SUIT //suit/skirt
var/hair_style = "Bald" //Hair type
@@ -144,6 +144,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
"breasts_size" = "C",
"breasts_shape" = "Pair",
"breasts_fluid" = "milk",
+ "breasts_producing" = FALSE,
"has_vag" = FALSE,
"vag_shape" = "Human",
"vag_color" = "fff",
@@ -680,13 +681,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "Clothing & Equipment"
dat += "Underwear:[underwear]"
if(UNDIE_COLORABLE(GLOB.underwear_list[underwear]))
- dat += "Underwear Color:[undie_color]"
+ dat += "Underwear Color: Change "
dat += "Undershirt:[undershirt]"
if(UNDIE_COLORABLE(GLOB.undershirt_list[undershirt]))
- dat += "Undershirt Color:[shirt_color]"
+ dat += "Undershirt Color: Change "
dat += "Socks:[socks]"
if(UNDIE_COLORABLE(GLOB.socks_list[socks]))
- dat += "Socks Color:[socks_color]"
+ dat += "Socks Color: Change "
dat += "Backpack:[backbag]"
dat += "Jumpsuit: [jumpsuit_style] "
dat += "Uplink Location:[uplink_spawn_loc]"
@@ -743,6 +744,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += " Change "
dat += "Cup Size:[features["breasts_size"]]"
dat += "Breast Shape:[features["breasts_shape"]]"
+ dat += "Lactates:[features["breasts_producing"] == TRUE ? "Yes" : "No"]"
dat += ""
dat += ""
dat += " "
@@ -796,6 +798,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "Voracious MediHound sleepers: [(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"] "
dat += "Hear Vore Sounds: [(cit_toggles & EATING_NOISES) ? "Yes" : "No"] "
dat += "Hear Vore Digestion Sounds: [(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"] "
+ dat += "Lewdchem:[lewdchem == TRUE ? "Enabled" : "Disabled"] "
dat += "Widescreen: [widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled (15x15)"] "
dat += "Auto stand: [autostand ? "Enabled" : "Disabled"] "
dat += "Screen Shake: [(screenshake==100) ? "Full" : ((screenshake==0) ? "None" : "[screenshake]")] "
@@ -916,11 +919,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += " | Description |
"
for(var/j in GLOB.loadout_items[gear_tab])
var/datum/gear/gear = GLOB.loadout_items[gear_tab][j]
- var/donoritem
- if(gear.ckeywhitelist && gear.ckeywhitelist.len)
- donoritem = TRUE
- if(!(user.ckey in gear.ckeywhitelist))
- continue
+ var/donoritem = gear.donoritem
+ if(donoritem && !gear.donator_ckey_check(user.ckey))
+ continue
var/class_link = ""
if(gear.type in chosen_gear)
class_link = "style='white-space:normal;' class='linkOn' href='?_src_=prefs;preference=gear;toggle_gear_path=[html_encode(j)];toggle_gear=0'"
@@ -1533,7 +1534,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("undie_color")
var/n_undie_color = input(user, "Choose your underwear's color.", "Character Preference", undie_color) as color|null
if(n_undie_color)
- undie_color = sanitize_hexcolor(n_undie_color, include_crunch= TRUE)
+ undie_color = sanitize_hexcolor(n_undie_color)
if("undershirt")
var/new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in GLOB.undershirt_list
@@ -1543,7 +1544,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("shirt_color")
var/n_shirt_color = input(user, "Choose your undershirt's color.", "Character Preference", shirt_color) as color|null
if(n_shirt_color)
- shirt_color = sanitize_hexcolor(n_shirt_color, include_crunch= TRUE)
+ shirt_color = sanitize_hexcolor(n_shirt_color)
if("socks")
var/new_socks = input(user, "Choose your character's socks:", "Character Preference") as null|anything in GLOB.socks_list
@@ -1553,7 +1554,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("socks_color")
var/n_socks_color = input(user, "Choose your socks' color.", "Character Preference", socks_color) as color|null
if(n_socks_color)
- socks_color = sanitize_hexcolor(n_socks_color, include_crunch= TRUE)
+ socks_color = sanitize_hexcolor(n_socks_color)
if("eyes")
var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference","#"+eye_color) as color|null
@@ -2037,6 +2038,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["genitals_use_skintone"] = !features["genitals_use_skintone"]
if("arousable")
arousable = !arousable
+ if("lewdchem")
+ lewdchem = !lewdchem
if("has_cock")
features["has_cock"] = !features["has_cock"]
if(features["has_cock"] == FALSE)
@@ -2053,6 +2056,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["eggsack_internal"] = !features["eggsack_internal"]
if("has_breasts")
features["has_breasts"] = !features["has_breasts"]
+ if(features["has_breasts"] == FALSE)
+ features["breasts_producing"] = FALSE
+ if("breasts_producing")
+ features["breasts_producing"] = !features["breasts_producing"]
if("has_vag")
features["has_vag"] = !features["has_vag"]
if(features["has_vag"] == FALSE)
@@ -2236,7 +2243,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(!is_loadout_slot_available(G.category))
to_chat(user, "