"
for(var/A in get_region_accesses(i))
- if(A in modify.access)
+ if(A in inserted_modify_id.access)
accesses += "[replacetext(get_access_desc(A), " ", " ")] "
else
accesses += "[replacetext(get_access_desc(A), " ", " ")] "
@@ -353,52 +392,66 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
usr.set_machine(src)
switch(href_list["choice"])
- if ("modify")
- eject_id_modify(usr)
- if ("scan")
- eject_id_scan(usr)
+ if ("inserted_modify_id")
+ if (inserted_modify_id)
+ if(id_eject(usr, inserted_modify_id))
+ inserted_modify_id = null
+ else
+ var/mob/M = usr
+ var/obj/item/card/id/I = M.get_idcard(TRUE)
+ if(id_insert(usr, I, inserted_modify_id))
+ inserted_modify_id = I
+ if ("inserted_scan_id")
+ if (inserted_scan_id)
+ if(id_eject(usr, inserted_scan_id))
+ inserted_scan_id = null
+ else
+ var/mob/M = usr
+ var/obj/item/card/id/I = M.get_idcard(TRUE)
+ if(id_insert(usr, I, inserted_scan_id))
+ inserted_scan_id = I
if ("auth")
- if ((!( authenticated ) && (scan || issilicon(usr)) && (modify || mode)))
- if (check_access(scan))
+ if ((!( authenticated ) && (inserted_scan_id || issilicon(usr)) && (inserted_modify_id || mode)))
+ if (check_access(inserted_scan_id))
region_access = list()
head_subordinates = list()
- if(ACCESS_CHANGE_IDS in scan.access)
+ if(ACCESS_CHANGE_IDS in inserted_scan_id.access)
if(target_dept)
head_subordinates = get_all_jobs()
region_access |= target_dept
authenticated = 1
else
authenticated = 2
- playsound(src, 'sound/machines/terminal_on.ogg', 50, 0)
+ playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
else
- if((ACCESS_HOP in scan.access) && ((target_dept==1) || !target_dept))
+ if((ACCESS_HOP in inserted_scan_id.access) && ((target_dept==1) || !target_dept))
region_access |= 1
get_subordinates("Head of Personnel")
- if((ACCESS_HOS in scan.access) && ((target_dept==2) || !target_dept))
+ if((ACCESS_HOS in inserted_scan_id.access) && ((target_dept==2) || !target_dept))
region_access |= 2
get_subordinates("Head of Security")
- if((ACCESS_CMO in scan.access) && ((target_dept==3) || !target_dept))
+ if((ACCESS_CMO in inserted_scan_id.access) && ((target_dept==3) || !target_dept))
region_access |= 3
get_subordinates("Chief Medical Officer")
- if((ACCESS_RD in scan.access) && ((target_dept==4) || !target_dept))
+ if((ACCESS_RD in inserted_scan_id.access) && ((target_dept==4) || !target_dept))
region_access |= 4
get_subordinates("Research Director")
- if((ACCESS_CE in scan.access) && ((target_dept==5) || !target_dept))
+ if((ACCESS_CE in inserted_scan_id.access) && ((target_dept==5) || !target_dept))
region_access |= 5
get_subordinates("Chief Engineer")
- if((ACCESS_QM in scan.access) && ((target_dept==6) || !target_dept))
+ if((ACCESS_QM in inserted_scan_id.access) && ((target_dept==6) || !target_dept))
region_access |= 6
get_subordinates("Quartermaster")
if(region_access)
authenticated = 1
- else if ((!( authenticated ) && issilicon(usr)) && (!modify))
+ else if ((!( authenticated ) && issilicon(usr)) && (!inserted_modify_id))
to_chat(usr, "You can't modify an ID without an ID inserted to modify! Once one is in the modify slot on the computer, you can log in.")
if ("logout")
region_access = null
head_subordinates = null
authenticated = 0
- playsound(src, 'sound/machines/terminal_off.ogg', 50, 0)
+ playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
if("access")
if(href_list["allowed"])
@@ -406,20 +459,20 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
var/access_type = text2num(href_list["access_target"])
var/access_allowed = text2num(href_list["allowed"])
if(access_type in (istype(src, /obj/machinery/computer/card/centcom)?get_all_centcom_access() : get_all_accesses()))
- modify.access -= access_type
+ inserted_modify_id.access -= access_type
if(access_allowed == 1)
- modify.access += access_type
- playsound(src, "terminal_type", 50, 0)
+ inserted_modify_id.access += access_type
+ playsound(src, "terminal_type", 50, FALSE)
if ("assign")
if (authenticated == 2)
var/t1 = href_list["assign_target"]
if(t1 == "Custom")
- var/newJob = reject_bad_text(input("Enter a custom job assignment.", "Assignment", modify ? modify.assignment : "Unassigned"), MAX_NAME_LEN)
+ var/newJob = reject_bad_text(input("Enter a custom job assignment.", "Assignment", inserted_modify_id ? inserted_modify_id.assignment : "Unassigned"), MAX_NAME_LEN)
if(newJob)
t1 = newJob
else if(t1 == "Unassigned")
- modify.access -= get_all_accesses()
+ inserted_modify_id.access -= get_all_accesses()
else
var/datum/job/jobdatum
@@ -434,24 +487,24 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
updateUsrDialog()
return
- modify.access = ( istype(src, /obj/machinery/computer/card/centcom) ? get_centcom_access(t1) : jobdatum.get_access() )
- if (modify)
- modify.assignment = t1
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ inserted_modify_id.access = ( istype(src, /obj/machinery/computer/card/centcom) ? get_centcom_access(t1) : jobdatum.get_access() )
+ if (inserted_modify_id)
+ inserted_modify_id.assignment = t1
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
if ("demote")
- if(modify.assignment in head_subordinates || modify.assignment == "Assistant")
- modify.assignment = "Unassigned"
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ if(inserted_modify_id.assignment in head_subordinates || inserted_modify_id.assignment == "Assistant")
+ inserted_modify_id.assignment = "Unassigned"
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
else
to_chat(usr, "You are not authorized to demote this position.")
if ("reg")
if (authenticated)
- var/t2 = modify
- if ((authenticated && modify == t2 && (in_range(src, usr) || issilicon(usr)) && isturf(loc)))
+ var/t2 = inserted_modify_id
+ if ((authenticated && inserted_modify_id == t2 && (in_range(src, usr) || issilicon(usr)) && isturf(loc)))
var/newName = reject_bad_name(href_list["reg"])
if(newName)
- modify.registered_name = newName
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ inserted_modify_id.registered_name = newName
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
else
to_chat(usr, "Invalid name entered.")
updateUsrDialog()
@@ -462,11 +515,11 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
if("return")
//DISPLAY MAIN MENU
mode = 3;
- playsound(src, "terminal_type", 25, 0)
+ playsound(src, "terminal_type", 25, FALSE)
if("make_job_available")
// MAKE ANOTHER JOB POSITION AVAILABLE FOR LATE JOINERS
- if(scan && (ACCESS_CHANGE_IDS in scan.access) && !target_dept)
+ if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept)
var/edit_job_target = href_list["job"]
var/datum/job/j = SSjob.GetJob(edit_job_target)
if(!j)
@@ -479,11 +532,11 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
GLOB.time_last_changed_position = world.time / 10
j.total_positions++
opened_positions[edit_job_target]++
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
if("make_job_unavailable")
// MAKE JOB POSITION UNAVAILABLE FOR LATE JOINERS
- if(scan && (ACCESS_CHANGE_IDS in scan.access) && !target_dept)
+ if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept)
var/edit_job_target = href_list["job"]
var/datum/job/j = SSjob.GetJob(edit_job_target)
if(!j)
@@ -497,11 +550,11 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
GLOB.time_last_changed_position = world.time / 10
j.total_positions--
opened_positions[edit_job_target]--
- playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, FALSE)
if ("prioritize_job")
// TOGGLE WHETHER JOB APPEARS AS PRIORITIZED IN THE LOBBY
- if(scan && (ACCESS_CHANGE_IDS in scan.access) && !target_dept)
+ if(inserted_scan_id && (ACCESS_CHANGE_IDS in inserted_scan_id.access) && !target_dept)
var/priority_target = href_list["job"]
var/datum/job/j = SSjob.GetJob(priority_target)
if(!j)
@@ -518,7 +571,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
else
SSjob.prioritized_jobs += j
to_chat(usr, "[j.title] has been successfully [priority ? "prioritized" : "unprioritized"]. Potential employees will notice your request.")
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
if ("print")
if (!( printing ))
@@ -531,59 +584,9 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
P.info = t1
P.name = "paper- 'Crew Manifest'"
printing = null
- playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
- if (modify)
- modify.update_label()
- updateUsrDialog()
-
-/obj/machinery/computer/card/AltClick(mob/user)
- if(!user.canUseTopic(src, !issilicon(user)) || !is_operational())
- return
- if(scan)
- eject_id_scan(user)
- if(modify)
- eject_id_modify(user)
-
-/obj/machinery/computer/card/proc/eject_id_scan(mob/user)
- if(scan)
- scan.forceMove(drop_location())
- if(!issilicon(user) && Adjacent(user))
- user.put_in_hands(scan)
- playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
- scan = null
- else //switching the ID with the one you're holding
- if(issilicon(user) || !Adjacent(user))
- return
- var/obj/item/I = user.get_active_held_item()
- if(istype(I, /obj/item/card/id))
- if(!user.transferItemToLoc(I,src))
- return
- playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
- scan = I
- authenticated = FALSE
- updateUsrDialog()
-
-/obj/machinery/computer/card/proc/eject_id_modify(mob/user)
- if(modify)
- GLOB.data_core.manifest_modify(modify.registered_name, modify.assignment)
- modify.update_label()
- modify.forceMove(drop_location())
- if(!issilicon(user) && Adjacent(user))
- user.put_in_hands(modify)
- playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
- modify = null
- region_access = null
- head_subordinates = null
- else //switching the ID with the one you're holding
- if(issilicon(user) || !Adjacent(user))
- return
- var/obj/item/I = user.get_active_held_item()
- if(istype(I, /obj/item/card/id))
- if (!user.transferItemToLoc(I,src))
- return
- playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, 0)
- modify = I
- authenticated = FALSE
+ playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE)
+ if (inserted_modify_id)
+ inserted_modify_id.update_label()
updateUsrDialog()
/obj/machinery/computer/card/proc/get_subordinates(rank)
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index 5cbd2d8975..43cfbdb33b 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -298,13 +298,15 @@
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
say("Initiating scan...")
-
+ var/prev_locked = scanner.locked
+ scanner.locked = TRUE
spawn(20)
src.scan_occupant(scanner.occupant)
loading = 0
src.updateUsrDialog()
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+ scanner.locked = prev_locked
//No locking an open scanner.
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index 557f2f0636..f3612078d6 100755
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -335,7 +335,7 @@
Nuke_request(input, usr)
to_chat(usr, "Request sent.")
usr.log_message("has requested the nuclear codes from CentCom", LOG_SAY)
- priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested",'sound/ai/commandreport.ogg')
+ priority_announce("The codes for the on-station nuclear self-destruct have been requested by [usr]. Confirmation or denial of this request will be sent shortly.", "Nuclear Self Destruct Codes Requested","commandreport")
CM.lastTimeUsed = world.time
diff --git a/code/game/machinery/computer/gulag_teleporter.dm b/code/game/machinery/computer/gulag_teleporter.dm
deleted file mode 100644
index 68cbf03f03..0000000000
--- a/code/game/machinery/computer/gulag_teleporter.dm
+++ /dev/null
@@ -1,163 +0,0 @@
-//computer that handle the points and teleports the prisoner
-/obj/machinery/computer/gulag_teleporter_computer
- name = "labor camp teleporter console"
- desc = "Used to send criminals to the Labor Camp."
- icon_screen = "explosive"
- icon_keyboard = "security_key"
- req_access = list(ACCESS_ARMORY)
- circuit = /obj/item/circuitboard/computer/gulag_teleporter_console
- var/default_goal = 200
- var/obj/item/card/id/prisoner/id = null
- var/obj/machinery/gulag_teleporter/teleporter = null
- var/obj/structure/gulag_beacon/beacon = null
- var/mob/living/carbon/human/prisoner = null
- var/datum/data/record/temporary_record = null
-
- light_color = LIGHT_COLOR_RED
-
-/obj/machinery/computer/gulag_teleporter_computer/Initialize()
- . = ..()
- scan_machinery()
-
-/obj/machinery/computer/gulag_teleporter_computer/Destroy()
- if(id)
- id.forceMove(get_turf(src))
- return ..()
-
-/obj/machinery/computer/gulag_teleporter_computer/attackby(obj/item/W, mob/user)
- if(istype(W, /obj/item/card/id/prisoner))
- if(!id)
- if (!user.transferItemToLoc(W,src))
- return
- id = W
- to_chat(user, "You insert [W].")
- return
- else
- to_chat(user, "There's an ID inserted already.")
- return ..()
-
-/obj/machinery/computer/gulag_teleporter_computer/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, "gulag_console", name, 455, 440, master_ui, state)
- ui.open()
-
-/obj/machinery/computer/gulag_teleporter_computer/ui_data(mob/user)
- var/list/data = list()
-
- var/list/prisoner_list = list()
- var/can_teleport = FALSE
-
- if(teleporter && (teleporter.occupant && ishuman(teleporter.occupant)))
- prisoner = teleporter.occupant
- prisoner_list["name"] = prisoner.real_name
- if(id)
- can_teleport = TRUE
- if(!isnull(GLOB.data_core.general))
- for(var/r in GLOB.data_core.security)
- var/datum/data/record/R = r
- if(R.fields["name"] == prisoner_list["name"])
- temporary_record = R
- prisoner_list["crimstat"] = temporary_record.fields["criminal"]
-
- data["prisoner"] = prisoner_list
-
- if(teleporter)
- data["teleporter"] = teleporter
- data["teleporter_location"] = "([teleporter.x], [teleporter.y], [teleporter.z])"
- data["teleporter_lock"] = teleporter.locked
- data["teleporter_state_open"] = teleporter.state_open
- if(beacon)
- data["beacon"] = beacon
- data["beacon_location"] = "([beacon.x], [beacon.y], [beacon.z])"
- if(id)
- data["id"] = id
- data["id_name"] = id.registered_name
- data["goal"] = id.goal
- data["can_teleport"] = can_teleport
-
- return data
-
-/obj/machinery/computer/gulag_teleporter_computer/ui_act(action, list/params)
- if(..())
- return
- if(!allowed(usr))
- to_chat(usr, "Access denied.")
- return
- switch(action)
- if("scan_teleporter")
- teleporter = findteleporter()
- if("scan_beacon")
- beacon = findbeacon()
- if("handle_id")
- if(id)
- usr.put_in_hands(id)
- id = null
- else
- var/obj/item/I = usr.is_holding_item_of_type(/obj/item/card/id/prisoner)
- if(I)
- if(!usr.transferItemToLoc(I, src))
- return
- id = I
- if("set_goal")
- var/new_goal = input("Set the amount of points:", "Points", id.goal) as num|null
- if(!isnum(new_goal))
- return
- if(!new_goal)
- new_goal = default_goal
- if (new_goal > 1000)
- to_chat(usr, "The entered amount of points is too large. Points have instead been set to the maximum allowed amount.")
- id.goal = CLAMP(new_goal, 0, 1000) //maximum 1000 points
- if("toggle_open")
- if(teleporter.locked)
- to_chat(usr, "The teleporter is locked")
- return
- teleporter.toggle_open()
- if("teleporter_lock")
- if(teleporter.state_open)
- to_chat(usr, "Close the teleporter before locking!")
- return
- teleporter.locked = !teleporter.locked
- if("teleport")
- if(!teleporter || !beacon)
- return
- addtimer(CALLBACK(src, .proc/teleport, usr), 5)
-
-/obj/machinery/computer/gulag_teleporter_computer/proc/scan_machinery()
- teleporter = findteleporter()
- beacon = findbeacon()
-
-/obj/machinery/computer/gulag_teleporter_computer/proc/findteleporter()
- var/obj/machinery/gulag_teleporter/teleporterf = null
-
- for(var/direction in GLOB.cardinals)
- teleporterf = locate(/obj/machinery/gulag_teleporter, get_step(src, direction))
- if(teleporterf && teleporterf.is_operational())
- return teleporterf
-
-/obj/machinery/computer/gulag_teleporter_computer/proc/findbeacon()
- return locate(/obj/structure/gulag_beacon)
-
-/obj/machinery/computer/gulag_teleporter_computer/proc/teleport(mob/user)
- if(!id) //incase the ID was removed after the transfer timer was set.
- say("Warning: Unable to transfer prisoner without a valid Prisoner ID inserted!")
- return
- var/id_goal_not_set
- if(!id.goal)
- id_goal_not_set = TRUE
- id.goal = default_goal
- say("[id]'s ID card goal defaulting to [id.goal] points.")
- log_game("[key_name(user)] teleported [key_name(prisoner)] to the Labor Camp [COORD(beacon)] for [id_goal_not_set ? "default goal of ":""][id.goal] points.")
- teleporter.handle_prisoner(id, temporary_record)
- playsound(src, 'sound/weapons/emitter.ogg', 50, 1)
- prisoner.forceMove(get_turf(beacon))
- prisoner.Knockdown(40) // small travel dizziness
- to_chat(prisoner, "The teleportation makes you a little dizzy.")
- new /obj/effect/particle_effect/sparks(get_turf(prisoner))
- playsound(src, "sparks", 50, 1)
- if(teleporter.locked)
- teleporter.locked = FALSE
- teleporter.toggle_open()
- id = null
- temporary_record = null
diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm
index d4fe3e27a2..33de8bfce2 100644
--- a/code/game/machinery/computer/medical.dm
+++ b/code/game/machinery/computer/medical.dm
@@ -22,12 +22,6 @@
/obj/machinery/computer/med_data/syndie
icon_keyboard = "syndie_key"
-/obj/machinery/computer/med_data/attackby(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/card/id))
- id_insert_scan(user)
- else
- return ..()
-
/obj/machinery/computer/med_data/ui_interact(mob/user)
. = ..()
if(isliving(user))
@@ -484,7 +478,7 @@
var/counter = 1
while(active2.fields[text("com_[]", counter)])
counter++
- active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], [] []", authenticated, rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
+ active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], [] []", authenticated, rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1)
else if(href_list["del_c"])
if((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])]))
@@ -575,7 +569,7 @@
if(user)
if(message)
if(authenticated)
- if(user.canUseTopic(src, BE_CLOSE))
+ if(user.canUseTopic(src, !issilicon(user)))
if(!record1 || record1 == active1)
if(!record2 || record2 == active2)
return 1
diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm
index 1823e34100..c9f2f28ab1 100644
--- a/code/game/machinery/computer/security.dm
+++ b/code/game/machinery/computer/security.dm
@@ -35,7 +35,8 @@
//Someone needs to break down the dat += into chunks instead of long ass lines.
/obj/machinery/computer/secure_data/ui_interact(mob/user)
. = ..()
- playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
+ if(isliving(user))
+ playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
if(src.z > 6)
to_chat(user, "Unable to establish a connection: \black You're too far away from the station!")
return
@@ -455,7 +456,7 @@ What a mess.*/
var/counter = 1
while(active2.fields[text("com_[]", counter)])
counter++
- active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], [] []", src.authenticated, src.rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
+ active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [] [], [] []", src.authenticated, src.rank, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1)
if("Delete Record (ALL)")
if(active1)
@@ -801,7 +802,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, BE_CLOSE))
+ if(user.canUseTopic(src, !issilicon(user)))
if(!trim(message1))
return 0
if(!record1 || record1 == active1)
diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm
index 692bc8f038..67407d220e 100644
--- a/code/game/machinery/computer/telecrystalconsoles.dm
+++ b/code/game/machinery/computer/telecrystalconsoles.dm
@@ -33,7 +33,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
if(uplinkholder)
to_chat(user, "[src] already has an uplink in it.")
return
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, I)
+ var/datum/component/uplink/hidden_uplink = I.GetComponent(/datum/component/uplink)
if(hidden_uplink)
if(!user.transferItemToLoc(I, src))
return
@@ -57,7 +57,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(amt, addLog = 1)
if(uplinkholder && linkedboss)
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
+ var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
if(amt < 0)
linkedboss.storedcrystals += hidden_uplink.telecrystals
if(addLog)
@@ -71,7 +71,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(amt, addLog = 1)
if(uplinkholder && linkedboss)
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
+ var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
if(amt < 0)
hidden_uplink.telecrystals += linkedboss.storedcrystals
if(addLog)
@@ -94,7 +94,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
dat += "No linked management consoles detected. Scan for uplink stations using the management console.
"
if(uplinkholder)
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, uplinkholder)
+ var/datum/component/uplink/hidden_uplink = uplinkholder.GetComponent(/datum/component/uplink)
dat += "[hidden_uplink.telecrystals] telecrystals remain in this uplink. "
if(linkedboss)
dat += "Donate TC: 1 | 5 | All"
@@ -170,7 +170,7 @@ GLOBAL_LIST_INIT(possible_uplinker_IDs, list("Alfa","Bravo","Charlie","Delta","E
for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
dat += "[A.name] | "
if(A.uplinkholder)
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, A.uplinkholder)
+ var/datum/component/uplink/hidden_uplink = A.uplinkholder.GetComponent(/datum/component/uplink)
dat += "[hidden_uplink.telecrystals] telecrystals."
if(storedcrystals)
dat+= " Add TC: 1 | 5 | 10 | All"
diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm
index e50eeb8619..b5869ef36b 100644
--- a/code/game/machinery/computer/teleporter.dm
+++ b/code/game/machinery/computer/teleporter.dm
@@ -10,6 +10,7 @@
var/obj/machinery/teleport/station/power_station
var/calibrating
var/turf/target
+ var/obj/item/implant/imp_t
/obj/machinery/computer/teleporter/Initialize()
. = ..()
@@ -89,6 +90,7 @@
say("Processing hub calibration to target...")
calibrating = 1
+ power_station.update_icon()
spawn(50 * (3 - power_station.teleporter_hub.accurate)) //Better parts mean faster calibration
calibrating = 0
if(check_hub_connection())
@@ -96,6 +98,7 @@
say("Calibration complete.")
else
say("Error: Unable to detect hub.")
+ power_station.update_icon()
updateDialog()
updateDialog()
@@ -109,6 +112,9 @@
/obj/machinery/computer/teleporter/proc/reset_regime()
target = null
+ if(imp_t)
+ UnregisterSignal(imp_t, COMSIG_IMPLANT_REMOVING)
+ imp_t = null
if(regime_set == "Teleporter")
regime_set = "Gate"
else
@@ -132,10 +138,24 @@
if(M.timeofdeath + 6000 < world.time)
continue
if(is_eligible(M))
- L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = I
+ L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = M
var/desc = input("Please select a location to lock in.", "Locking Computer") as null|anything in L
+ if(!user.canUseTopic(src, !issilicon(user), NO_DEXTERY)) //check if we are still around
+ return
target = L[desc]
+ if(imp_t)
+ UnregisterSignal(imp_t, COMSIG_IMPLANT_REMOVING)
+ imp_t = null
+ if(isliving(target)) //make sure the living mob is still implanted to be a valid target
+ var/mob/living/M = target
+ var/obj/item/implant/tracking/I = locate() in M.implants
+ if(I)
+ RegisterSignal(I, COMSIG_IMPLANT_REMOVING, .proc/untarget_implant)
+ imp_t = I
+ else
+ target = null
+ return
var/turf/T = get_turf(target)
log_game("[key_name(user)] has set the teleporter target to [target] at [AREACOORD(T)]")
@@ -149,6 +169,8 @@
to_chat(user, "No active connected stations located.")
return
var/desc = input("Please select a station to lock in.", "Locking Computer") as null|anything in L
+ if(!user.canUseTopic(src, !issilicon(user), NO_DEXTERY)) //again, check if we are still around
+ return
var/obj/machinery/teleport/station/target_station = L[desc]
if(!target_station || !target_station.teleporter_hub)
return
@@ -164,6 +186,14 @@
target_station.teleporter_console.stat &= ~NOPOWER
target_station.teleporter_console.update_icon()
+/obj/machinery/computer/teleporter/proc/untarget_implant() //untargets from mob the racker was once implanted in to prevent issues.
+ target = null
+ if(power_station)
+ power_station.engaged = FALSE
+ power_station.teleporter_hub?.update_icon()
+ UnregisterSignal(imp_t, COMSIG_IMPLANT_REMOVING)
+ imp_t = null
+
/obj/machinery/computer/teleporter/proc/is_eligible(atom/movable/AM)
var/turf/T = get_turf(AM)
if(!T)
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index b856ee4c94..a9669b4fc5 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -370,16 +370,14 @@
O.find_target()
O.update_explanation_text()
if(!(O.target))
- O.owner.objectives -= O
qdel(O)
- if(mob_occupant.mind && mob_occupant.mind.assigned_role)
+ if(mob_occupant.mind)
//Handle job slot/tater cleanup.
- var/job = mob_occupant.mind.assigned_role
- SSjob.FreeRole(job)
- if(mob_occupant.mind.objectives.len)
- mob_occupant.mind.objectives.Cut()
- mob_occupant.mind.special_role = null
+ if(mob_occupant.mind.assigned_role)
+ var/job = mob_occupant.mind.assigned_role
+ SSjob.FreeRole(job)
+ mob_occupant.mind.special_role = null
// Delete them from datacore.
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 2e78d72b96..eaf8faef12 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -74,7 +74,8 @@
to_chat(user, "You start adding [I] to [src]...")
if(do_after(user, 50, target=src))
W.use(5)
- new /turf/closed/wall/mineral/wood/nonmetal(get_turf(src))
+ var/turf/T = get_turf(src)
+ T.PlaceOnTop(/turf/closed/wall/mineral/wood/nonmetal)
qdel(src)
return
return ..()
diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm
index 8704a4c749..becd89063f 100644
--- a/code/game/machinery/doors/airlock_types.dm
+++ b/code/game/machinery/doors/airlock_types.dm
@@ -249,10 +249,10 @@
return 0
/obj/machinery/door/airlock/plasma/attackby(obj/item/C, mob/user, params)
- if(C.is_hot() > 300)//If the temperature of the object is over 300, then ignite
+ if(C.get_temperature() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma airlock ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(src)]")
log_game("Plasma airlock ignited by [key_name(user)] in [AREACOORD(src)]")
- ignite(C.is_hot())
+ ignite(C.get_temperature())
else
return ..()
@@ -499,7 +499,7 @@
SEND_SOUND(L, sound(pick('sound/hallucinations/turn_around1.ogg','sound/hallucinations/turn_around2.ogg'),0,1,50))
flash_color(L, flash_color="#960000", flash_time=20)
L.Knockdown(40)
- L.throw_at(throwtarget, 5, 1,src)
+ L.throw_at(throwtarget, 5, 1)
return 0
/obj/machinery/door/airlock/cult/proc/conceal()
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index a2da7de29a..3ac386e1fb 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -326,7 +326,7 @@
else //for simple_animals & borgs
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
var/turf/location = get_turf(src)
- //add_blood doesn't work for borgs/xenos, but add_blood_floor does.
+ //add_blood_DNA doesn't work for borgs/xenos, but add_blood_floor does.
if(iscarbon(L))
var/mob/living/carbon/C = L
C.bleed(DOOR_CRUSH_DAMAGE)
diff --git a/code/game/machinery/droneDispenser.dm b/code/game/machinery/droneDispenser.dm
index 7c92c158b3..b121057315 100644
--- a/code/game/machinery/droneDispenser.dm
+++ b/code/game/machinery/droneDispenser.dm
@@ -146,7 +146,7 @@
if((stat & (NOPOWER|BROKEN)) || !anchored)
return
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(!materials.has_materials(using_materials))
return // We require more minerals
@@ -211,7 +211,7 @@
/obj/machinery/droneDispenser/attackby(obj/item/I, mob/living/user)
if(istype(I, /obj/item/crowbar))
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
I.play_tool_sound(src)
to_chat(user, "You retrieve the materials from [src].")
diff --git a/code/game/machinery/exp_cloner.dm b/code/game/machinery/exp_cloner.dm
index b594991a7d..25e5948b51 100644
--- a/code/game/machinery/exp_cloner.dm
+++ b/code/game/machinery/exp_cloner.dm
@@ -42,11 +42,12 @@
icon_state = "pod_1"
//Get the clone body ready
maim_clone(H)
- ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning")
- ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning")
- ADD_TRAIT(H, TRAIT_MUTE, "cloning")
- ADD_TRAIT(H, TRAIT_NOBREATH, "cloning")
- ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning")
+ ADD_TRAIT(H, TRAIT_STABLEHEART, CLONING_POD_TRAIT)
+ ADD_TRAIT(H, TRAIT_STABLELIVER, CLONING_POD_TRAIT)
+ ADD_TRAIT(H, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT)
+ ADD_TRAIT(H, TRAIT_MUTE, CLONING_POD_TRAIT)
+ ADD_TRAIT(H, TRAIT_NOBREATH, CLONING_POD_TRAIT)
+ ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT)
H.Unconscious(80)
var/list/candidates = pollCandidatesForMob("Do you want and agree to play as a [clonename]'s defective clone, respect their character and not engage in ERP without permission from the original?", null, null, null, 100, H, POLL_IGNORE_CLONE)
diff --git a/code/game/machinery/gulag_teleporter.dm b/code/game/machinery/gulag_teleporter.dm
index 6b944f762d..a2d0460d25 100644
--- a/code/game/machinery/gulag_teleporter.dm
+++ b/code/game/machinery/gulag_teleporter.dm
@@ -135,18 +135,19 @@ The console is located at computer/gulag_teleporter.dm
if(linked_reclaimer)
linked_reclaimer.stored_items[occupant] = list()
var/mob/living/mob_occupant = occupant
- for(var/obj/item/W in mob_occupant)
- if(!is_type_in_typecache(W, telegulag_required_items))
- if(mob_occupant.temporarilyRemoveItemFromInventory(W))
- if(istype(W, /obj/item/restraints/handcuffs))
- W.forceMove(get_turf(src))
- continue
- if(linked_reclaimer)
- linked_reclaimer.stored_items[mob_occupant] += W
- linked_reclaimer.contents += W
- W.forceMove(linked_reclaimer)
- else
- W.forceMove(src)
+ for(var/A in mob_occupant.get_equipped_items(TRUE))
+ var/obj/item/I = A
+ if(is_type_in_typecache(I, telegulag_required_items) || !mob_occupant.temporarilyRemoveItemFromInventory(I))
+ continue
+ if(istype(I, /obj/item/restraints/handcuffs))
+ I.forceMove(get_turf(src))
+ continue
+ if(linked_reclaimer)
+ linked_reclaimer.stored_items[mob_occupant] += I
+ linked_reclaimer.contents += I
+ I.forceMove(linked_reclaimer)
+ else
+ I.forceMove(src)
/obj/machinery/gulag_teleporter/proc/handle_prisoner(obj/item/id, datum/data/record/R)
if(!ishuman(occupant))
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 893f36acb3..79aef8ba7b 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -24,6 +24,8 @@ Possible to do for anyone motivated enough:
* Holopad
*/
+GLOBAL_LIST_EMPTY(network_holopads)
+
#define HOLOPAD_PASSIVE_POWER_USAGE 1
#define HOLOGRAM_POWER_USAGE 2
@@ -55,7 +57,6 @@ Possible to do for anyone motivated enough:
var/record_user //user that inititiated the recording
var/obj/effect/overlay/holo_pad_hologram/replay_holo //replay hologram
var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging
- var/static/list/holopads = list()
var/obj/effect/overlay/holoray/ray
var/ringing = FALSE
var/offset = FALSE
@@ -96,7 +97,7 @@ Possible to do for anyone motivated enough:
/obj/machinery/holopad/Initialize()
. = ..()
if(on_network)
- holopads += src
+ GLOB.network_holopads += src
/obj/machinery/holopad/Destroy()
if(outgoing_call)
@@ -116,7 +117,7 @@ Possible to do for anyone motivated enough:
QDEL_NULL(disk)
- holopads -= src
+ GLOB.network_holopads -= src
return ..()
/obj/machinery/holopad/power_change()
@@ -260,7 +261,7 @@ Possible to do for anyone motivated enough:
temp += "Main Menu"
if(usr.loc == loc)
var/list/callnames = list()
- for(var/I in holopads)
+ for(var/I in GLOB.network_holopads)
var/area/A = get_area(I)
if(A)
LAZYADD(callnames[A], I)
@@ -474,7 +475,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
var/obj/effect/overlay/holo_pad_hologram/h = masters[holo_owner]
if(!h || h.HC) //Holocalls can't change source.
return FALSE
- for(var/pad in holopads)
+ for(var/pad in GLOB.network_holopads)
var/obj/machinery/holopad/another = pad
if(another == src)
continue
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index b217c14e53..621ca266bb 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -8,14 +8,14 @@
icon_state = "iv_drip"
anchored = FALSE
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
- var/mob/living/carbon/attached = null
+ var/mob/living/carbon/attached
var/mode = IV_INJECTING
- var/obj/item/reagent_containers/beaker = null
+ var/obj/item/reagent_containers/beaker
var/static/list/drip_containers = typecacheof(list(/obj/item/reagent_containers/blood,
/obj/item/reagent_containers/food,
/obj/item/reagent_containers/glass))
-/obj/machinery/iv_drip/Initialize()
+/obj/machinery/iv_drip/Initialize(mapload)
. = ..()
update_icon()
@@ -84,6 +84,8 @@
if(Adjacent(target) && usr.Adjacent(target))
if(beaker)
usr.visible_message("[usr] attaches [src] to [target].", "You attach [src] to [target].")
+ log_combat(usr, target, "attached", src, "containing: [beaker.name] - ([beaker.reagents.log_list()])")
+ add_fingerprint(usr)
attached = target
START_PROCESSING(SSmachines, src)
update_icon()
@@ -100,6 +102,8 @@
return
beaker = W
to_chat(user, "You attach [W] to [src].")
+ user.log_message("attached a [W] to [src] at [AREACOORD(src)] containing ([beaker.reagents.log_list()])", LOG_ATTACK)
+ add_fingerprint(user)
update_icon()
return
else
@@ -142,10 +146,11 @@
if(!amount)
if(prob(5))
visible_message("[src] pings.")
+ playsound(loc, 'sound/machines/beep.ogg', 50, 1)
return
// If the human is losing too much blood, beep.
- if(attached.blood_volume < ( (BLOOD_VOLUME_SAFE*attached.blood_ratio) && prob(5) ) )
+ if(attached.blood_volume < ((BLOOD_VOLUME_SAFE*attached.blood_ratio) && prob(5) && ishuman(attached))) //really couldn't care less about monkeys
visible_message("[src] beeps loudly.")
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
attached.transfer_blood_to(beaker, amount)
@@ -178,9 +183,10 @@
if(usr.incapacitated())
return
-
if(beaker)
- beaker.forceMove(drop_location())
+ if(usr && Adjacent(usr) && !issiliconoradminghost(usr))
+ if(!usr.put_in_hands(beaker))
+ beaker.forceMove(drop_location())
beaker = null
update_icon()
@@ -195,27 +201,27 @@
if(usr.incapacitated())
return
-
mode = !mode
to_chat(usr, "The IV drip is now [mode ? "injecting" : "taking blood"].")
update_icon()
/obj/machinery/iv_drip/examine(mob/user)
- ..()
+ . = ..()
if(get_dist(user, src) > 2)
return
- to_chat(user, "The IV drip is [mode ? "injecting" : "taking blood"].")
+ . += "[src] is [mode ? "injecting" : "taking blood"].\n"
if(beaker)
if(beaker.reagents && beaker.reagents.reagent_list.len)
- to_chat(user, "Attached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.")
+ . += "\tAttached is \a [beaker] with [beaker.reagents.total_volume] units of liquid.\n"
else
- to_chat(user, "Attached is an empty [beaker.name].")
+ . += "\tAttached is an empty [beaker.name].\n"
else
- to_chat(user, "No chemicals are attached.")
+ . += "\tNo chemicals are attached.\n"
- to_chat(user, "[attached ? attached : "No one"] is attached.")
+ . += "\t[attached ? attached : "No one"] is attached."
+ to_chat(user,.)
#undef IV_TAKING
-#undef IV_INJECTING
+#undef IV_INJECTING
\ No newline at end of file
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index b0a75c99dc..7aaab0d8ea 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -40,6 +40,8 @@
var/stun_projectile = null //stun mode projectile type
var/stun_projectile_sound
+ var/nonlethal_projectile //projectile to use in stun mode when the target is resting, if any
+ var/nonlethal_projectile_sound
var/lethal_projectile = null //lethal mode projectile type
var/lethal_projectile_sound
@@ -535,13 +537,22 @@
T = closer
break
+ var/mob/living/carbon/C
+ if(iscarbon(target))
+ C = target
+
update_icon()
var/obj/item/projectile/A
//any emagged turrets drains 2x power and uses a different projectile?
if(mode == TURRET_STUN)
- use_power(reqpower)
- A = new stun_projectile(T)
- playsound(loc, stun_projectile_sound, 75, 1)
+ if(nonlethal_projectile && C && C.resting)
+ use_power(reqpower*0.5)
+ A = new nonlethal_projectile(T)
+ playsound(loc, nonlethal_projectile_sound, 75, 1)
+ else
+ use_power(reqpower)
+ A = new stun_projectile(T)
+ playsound(loc, stun_projectile_sound, 75, 1)
else
use_power(reqpower * 2)
A = new lethal_projectile(T)
@@ -551,6 +562,7 @@
//Shooting Code:
A.preparePixelProjectile(target, T)
A.firer = src
+ A.fired_from = src
A.fire()
return A
@@ -653,6 +665,8 @@
base_icon_state = "standard"
stun_projectile = /obj/item/projectile/energy/electrode
stun_projectile_sound = 'sound/weapons/taser.ogg'
+ nonlethal_projectile = /obj/item/projectile/beam/disabler
+ nonlethal_projectile_sound = 'sound/weapons/taser2.ogg'
lethal_projectile = /obj/item/projectile/beam/laser
lethal_projectile_sound = 'sound/weapons/laser.ogg'
desc = "An energy blaster auto-turret."
@@ -662,6 +676,8 @@
base_icon_state = "standard"
stun_projectile = /obj/item/projectile/energy/electrode
stun_projectile_sound = 'sound/weapons/taser.ogg'
+ nonlethal_projectile = /obj/item/projectile/beam/disabler
+ nonlethal_projectile_sound = 'sound/weapons/taser2.ogg'
lethal_projectile = /obj/item/projectile/beam/laser/heavylaser
lethal_projectile_sound = 'sound/weapons/lasercannonfire.ogg'
desc = "An energy blaster auto-turret."
@@ -681,6 +697,8 @@
/obj/machinery/porta_turret/ai
faction = list("silicon")
+ nonlethal_projectile = /obj/item/projectile/beam/disabler
+ nonlethal_projectile_sound = 'sound/weapons/taser2.ogg'
/obj/machinery/porta_turret/ai/assess_perp(mob/living/carbon/human/perp)
return 10 //AI turrets shoot at everything not in their faction
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index 9d431487e0..1a8bc7ece4 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -32,10 +32,10 @@
mat_mod *= 50000
for(var/obj/item/stock_parts/manipulator/M in component_parts)
amt_made = 12.5 * M.rating //% of materials salvaged
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = mat_mod
amount_produced = min(50, amt_made) + 50
- GET_COMPONENT(butchering, /datum/component/butchering)
+ var/datum/component/butchering/butchering = GetComponent(/datum/component/butchering)
butchering.effectiveness = amount_produced
butchering.bonus_modifier = amount_produced/5
@@ -99,7 +99,7 @@
/obj/machinery/recycler/proc/eat(atom/AM0, sound=TRUE)
var/list/to_eat
if(isitem(AM0))
- to_eat = AM0.GetAllContents()
+ to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
else
to_eat = list(AM0)
@@ -144,7 +144,7 @@
qdel(L)
return
else
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
var/material_amount = materials.get_item_material_amount(I)
if(!material_amount)
qdel(I)
@@ -195,7 +195,7 @@
L.Unconscious(100)
L.adjustBruteLoss(crush_damage)
if(L.stat == DEAD && (L.butcher_results || L.guaranteed_butcher_results))
- GET_COMPONENT(butchering, /datum/component/butchering)
+ var/datum/component/butchering/butchering = GetComponent(/datum/component/butchering)
butchering.Butcher(src,L)
/obj/machinery/recycler/deathtrap
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index d308d180d0..f35caf514c 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -265,6 +265,8 @@
things_to_clear += occupant.GetAllContents()
for(var/atom/movable/AM in things_to_clear) //Scorches away blood and forensic evidence, although the SSU itself is unaffected
SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRONG)
+ AM.clean_blood()
+ AM.fingerprints = list()
var/datum/component/radioactive/contamination = AM.GetComponent(/datum/component/radioactive)
if(contamination)
qdel(contamination)
@@ -435,4 +437,4 @@
if(I)
I.forceMove(loc)
. = TRUE
- update_icon()
+ update_icon()
\ No newline at end of file
diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm
index 1f1f13ee22..ae71a0b844 100644
--- a/code/game/machinery/teleporter.dm
+++ b/code/game/machinery/teleporter.dm
@@ -209,5 +209,7 @@
icon_state = "controller-o"
else if(stat & (BROKEN|NOPOWER))
icon_state = "controller-p"
+ else if(teleporter_console && teleporter_console.calibrating)
+ icon_state = "controller-c"
else
icon_state = "controller"
diff --git a/code/game/machinery/turnstile.dm b/code/game/machinery/turnstile.dm
new file mode 100644
index 0000000000..1fd78056d4
--- /dev/null
+++ b/code/game/machinery/turnstile.dm
@@ -0,0 +1,84 @@
+/obj/machinery/turnstile
+ name = "turnstile"
+ desc = "A mechanical door that permits one-way access and prevents tailgating."
+ icon = 'icons/obj/turnstile.dmi'
+ icon_state = "turnstile_map"
+ density = FALSE
+ armor = list(melee = 50, bullet = 50, laser = 50, energy = 50, bomb = 10, bio = 100, rad = 100, fire = 90, acid = 70)
+ anchored = TRUE
+ use_power = FALSE
+ idle_power_usage = 2
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ layer = OPEN_DOOR_LAYER
+
+/obj/machinery/turnstile/Initialize()
+ . = ..()
+ icon_state = "turnstile"
+
+/obj/machinery/turnstile/CanAtmosPass(turf/T)
+ return TRUE
+
+/obj/machinery/turnstile/bullet_act(obj/item/projectile/P, def_zone)
+ return -1 //Pass through!
+
+/obj/machinery/turnstile/proc/allowed_access(var/mob/B)
+ if(B.pulledby && ismob(B.pulledby))
+ return allowed(B.pulledby) | allowed(B)
+ else
+ return allowed(B)
+
+/obj/machinery/turnstile/CanPass(atom/movable/AM, turf/T)
+ if(ismob(AM))
+ var/mob/B = AM
+ if(isliving(AM))
+ var/mob/living/M = AM
+
+ if(world.time - M.last_bumped <= 5)
+ return FALSE
+ M.last_bumped = world.time
+
+ var/allowed_access = FALSE
+ var/turf/behind = get_step(src, dir)
+
+ if(B in behind.contents)
+ allowed_access = allowed_access(B)
+ else
+ to_chat(usr, "\the [src] resists your efforts.")
+ return FALSE
+
+ if(allowed_access)
+ flick("operate", src)
+ playsound(src,'sound/items/ratchet.ogg',50,0,3)
+ return TRUE
+ else
+ flick("deny", src)
+ playsound(src,'sound/machines/deniedbeep.ogg',50,0,3)
+ return FALSE
+ if(ispath(AM, /obj/item/))
+ return TRUE
+ else
+ return FALSE
+
+/obj/machinery/turnstile/CheckExit(atom/movable/AM as mob|obj, target)
+ if(isliving(AM))
+ var/mob/living/M = AM
+ var/outdir = dir
+ if(allowed_access(M))
+ switch(dir)
+ if(NORTH)
+ outdir = SOUTH
+ if(SOUTH)
+ outdir = NORTH
+ if(EAST)
+ outdir = WEST
+ if(WEST)
+ outdir = EAST
+ var/turf/outturf = get_step(src, outdir)
+ var/canexit = (target == src.loc) | (target == outturf)
+
+ if(!canexit && world.time - M.last_bumped <= 5)
+ to_chat(usr, "\the [src] resists your efforts.")
+ M.last_bumped = world.time
+ return canexit
+ else
+ return TRUE
\ No newline at end of file
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index 5e8515d3d5..8be079656b 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -11,10 +11,6 @@
var/obj/item/color_source
var/max_wash_capacity = 5
-/obj/machinery/washing_machine/ComponentInitialize()
- . = ..()
- AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
-
/obj/machinery/washing_machine/examine(mob/user)
..()
to_chat(user, "Alt-click it to start a wash cycle.")
@@ -59,7 +55,8 @@
M.Translate(rand(-3, 3), rand(-1, 3))
animate(src, transform=M, time=2)
-/obj/machinery/washing_machine/proc/clean_blood()
+/obj/machinery/washing_machine/clean_blood()
+ ..()
if(!busy)
bloody_mess = FALSE
update_icon()
@@ -67,7 +64,8 @@
/obj/machinery/washing_machine/proc/wash_cycle()
for(var/X in contents)
var/atom/movable/AM = X
- SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(AM, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ AM.clean_blood()
AM.machine_wash(src)
busy = FALSE
diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm
index ea51693135..431d4c30b3 100644
--- a/code/game/mecha/combat/combat.dm
+++ b/code/game/mecha/combat/combat.dm
@@ -3,3 +3,9 @@
internal_damage_threshold = 50
armor = list("melee" = 30, "bullet" = 30, "laser" = 15, "energy" = 20, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
mouse_pointer = 'icons/mecha/mecha_mouse.dmi'
+ var/spawn_tracked = TRUE
+
+/obj/mecha/combat/Initialize()
+ . = ..()
+ if(spawn_tracked)
+ trackers += new /obj/item/mecha_parts/mecha_tracking(src)
\ No newline at end of file
diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm
index cd7051d074..caaa3e3a00 100644
--- a/code/game/mecha/combat/durand.dm
+++ b/code/game/mecha/combat/durand.dm
@@ -19,7 +19,3 @@
/obj/mecha/combat/durand/RemoveActions(mob/living/user, human_occupant = 0)
..()
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 564f308df3..c7c180af41 100644
--- a/code/game/mecha/combat/gygax.dm
+++ b/code/game/mecha/combat/gygax.dm
@@ -29,6 +29,7 @@
operation_req_access = list(ACCESS_SYNDICATE)
wreckage = /obj/structure/mecha_wreckage/gygax/dark
max_equip = 4
+ spawn_tracked = FALSE
/obj/mecha/combat/gygax/dark/loaded/Initialize()
. = ..()
@@ -48,7 +49,6 @@
return
cell = new /obj/item/stock_parts/cell/hyper(src)
-
/obj/mecha/combat/gygax/GrantActions(mob/living/user, human_occupant = 0)
..()
overload_action.Grant(user, src)
@@ -65,7 +65,3 @@
/obj/mecha/combat/gygax/dark/RemoveActions(mob/living/user, human_occupant = 0)
..()
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 4c32e9c367..ed29809f91 100644
--- a/code/game/mecha/combat/honker.dm
+++ b/code/game/mecha/combat/honker.dm
@@ -152,8 +152,4 @@
var/color=""
for (var/i=0;i<6;i++)
color = color+pick(colors)
- return color
-
-/obj/mecha/combat/Initialize()
- . = ..()
- trackers += new /obj/item/mecha_parts/mecha_tracking(src)
+ return color
\ No newline at end of file
diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm
index 21f8259e69..42817b586c 100644
--- a/code/game/mecha/combat/marauder.dm
+++ b/code/game/mecha/combat/marauder.dm
@@ -16,6 +16,7 @@
force = 45
max_equip = 4
bumpsmash = 1
+ spawn_tracked = FALSE
/obj/mecha/combat/marauder/GrantActions(mob/living/user, human_occupant = 0)
..()
diff --git a/code/game/mecha/combat/neovgre.dm b/code/game/mecha/combat/neovgre.dm
new file mode 100644
index 0000000000..b1f2cdd02a
--- /dev/null
+++ b/code/game/mecha/combat/neovgre.dm
@@ -0,0 +1,97 @@
+/obj/mecha/combat/neovgre
+ name = "Neovgre, the Anima Bulwark"
+ desc = "Nezbere's most powerful creation, a mighty war machine of unmatched power said to have ended wars in a single night."
+ icon = 'icons/mecha/neovgre.dmi'
+ icon_state = "neovgre"
+ max_integrity = 500 //This is THE ratvarian superweaon, its deployment is an investment
+ armor = list("melee" = 50, "bullet" = 40, "laser" = 25, "energy" = 25, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) //Its similar to the clockwork armour albeit with a few buffs becuase RATVARIAN SUPERWEAPON!!
+ force = 50 //SMASHY SMASHY!!
+ internal_damage_threshold = 0
+ step_in = 3
+ pixel_x = -16
+ layer = ABOVE_MOB_LAYER
+ breach_time = 100 //ten seconds till all goes to shit
+ recharge_rate = 100
+ wreckage = /obj/structure/mecha_wreckage/durand/neovgre
+ spawn_tracked = FALSE
+
+/obj/mecha/combat/neovgre/GrantActions(mob/living/user, human_occupant = 0) //No Eject action for you sonny jim, your life for Ratvar!
+ internals_action.Grant(user, src)
+ cycle_action.Grant(user, src)
+ lights_action.Grant(user, src)
+ stats_action.Grant(user, src)
+ strafing_action.Grant(user, src)
+
+/obj/mecha/combat/neovgre/RemoveActions(mob/living/user, human_occupant = 0)
+ internals_action.Remove(user)
+ cycle_action.Remove(user)
+ lights_action.Remove(user)
+ stats_action.Remove(user)
+ strafing_action.Remove(user)
+
+/obj/mecha/combat/neovgre/MouseDrop_T(mob/M, mob/user)
+ if(!is_servant_of_ratvar(user))
+ to_chat(user, "BEGONE HERETIC!")
+ return
+ else
+ ..()
+
+/obj/mecha/combat/neovgre/moved_inside(mob/living/carbon/human/H)
+ var/list/Itemlist = H.get_contents()
+ for(var/obj/item/clockwork/slab/W in Itemlist)
+ to_chat(H, "You safely store [W] inside [src].")
+ qdel(W)
+ . = ..()
+
+/obj/mecha/combat/neovgre/obj_destruction()
+ for(var/mob/M in src)
+ to_chat(M, "You are consumed by the fires raging within Neovgre...")
+ M.dust()
+ playsound(src, 'sound/magic/lightning_chargeup.ogg', 100, 0)
+ src.visible_message("The reactor has gone critical, its going to blow!")
+ addtimer(CALLBACK(src,.proc/go_critical),breach_time)
+
+/obj/mecha/combat/neovgre/proc/go_critical()
+ explosion(get_turf(loc), 3, 5, 10, 20, 30)
+ Destroy(src)
+
+/obj/mecha/combat/neovgre/container_resist(mob/living/user)
+ to_chat(user, "Neovgre requires a lifetime commitment friend, no backing out now!")
+ return
+
+/obj/mecha/combat/neovgre/process()
+ ..()
+ if(GLOB.ratvar_awakens) // At this point only timley intervention by lord singulo could hople to stop the superweapon
+ cell.charge = INFINITY
+ max_integrity = INFINITY
+ obj_integrity = max_integrity
+ CHECK_TICK //Just to be on the safe side lag wise
+ else if(cell.charge < cell.maxcharge)
+ for(var/obj/effect/clockwork/sigil/transmission/T in range(SIGIL_ACCESS_RANGE, src))
+ var/delta = min(recharge_rate, cell.maxcharge - cell.charge)
+ if (get_clockwork_power() <= delta)
+ cell.charge += delta
+ adjust_clockwork_power(-delta)
+ CHECK_TICK
+
+/obj/mecha/combat/neovgre/Initialize()
+ .=..()
+ GLOB.neovgre_exists ++
+ var/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/neovgre/N = new
+ N.attach(src)
+
+/obj/structure/mecha_wreckage/durand/neovgre
+ name = "\improper Neovgre wreckage?"
+ desc = "On closer inspection this looks like the wreck of a durand with some spraypainted cardboard duct taped to it!"
+
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/neovgre
+ equip_cooldown = 8 //Rapid fire heavy laser cannon, simple yet elegant
+ energy_drain = 30
+ name = "Aribter Laser Cannon"
+ desc = "Please re-attach this to neovgre and stop asking questions about why it looks like a normal Nanotrasen issue Solaris laser cannon - Nezbere"
+ fire_sound = "sound/weapons/neovgre_laser.ogg"
+
+/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/heavy/neovgre/can_attach(obj/mecha/combat/neovgre/M)
+ if(istype(M))
+ return 1
+ return 0
diff --git a/code/game/mecha/combat/phazon.dm b/code/game/mecha/combat/phazon.dm
index 1264a647c4..15b865c1e9 100644
--- a/code/game/mecha/combat/phazon.dm
+++ b/code/game/mecha/combat/phazon.dm
@@ -27,7 +27,3 @@
..()
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/combat/reticence.dm b/code/game/mecha/combat/reticence.dm
index 4cd8c01517..7e8c865517 100644
--- a/code/game/mecha/combat/reticence.dm
+++ b/code/game/mecha/combat/reticence.dm
@@ -18,6 +18,7 @@
stepsound = null
turnsound = null
opacity = 0
+ spawn_tracked = FALSE
/obj/mecha/combat/reticence/loaded/Initialize()
. = ..()
diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm
index eb3261bb27..4044951c42 100644
--- a/code/game/mecha/equipment/tools/mining_tools.dm
+++ b/code/game/mecha/equipment/tools/mining_tools.dm
@@ -100,12 +100,12 @@
/obj/item/mecha_parts/mecha_equipment/drill/attach(obj/mecha/M)
..()
- GET_COMPONENT_FROM(butchering, /datum/component/butchering, src)
+ var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.butchering_enabled = TRUE
/obj/item/mecha_parts/mecha_equipment/drill/detach(atom/moveto)
..()
- GET_COMPONENT_FROM(butchering, /datum/component/butchering, src)
+ var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.butchering_enabled = FALSE
/obj/item/mecha_parts/mecha_equipment/drill/proc/drill_mob(mob/living/target, mob/user)
@@ -115,7 +115,7 @@
if(target.stat == DEAD && target.getBruteLoss() >= 200)
log_combat(user, target, "gibbed", name)
if(LAZYLEN(target.butcher_results) || LAZYLEN(target.guaranteed_butcher_results))
- GET_COMPONENT_FROM(butchering, /datum/component/butchering, src)
+ var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.Butcher(chassis, target)
else
target.gib()
diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm
index e1dc80911f..4acf7981bc 100644
--- a/code/game/mecha/mech_fabricator.dm
+++ b/code/game/mecha/mech_fabricator.dm
@@ -47,7 +47,7 @@
//maximum stocking amount (default 300000, 600000 at T4)
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
T += M.rating
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.max_amount = (200000 + (T*50000))
//resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55)
@@ -109,7 +109,7 @@
/obj/machinery/mecha_part_fabricator/proc/output_available_resources()
var/output
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = materials.materials[mat_id]
output += "[M.name]: [M.amount] cm³"
@@ -130,7 +130,7 @@
/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D)
if(D.reagents_list.len) // No reagents storage - no reagent designs.
return FALSE
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(materials.has_materials(get_resources_w_coeff(D)))
return TRUE
return FALSE
@@ -140,7 +140,7 @@
desc = "It's building \a [initial(D.name)]."
var/list/res_coef = get_resources_w_coeff(D)
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.use_amount(res_coef)
add_overlay("fab-active")
use_power = ACTIVE_POWER_USE
@@ -384,14 +384,14 @@
break
if(href_list["remove_mat"] && href_list["material"])
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_sheets(text2num(href_list["remove_mat"]), href_list["material"])
updateUsrDialog()
return
/obj/machinery/mecha_part_fabricator/on_deconstruction()
- GET_COMPONENT(materials, /datum/component/material_container)
+ var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
materials.retrieve_all()
..()
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 22aac63d2b..717c94362c 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -49,6 +49,8 @@
var/lights = FALSE
var/lights_power = 6
var/last_user_hud = 1 // used to show/hide the mecha hud while preserving previous preference
+ var/breach_time = 0
+ var/recharge_rate = 0
var/bumpsmash = 0 //Whether or not the mech destroys walls by running into it.
//inner atmos
@@ -1023,7 +1025,7 @@
/obj/mecha/log_message(message as text, message_type=LOG_GAME, color=null, log_globally)
log.len++
- log[log.len] = list("time"="[STATION_TIME_TIMESTAMP("hh:mm:ss")]","date","year"="[GLOB.year_integer+540]","message"="[color?"":null][message][color?"":null]")
+ log[log.len] = list("time"="[STATION_TIME_TIMESTAMP("hh:mm:ss")]","date","year"="[GLOB.year_integer]","message"="[color?"":null][message][color?"":null]")
..()
return log.len
@@ -1032,9 +1034,6 @@
last_entry["message"] += " [red?"":null][message][red?"":null]"
return
-GLOBAL_VAR_INIT(year, time2text(world.realtime,"YYYY"))
-GLOBAL_VAR_INIT(year_integer, text2num(year)) // = 2013???
-
///////////////////////
///// Power stuff /////
///////////////////////
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index ef3ba969e9..19656f2d7d 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -47,7 +47,7 @@
/obj/mecha/working/ripley/update_icon()
..()
- GET_COMPONENT(C,/datum/component/armor_plate)
+ var/datum/component/armor_plate/C = GetComponent(/datum/component/armor_plate)
if (C.amount)
cut_overlays()
if(C.amount < 3)
diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm
index 693d32e545..9c3df5395f 100644
--- a/code/game/objects/buckling.dm
+++ b/code/game/objects/buckling.dm
@@ -89,7 +89,6 @@
buckled_mob.clear_alert("buckled")
buckled_mobs -= buckled_mob
SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force)
- SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, src, force)
post_unbuckle_mob(.)
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index d5aff99f32..cab4a66fdd 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -8,6 +8,7 @@
/obj/effect/decal/cleanable/Initialize(mapload, list/datum/disease/diseases)
. = ..()
+ LAZYINITLIST(blood_DNA) //Kinda needed
if (random_icon_states && (icon_state == initial(icon_state)) && length(random_icon_states) > 0)
icon_state = pick(random_icon_states)
create_reagents(300)
@@ -27,7 +28,7 @@
/obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal
if(mergeable_decal)
- return TRUE
+ qdel(C)
/obj/effect/decal/cleanable/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/reagent_containers/glass) || istype(W, /obj/item/reagent_containers/food/drinks))
@@ -44,11 +45,11 @@
if(!reagents.total_volume) //scooped up all of it
qdel(src)
return
- if(W.is_hot()) //todo: make heating a reagent holder proc
+ if(W.get_temperature()) //todo: make heating a reagent holder proc
if(istype(W, /obj/item/clothing/mask/cigarette))
return
else
- var/hotness = W.is_hot()
+ var/hotness = W.get_temperature()
reagents.expose_temperature(hotness)
to_chat(user, "You heat [name] with [W]!")
else
@@ -81,7 +82,9 @@
add_blood = bloodiness
bloodiness -= add_blood
S.bloody_shoes[blood_state] = min(MAX_SHOE_BLOODINESS,S.bloody_shoes[blood_state]+add_blood)
- S.add_blood_DNA(return_blood_DNA())
+ if(blood_DNA && blood_DNA.len)
+ S.add_blood_DNA(blood_DNA)
+ S.add_blood_overlay()
S.blood_state = blood_state
update_icon()
H.update_inv_shoes()
@@ -90,4 +93,4 @@
if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY))
return bloodiness
else
- return 0
+ return FALSE
diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm
index ca2a8ccaff..a4d0da1bbe 100644
--- a/code/game/objects/effects/decals/cleanable/aliens.dm
+++ b/code/game/objects/effects/decals/cleanable/aliens.dm
@@ -1,71 +1,70 @@
-// Note: BYOND is object oriented. There is no reason for this to be copy/pasted blood code.
-/obj/effect/decal/cleanable/xenoblood
+/obj/effect/decal/cleanable/blood/xeno
name = "xeno blood"
desc = "It's green and acidic. It looks like... blood?"
- icon = 'icons/effects/blood.dmi'
- icon_state = "xfloor1"
- random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
- bloodiness = BLOOD_AMOUNT_PER_DECAL
- blood_state = BLOOD_STATE_XENO
+ color = BLOOD_COLOR_XENO
-/obj/effect/decal/cleanable/xenoblood/Initialize()
+/obj/effect/decal/cleanable/blood/splatter/xeno
+ color = BLOOD_COLOR_XENO
+
+/obj/effect/decal/cleanable/blood/gibs/xeno
+ color = BLOOD_COLOR_XENO
+ gibs_reagent_id = "liquidxenogibs"
+ gibs_bloodtype = "X*"
+
+/obj/effect/decal/cleanable/blood/gibs/xeno/Initialize(mapload, list/datum/disease/diseases)
. = ..()
- add_blood_DNA(list("UNKNOWN DNA" = "X*"))
+ update_icon()
-/obj/effect/decal/cleanable/xenoblood/xsplatter
- random_icon_states = list("xgibbl1", "xgibbl2", "xgibbl3", "xgibbl4", "xgibbl5")
+/obj/effect/decal/cleanable/blood/gibs/xeno/update_icon()
+ add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
+ cut_overlays()
+ var/mutable_appearance/flesh = mutable_appearance(icon, "[icon_state]x_flesh")
+ flesh.appearance_flags = RESET_COLOR
+ flesh.color = body_colors
+ add_overlay(flesh)
-/obj/effect/decal/cleanable/xenoblood/xgibs
- name = "xeno gibs"
- desc = "Gnarly..."
- icon = 'icons/effects/blood.dmi'
- icon_state = "xgib1"
- layer = LOW_OBJ_LAYER
- random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6")
- mergeable_decal = FALSE
-
-/obj/effect/decal/cleanable/xenoblood/xgibs/proc/streak(list/directions)
- set waitfor = 0
+/obj/effect/decal/cleanable/blood/gibs/xeno/streak(list/directions)
+ set waitfor = FALSE
+ var/list/diseases = list()
+ SEND_SIGNAL(src, COMSIG_GIBS_STREAK, directions, diseases)
var/direction = pick(directions)
- for(var/i = 0, i < pick(1, 200; 2, 150; 3, 50), i++)
+ for(var/i in 0 to pick(0, 200; 1, 150; 2, 50))
sleep(2)
if(i > 0)
- new /obj/effect/decal/cleanable/xenoblood/xsplatter(loc)
+ var/obj/effect/decal/cleanable/blood/splatter/xeno/splat = new /obj/effect/decal/cleanable/blood/splatter/xeno(loc, diseases)
+ splat.transfer_blood_dna(blood_DNA, diseases)
if(!step_to(src, get_step(src, direction), 0))
break
-/obj/effect/decal/cleanable/xenoblood/xgibs/ex_act()
- return
+/obj/effect/decal/cleanable/blood/gibs/xeno/up
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
-/obj/effect/decal/cleanable/xenoblood/xgibs/up
- random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6","xgibup1","xgibup1","xgibup1")
+/obj/effect/decal/cleanable/blood/gibs/xeno/down
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
-/obj/effect/decal/cleanable/xenoblood/xgibs/down
- random_icon_states = list("xgib1", "xgib2", "xgib3", "xgib4", "xgib5", "xgib6","xgibdown1","xgibdown1","xgibdown1")
+/obj/effect/decal/cleanable/blood/gibs/xeno/body
+ random_icon_states = list("gibhead", "gibtorso")
-/obj/effect/decal/cleanable/xenoblood/xgibs/body
- random_icon_states = list("xgibhead", "xgibtorso")
+/obj/effect/decal/cleanable/blood/gibs/xeno/torso
+ random_icon_states = list("gibtorso")
-/obj/effect/decal/cleanable/xenoblood/xgibs/torso
- random_icon_states = list("xgibtorso")
+/obj/effect/decal/cleanable/blood/gibs/xeno/limb
+ random_icon_states = list("gibleg", "gibarm")
-/obj/effect/decal/cleanable/xenoblood/xgibs/limb
- random_icon_states = list("xgibleg", "xgibarm")
+/obj/effect/decal/cleanable/blood/gibs/xeno/core
+ random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
-/obj/effect/decal/cleanable/xenoblood/xgibs/core
- random_icon_states = list("xgibmid1", "xgibmid2", "xgibmid3")
-
-/obj/effect/decal/cleanable/xenoblood/xgibs/larva
+/obj/effect/decal/cleanable/blood/gibs/xeno/larva
random_icon_states = list("xgiblarva1", "xgiblarva2")
-/obj/effect/decal/cleanable/xenoblood/xgibs/larva/body
+/obj/effect/decal/cleanable/blood/gibs/xeno/larva/body
random_icon_states = list("xgiblarvahead", "xgiblarvatorso")
/obj/effect/decal/cleanable/blood/xtracks
- icon_state = "xtracks"
+ icon_state = "tracks"
random_icon_states = null
/obj/effect/decal/cleanable/blood/xtracks/Initialize()
- . = ..()
- add_blood_DNA(list("Unknown DNA" = "X*"))
+ add_blood_DNA(list("UNKNOWN DNA" = "X*"))
+ . = ..()
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/cleanable/gibs.dm b/code/game/objects/effects/decals/cleanable/gibs.dm
new file mode 100644
index 0000000000..03eeca7d0b
--- /dev/null
+++ b/code/game/objects/effects/decals/cleanable/gibs.dm
@@ -0,0 +1,231 @@
+/obj/effect/decal/cleanable/blood/gibs
+ name = "gibs"
+ desc = "They look bloody and gruesome."
+ icon_state = "gibbl5"
+ layer = LOW_OBJ_LAYER
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
+ mergeable_decal = FALSE
+ var/body_colors = "#e3ba84" //a default color just in case.
+ var/gibs_reagent_id = "liquidgibs"
+ var/gibs_bloodtype = "A+"
+
+/obj/effect/decal/cleanable/blood/gibs/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ if(random_icon_states && (icon_state == initial(icon_state)) && length(random_icon_states) > 0)
+ icon_state = pick(random_icon_states)
+ if(gibs_reagent_id)
+ reagents.add_reagent(gibs_reagent_id, 5)
+ if(gibs_bloodtype)
+ add_blood_DNA(list("Non-human DNA" = gibs_bloodtype, diseases))
+ update_icon()
+
+
+/obj/effect/decal/cleanable/blood/gibs/update_icon()
+ add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
+ cut_overlays()
+ var/mutable_appearance/guts = mutable_appearance(icon, "[icon_state]_guts")
+ guts.appearance_flags = RESET_COLOR
+ add_overlay(guts)
+ var/mutable_appearance/flesh = mutable_appearance(icon, "[icon_state]_flesh")
+ flesh.appearance_flags = RESET_COLOR
+ flesh.color = body_colors
+ add_overlay(flesh)
+
+/obj/effect/decal/cleanable/blood/gibs/ex_act(severity, target)
+ return
+
+/obj/effect/decal/cleanable/blood/gibs/Crossed(mob/living/L)
+ if(istype(L) && has_gravity(loc))
+ playsound(loc, 'sound/effects/gib_step.ogg', !HAS_TRAIT(L,TRAIT_LIGHT_STEP) ? 20 : 50, 1)
+ . = ..()
+
+/obj/effect/decal/cleanable/blood/gibs/proc/streak(list/directions)
+ set waitfor = FALSE
+ var/list/diseases = list()
+ SEND_SIGNAL(src, COMSIG_GIBS_STREAK, directions, diseases)
+ var/direction = pick(directions)
+ for(var/i in 0 to pick(0, 200; 1, 150; 2, 50))
+ sleep(2)
+ if(i > 0)
+ var/obj/effect/decal/cleanable/blood/splatter/splat = new /obj/effect/decal/cleanable/blood/splatter(loc, diseases)
+ splat.transfer_blood_dna(blood_DNA, diseases)
+ if(!step_to(src, get_step(src, direction), 0))
+ break
+
+/obj/effect/decal/cleanable/blood/gibs/up
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
+
+/obj/effect/decal/cleanable/blood/gibs/down
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
+
+/obj/effect/decal/cleanable/blood/gibs/body
+ random_icon_states = list("gibhead", "gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/torso
+ random_icon_states = list("gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/limb
+ random_icon_states = list("gibleg", "gibarm")
+
+/obj/effect/decal/cleanable/blood/gibs/core
+ random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
+
+/obj/effect/decal/cleanable/blood/gibs/old
+ name = "old rotting gibs"
+ desc = "Space Jesus, why didn't anyone clean this up? It smells terrible."
+ bloodiness = 0
+
+/obj/effect/decal/cleanable/blood/gibs/old/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ setDir(pick(GLOB.cardinals))
+ icon_state += "-old"
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/drip
+ name = "drips of blood"
+ desc = "It's gooey."
+ icon_state = "1"
+ random_icon_states = list("drip1","drip2","drip3","drip4","drip5")
+ bloodiness = 0
+ var/drips = 1
+
+/obj/effect/decal/cleanable/blood/drip/can_bloodcrawl_in()
+ return TRUE
+
+/obj/effect/decal/cleanable/blood/gibs/human
+
+/obj/effect/decal/cleanable/blood/gibs/human/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/gibs/human/up
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
+
+/obj/effect/decal/cleanable/blood/gibs/human/down
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
+
+/obj/effect/decal/cleanable/blood/gibs/human/body
+ random_icon_states = list("gibhead", "gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/human/torso
+ random_icon_states = list("gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/human/limb
+ random_icon_states = list("gibleg", "gibarm")
+
+/obj/effect/decal/cleanable/blood/gibs/human/core
+ random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
+
+
+//Lizards
+/obj/effect/decal/cleanable/blood/gibs/human/lizard
+ body_colors = "117720"
+ gibs_reagent_id = "liquidgibs"
+ gibs_bloodtype = "L"
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/up
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/down
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/body
+ random_icon_states = list("gibhead", "gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/torso
+ random_icon_states = list("gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/limb
+ random_icon_states = list("gibleg", "gibarm")
+
+/obj/effect/decal/cleanable/blood/gibs/human/lizard/core
+ random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
+
+// Slime Gibs
+/obj/effect/decal/cleanable/blood/gibs/slime
+ desc = "They look gooey and gruesome."
+ gibs_reagent_id = "liquidslimegibs"
+ gibs_bloodtype = "GEL"
+
+/obj/effect/decal/cleanable/blood/gibs/slime/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/gibs/slime/update_icon()
+ add_atom_colour(body_colors, FIXED_COLOUR_PRIORITY)
+ cut_overlays()
+ var/mutable_appearance/guts = mutable_appearance(icon, "[icon_state]s_guts")
+ guts.appearance_flags = RESET_COLOR
+ guts.color = body_colors
+ add_overlay(guts)
+ var/mutable_appearance/flesh = mutable_appearance(icon, "[icon_state]_flesh")
+ flesh.appearance_flags = RESET_COLOR
+ flesh.color = body_colors
+ add_overlay(flesh)
+
+/obj/effect/decal/cleanable/blood/gibs/slime/up
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
+
+/obj/effect/decal/cleanable/blood/gibs/slime/down
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
+
+/obj/effect/decal/cleanable/blood/gibs/slime/body
+ random_icon_states = list("gibhead", "gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/slime/torso
+ random_icon_states = list("gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/slime/limb
+ random_icon_states = list("gibleg", "gibarm")
+
+/obj/effect/decal/cleanable/blood/gibs/slime/core
+ random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
+
+/obj/effect/decal/cleanable/blood/gibs/synth
+ desc = "They look sludgy and disgusting."
+ gibs_reagent_id = "liquidsyntheticgibs"
+ gibs_bloodtype = "SY"
+
+/obj/effect/decal/cleanable/blood/gibs/synth/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ update_icon()
+
+//IPCs
+/obj/effect/decal/cleanable/blood/gibs/ipc
+ desc = "They look sharp yet oozing."
+ body_colors = "00ff00"
+ gibs_reagent_id = "liquidoilgibs"
+ gibs_bloodtype = "HF"
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/update_icon()
+ add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
+ cut_overlays()
+ var/mutable_appearance/guts = mutable_appearance(icon, "[icon_state]r-overlay")
+ guts.appearance_flags = RESET_COLOR
+ add_overlay(guts)
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/up
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/down
+ random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/body
+ random_icon_states = list("gibhead", "gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/torso
+ random_icon_states = list("gibtorso")
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/limb
+ random_icon_states = list("gibleg", "gibarm")
+
+/obj/effect/decal/cleanable/blood/gibs/ipc/core
+ random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm
index 35f06c2768..842b230b53 100644
--- a/code/game/objects/effects/decals/cleanable/humans.dm
+++ b/code/game/objects/effects/decals/cleanable/humans.dm
@@ -1,31 +1,45 @@
/obj/effect/decal/cleanable/blood
name = "blood"
- desc = "It's red and gooey. Perhaps it's the chef's cooking?"
+ desc = "It's gooey. Perhaps it's the chef's cooking?"
icon = 'icons/effects/blood.dmi'
icon_state = "floor1"
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
- blood_state = BLOOD_STATE_HUMAN
- bloodiness = BLOOD_AMOUNT_PER_DECAL
+ blood_state = BLOOD_STATE_BLOOD
+ bloodiness = MAX_SHOE_BLOODINESS
+ color = BLOOD_COLOR_HUMAN //default so we don't have white splotches everywhere.
/obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C)
- C.add_blood_DNA(return_blood_DNA())
- if (bloodiness)
- if (C.bloodiness < MAX_SHOE_BLOODINESS)
- C.bloodiness += bloodiness
- return ..()
+ if (C.blood_DNA)
+ blood_DNA |= C.blood_DNA.Copy()
+ update_icon()
+ ..()
+
+/obj/effect/decal/cleanable/blood/transfer_blood_dna()
+ ..()
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/transfer_mob_blood_dna()
+ . = ..()
+ update_icon()
+
+/obj/effect/decal/cleanable/blood/update_icon()
+ color = blood_DNA_to_color()
/obj/effect/decal/cleanable/blood/old
name = "dried blood"
- desc = "Looks like it's been here a while. Eew."
+ desc = "Looks like it's been here a while. Eew."
bloodiness = 0
/obj/effect/decal/cleanable/blood/old/Initialize(mapload, list/datum/disease/diseases)
- icon_state += "-old" //This IS necessary because the parent /blood type uses icon randomization.
- add_blood_DNA(list("Non-human DNA" = "A+")) // Needs to happen before ..()
- return ..()
+ ..()
+ icon_state += "-old"
+ add_blood_DNA(list("Non-human DNA" = "A+"))
+
+/obj/effect/decal/cleanable/blood/splats
+ random_icon_states = list("gibbl1", "gibbl2", "gibbl3", "gibbl4", "gibbl5")
/obj/effect/decal/cleanable/blood/splatter
- random_icon_states = list("gibbl1", "gibbl2", "gibbl3", "gibbl4", "gibbl5")
+ random_icon_states = list("splatter1", "splatter2", "splatter3", "splatter4", "splatter5")
/obj/effect/decal/cleanable/blood/tracks
icon_state = "tracks"
@@ -39,84 +53,23 @@
random_icon_states = null
var/list/existing_dirs = list()
+/obj/effect/decal/cleanable/trail_holder/update_icon()
+ color = blood_DNA_to_color()
+
+/obj/effect/cleanable/trail_holder/Initialize()
+ . = ..()
+ update_icon()
+
/obj/effect/decal/cleanable/trail_holder/can_bloodcrawl_in()
return TRUE
-/obj/effect/decal/cleanable/blood/gibs
- name = "gibs"
- desc = "They look bloody and gruesome."
- icon = 'icons/effects/blood.dmi'
- icon_state = "gibbl5"
- layer = LOW_OBJ_LAYER
- random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
- mergeable_decal = FALSE
+/obj/effect/decal/cleanable/trail_holder/transfer_blood_dna()
+ ..()
+ update_icon()
-/obj/effect/decal/cleanable/blood/gibs/Initialize(mapload, list/datum/disease/diseases)
+/obj/effect/decal/cleanable/trail_holder/transfer_mob_blood_dna()
. = ..()
- reagents.add_reagent("liquidgibs", 5)
-
-/obj/effect/decal/cleanable/blood/gibs/ex_act(severity, target)
- return
-
-/obj/effect/decal/cleanable/blood/gibs/Crossed(mob/living/L)
- if(istype(L) && has_gravity(loc))
- playsound(loc, 'sound/effects/gib_step.ogg', HAS_TRAIT(L, TRAIT_LIGHT_STEP) ? 20 : 50, 1)
- . = ..()
-
-/obj/effect/decal/cleanable/blood/gibs/proc/streak(list/directions)
- set waitfor = 0
- var/direction = pick(directions)
- for(var/i = 0, i < pick(1, 200; 2, 150; 3, 50), i++)
- sleep(2)
- if(i > 0)
- var/list/datum/disease/diseases
- GET_COMPONENT(infective, /datum/component/infective)
- if(infective)
- diseases = infective.diseases
- new /obj/effect/decal/cleanable/blood/splatter(loc, diseases)
- if(!step_to(src, get_step(src, direction), 0))
- break
-
-/obj/effect/decal/cleanable/blood/gibs/up
- random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibup1","gibup1","gibup1")
-
-/obj/effect/decal/cleanable/blood/gibs/down
- random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6","gibdown1","gibdown1","gibdown1")
-
-/obj/effect/decal/cleanable/blood/gibs/body
- random_icon_states = list("gibhead", "gibtorso")
-
-/obj/effect/decal/cleanable/blood/gibs/torso
- random_icon_states = list("gibtorso")
-
-/obj/effect/decal/cleanable/blood/gibs/limb
- random_icon_states = list("gibleg", "gibarm")
-
-/obj/effect/decal/cleanable/blood/gibs/core
- random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
-
-/obj/effect/decal/cleanable/blood/gibs/old
- name = "old rotting gibs"
- desc = "Space Jesus, why didn't anyone clean this up? It smells terrible."
- bloodiness = 0
-
-/obj/effect/decal/cleanable/blood/gibs/old/Initialize(mapload, list/datum/disease/diseases)
- . = ..()
- setDir(pick(1,2,4,8))
- icon_state += "-old"
- add_blood_DNA(list("Non-human DNA" = "A+"))
-
-/obj/effect/decal/cleanable/blood/drip
- name = "drips of blood"
- desc = "It's red."
- icon_state = "1"
- random_icon_states = list("drip1","drip2","drip3","drip4","drip5")
- bloodiness = 0
- var/drips = 1
-
-/obj/effect/decal/cleanable/blood/drip/can_bloodcrawl_in()
- return TRUE
-
+ update_icon()
//BLOODY FOOTPRINTS
/obj/effect/decal/cleanable/blood/footprints
@@ -127,15 +80,16 @@
random_icon_states = null
var/entered_dirs = 0
var/exited_dirs = 0
- blood_state = BLOOD_STATE_HUMAN //the icon state to load images from
+ blood_state = BLOOD_STATE_BLOOD //the icon state to load images from
var/list/shoe_types = list()
/obj/effect/decal/cleanable/blood/footprints/Crossed(atom/movable/O)
- ..()
if(ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/clothing/shoes/S = H.shoes
if(S && S.bloody_shoes[blood_state])
+ if(color != bloodtype_to_color(S.last_bloodtype))
+ return
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
shoe_types |= S.type
if (!(entered_dirs & H.dir))
@@ -143,21 +97,21 @@
update_icon()
/obj/effect/decal/cleanable/blood/footprints/Uncrossed(atom/movable/O)
- ..()
if(ishuman(O))
var/mob/living/carbon/human/H = O
var/obj/item/clothing/shoes/S = H.shoes
if(S && S.bloody_shoes[blood_state])
+ if(color != bloodtype_to_color(S.last_bloodtype))//last entry - we check its color
+ return
S.bloody_shoes[blood_state] = max(S.bloody_shoes[blood_state] - BLOOD_LOSS_PER_STEP, 0)
shoe_types |= S.type
if (!(exited_dirs & H.dir))
exited_dirs |= H.dir
update_icon()
-
/obj/effect/decal/cleanable/blood/footprints/update_icon()
+ ..()
cut_overlays()
-
for(var/Ddir in GLOB.cardinals)
if(entered_dirs & Ddir)
var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["entered-[blood_state]-[Ddir]"]
@@ -170,7 +124,7 @@
GLOB.bloody_footprints_cache["exited-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]2", dir = Ddir)
add_overlay(bloodstep_overlay)
- alpha = BLOODY_FOOTPRINT_BASE_ALPHA+bloodiness
+ alpha = BLOODY_FOOTPRINT_BASE_ALPHA + bloodiness
/obj/effect/decal/cleanable/blood/footprints/examine(mob/user)
@@ -179,16 +133,62 @@
. += "You recognise the footprints as belonging to:\n"
for(var/shoe in shoe_types)
var/obj/item/clothing/shoes/S = shoe
- . += "[icon2html(initial(S.icon), user)] Some [initial(S.name)].\n"
+ . += "some [initial(S.name)] [icon2html(initial(S.icon), user)]\n"
to_chat(user, .)
/obj/effect/decal/cleanable/blood/footprints/replace_decal(obj/effect/decal/cleanable/C)
if(blood_state != C.blood_state) //We only replace footprints of the same type as us
return
+ if(color != C.color)
+ return
..()
/obj/effect/decal/cleanable/blood/footprints/can_bloodcrawl_in()
if((blood_state != BLOOD_STATE_OIL) && (blood_state != BLOOD_STATE_NOT_BLOODY))
- return 1
- return 0
+ return TRUE
+ return FALSE
+
+/* Eventually TODO: make snowflake trails like baycode's
+/obj/effect/decal/cleanable/blood/footprints/tracks/shoe
+ name = "footprints"
+ desc = "They look like tracks left by footwear."
+ icon_state = FOOTPRINT_SHOE
+ print_state = FOOTPRINT_SHOE
+
+/obj/effect/decal/cleanable/blood/footprints/tracks/foot
+ name = "footprints"
+ desc = "They look like tracks left by a bare foot."
+ icon_state = FOOTPRINT_FOOT
+ print_state = FOOTPRINT_FOOT
+
+/obj/effect/decal/cleanable/blood/footprints/tracks/snake
+ name = "tracks"
+ desc = "They look like tracks left by a giant snake."
+ icon_state = FOOTPRINT_SNAKE
+ print_state = FOOTPRINT_SNAKE
+
+/obj/effect/decal/cleanable/blood/footprints/tracks/paw
+ name = "footprints"
+ desc = "They look like tracks left by paws."
+ icon_state = FOOTPRINT_PAW
+ print_state = FOOTPRINT_PAW
+
+/obj/effect/decal/cleanable/blood/footprints/tracks/claw
+ name = "footprints"
+ desc = "They look like tracks left by claws."
+ icon_state = FOOTPRINT_CLAW
+ print_state = FOOTPRINT_CLAW
+
+/obj/effect/decal/cleanable/blood/footprints/tracks/wheels
+ name = "tracks"
+ desc = "They look like tracks left by wheels."
+ gender = PLURAL
+ icon_state = FOOTPRINT_WHEEL
+ print_state = FOOTPRINT_WHEEL
+
+/obj/effect/decal/cleanable/blood/footprints/tracks/body
+ name = "trails"
+ desc = "A trail left by something being dragged."
+ icon_state = FOOTPRINT_DRAG
+ print_state = FOOTPRINT_DRAG */
diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm
index 484e0438e2..02bf51bdd9 100644
--- a/code/game/objects/effects/decals/cleanable/robots.dm
+++ b/code/game/objects/effects/decals/cleanable/robots.dm
@@ -11,6 +11,10 @@
bloodiness = BLOOD_AMOUNT_PER_DECAL
mergeable_decal = FALSE
+/obj/effect/decal/cleanable/robot_debris/Initialize(mapload, list/datum/disease/diseases)
+ . = ..()
+ reagents.add_reagent("liquidoilgibs", 5)
+
/obj/effect/decal/cleanable/robot_debris/proc/streak(list/directions)
set waitfor = 0
var/direction = pick(directions)
@@ -50,6 +54,7 @@
/obj/effect/decal/cleanable/oil/Initialize()
. = ..()
reagents.add_reagent("oil", 30)
+ reagents.add_reagent("liquidoilgibs", 5)
/obj/effect/decal/cleanable/oil/streak
random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5")
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 32d91ee76a..08f698e018 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -170,7 +170,7 @@
if(!victim.client || !istype(victim))
return
to_chat(victim, "You feel fast!")
- ADD_TRAIT(victim, TRAIT_GOTTAGOREALLYFAST, "yellow_orb")
+ victim.add_movespeed_modifier(MOVESPEED_ID_YELLOW_ORB, update=TRUE, priority=100, multiplicative_slowdown=-2, blacklisted_movetypes=(FLYING|FLOATING))
sleep(duration)
- REMOVE_TRAIT(victim, TRAIT_GOTTAGOREALLYFAST, "yellow_orb")
+ victim.remove_movespeed_modifier(MOVESPEED_ID_YELLOW_ORB)
to_chat(victim, "You slow down.")
diff --git a/code/game/objects/effects/proximity.dm b/code/game/objects/effects/proximity.dm
index de17582f27..6c9525008d 100644
--- a/code/game/objects/effects/proximity.dm
+++ b/code/game/objects/effects/proximity.dm
@@ -5,7 +5,6 @@
var/list/checkers //list of /obj/effect/abstract/proximity_checkers
var/current_range
var/ignore_if_not_on_turf //don't check turfs in range if the host's loc isn't a turf
- var/datum/component/movement_tracker
/datum/proximity_monitor/New(atom/_host, range, _ignore_if_not_on_turf = TRUE)
checkers = list()
@@ -15,15 +14,17 @@
SetHost(_host)
/datum/proximity_monitor/proc/SetHost(atom/H,atom/R)
+ if(H == host)
+ return
+ if(host)
+ UnregisterSignal(host, COMSIG_MOVABLE_MOVED)
if(R)
hasprox_receiver = R
else if(hasprox_receiver == host) //Default case
hasprox_receiver = H
host = H
+ RegisterSignal(host, COMSIG_MOVABLE_MOVED, .proc/HandleMove)
last_host_loc = host.loc
- if(movement_tracker)
- QDEL_NULL(movement_tracker)
- movement_tracker = host.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/HandleMove)))
SetRange(current_range,TRUE)
/datum/proximity_monitor/Destroy()
@@ -31,7 +32,6 @@
last_host_loc = null
hasprox_receiver = null
QDEL_LIST(checkers)
- QDEL_NULL(movement_tracker)
return ..()
/datum/proximity_monitor/proc/HandleMove()
diff --git a/code/game/objects/effects/spawners/gibspawner.dm b/code/game/objects/effects/spawners/gibspawner.dm
index e99a2fcbc6..dd39bc567a 100644
--- a/code/game/objects/effects/spawners/gibspawner.dm
+++ b/code/game/objects/effects/spawners/gibspawner.dm
@@ -1,25 +1,69 @@
/obj/effect/gibspawner
- var/sparks = 0 //whether sparks spread
+ var/sparks = FALSE //whether sparks spread
var/virusProb = 20 //the chance for viruses to spread on the gibs
+ var/gib_mob_type //generate a fake mob to transfer DNA from if we weren't passed a mob.
+ var/gib_mob_species //We'll want to nip-pick their species for blood type stuff
+ var/sound_to_play = 'sound/effects/blobattack.ogg'
+ var/sound_vol = 60
var/list/gibtypes = list() //typepaths of the gib decals to spawn
var/list/gibamounts = list() //amount to spawn for each gib decal type we'll spawn.
var/list/gibdirections = list() //of lists of possible directions to spread each gib decal type towards.
-/obj/effect/gibspawner/Initialize(mapload, datum/dna/MobDNA, list/datum/disease/diseases)
+/obj/effect/gibspawner/Initialize(mapload, mob/living/source_mob, list/datum/disease/diseases)
. = ..()
-
- if(gibtypes.len != gibamounts.len || gibamounts.len != gibdirections.len)
- to_chat(world, "Gib list length mismatch!")
+ if(gibtypes.len != gibamounts.len)
+ stack_trace("Gib list amount length mismatch!")
+ return
+ if(gibamounts.len != gibdirections.len)
+ stack_trace("Gib list dir length mismatch!")
return
var/obj/effect/decal/cleanable/blood/gibs/gib = null
+ if(sound_to_play && isnum(sound_vol))
+ playsound(src, sound_to_play, sound_vol, TRUE)
+
if(sparks)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(2, 1, loc)
s.start()
+ var/list/dna_to_add //find the dna to pass to the spawned gibs. do note this can be null if the mob doesn't have blood. add_blood_DNA() has built in null handling.
+ var/body_coloring = ""
+ if(source_mob)
+ dna_to_add = source_mob.get_blood_dna_list() //ez pz
+ if(ishuman(source_mob))
+ var/mob/living/carbon/human/H = source_mob
+ if(H.dna.species.use_skintones)
+ body_coloring = "#[skintone2hex(H.skin_tone)]"
+ else
+ body_coloring = "#[H.dna.features["mcolor"]]"
+
+ else if(gib_mob_type)
+ var/mob/living/temp_mob = new gib_mob_type(src) //generate a fake mob so that we pull the right type of DNA for the gibs.
+ if(gib_mob_species)
+ if(ishuman(temp_mob))
+ var/mob/living/carbon/human/H = temp_mob
+ H.set_species(gib_mob_species)
+ dna_to_add = temp_mob.get_blood_dna_list()
+ if(H.dna.species.use_skintones)
+ body_coloring = "#[skintone2hex(H.skin_tone)]"
+ else
+ body_coloring = "#[H.dna.features["mcolor"]]"
+ qdel(H)
+ else
+ dna_to_add = temp_mob.get_blood_dna_list()
+ qdel(temp_mob)
+ else if(!issilicon(temp_mob))
+ dna_to_add = temp_mob.get_blood_dna_list()
+ qdel(temp_mob)
+ else
+ qdel(temp_mob)
+ else
+ dna_to_add = list("Non-human DNA" = random_blood_type()) //else, generate a random bloodtype for it.
+
+
for(var/i = 1, i<= gibtypes.len, i++)
if(gibamounts[i])
for(var/j = 1, j<= gibamounts[i], j++)
@@ -29,10 +73,11 @@
var/mob/living/carbon/digester = loc
digester.stomach_contents += gib
- if(MobDNA)
+ if(dna_to_add && dna_to_add.len)
+ gib.add_blood_DNA(dna_to_add)
+ gib.body_colors = body_coloring
+ gib.update_icon()
- else if(istype(src, /obj/effect/gibspawner/generic)) // Probably a monkey
- gib.add_blood_DNA(list("Non-human DNA" = "A+"))
var/list/directions = gibdirections[i]
if(isturf(loc))
if(directions.len)
@@ -41,80 +86,158 @@
return INITIALIZE_HINT_QDEL
-
/obj/effect/gibspawner/generic
gibtypes = list(/obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs/core)
- gibamounts = list(2,2,1)
+ gibamounts = list(2, 2, 1)
+ sound_vol = 40
/obj/effect/gibspawner/generic/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 40, 1)
- gibdirections = list(list(WEST, NORTHWEST, SOUTHWEST, NORTH),list(EAST, NORTHEAST, SOUTHEAST, SOUTH), list())
- . = ..()
+ if(!gibdirections.len)
+ gibdirections = list(list(WEST, NORTHWEST, SOUTHWEST, NORTH),list(EAST, NORTHEAST, SOUTHEAST, SOUTH), list())
+ return ..()
+
+/obj/effect/gibspawner/generic/animal
+ gib_mob_type = /mob/living/simple_animal/pet
/obj/effect/gibspawner/human
- gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/up, /obj/effect/decal/cleanable/blood/gibs/down, /obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs/body, /obj/effect/decal/cleanable/blood/gibs/limb, /obj/effect/decal/cleanable/blood/gibs/core)
- gibamounts = list(1,1,1,1,1,1,1)
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/human/up, /obj/effect/decal/cleanable/blood/gibs/human/down, /obj/effect/decal/cleanable/blood/gibs/human, /obj/effect/decal/cleanable/blood/gibs/human, /obj/effect/decal/cleanable/blood/gibs/human/body, /obj/effect/decal/cleanable/blood/gibs/human/limb, /obj/effect/decal/cleanable/blood/gibs/human/core)
+ gibamounts = list(1, 1, 1, 1, 1, 1, 1)
+ gib_mob_type = /mob/living/carbon/human
+ gib_mob_species = /datum/species/human
+ sound_vol = 50
/obj/effect/gibspawner/human/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 50, 1)
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
- . = ..()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
+ return ..()
-
-/obj/effect/gibspawner/humanbodypartless //only the gibs that don't look like actual full bodyparts (except torso).
- gibtypes = list(/obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs/core, /obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs/core, /obj/effect/decal/cleanable/blood/gibs, /obj/effect/decal/cleanable/blood/gibs/torso)
+/obj/effect/gibspawner/human/bodypartless //only the gibs that don't look like actual full bodyparts (except torso).
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/human, /obj/effect/decal/cleanable/blood/gibs/human/core, /obj/effect/decal/cleanable/blood/gibs/human, /obj/effect/decal/cleanable/blood/gibs/human/core, /obj/effect/decal/cleanable/blood/gibs/human, /obj/effect/decal/cleanable/blood/gibs/human/torso)
gibamounts = list(1, 1, 1, 1, 1, 1)
-/obj/effect/gibspawner/humanbodypartless/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 50, 1)
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
- . = ..()
+/obj/effect/gibspawner/human/bodypartless/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
+ return ..()
+/obj/effect/gibspawner/lizard
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/human/lizard/up, /obj/effect/decal/cleanable/blood/gibs/human/lizard/down, /obj/effect/decal/cleanable/blood/gibs/human/lizard, /obj/effect/decal/cleanable/blood/gibs/human/lizard, /obj/effect/decal/cleanable/blood/gibs/human/lizard/body, /obj/effect/decal/cleanable/blood/gibs/human/lizard/limb, /obj/effect/decal/cleanable/blood/gibs/human/lizard/core)
+ gibamounts = list(1, 1, 1, 1, 1, 1, 1)
+ gib_mob_type = /mob/living/carbon/human/species/lizard
+ gib_mob_species = /datum/species/lizard
+ sound_vol = 50
+
+/obj/effect/gibspawner/lizard/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
+ return ..()
+
+/obj/effect/gibspawner/lizard/bodypartless
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/human/lizard, /obj/effect/decal/cleanable/blood/gibs/human/lizard/core, /obj/effect/decal/cleanable/blood/gibs/human/lizard, /obj/effect/decal/cleanable/blood/gibs/human/lizard/core, /obj/effect/decal/cleanable/blood/gibs/human/lizard, /obj/effect/decal/cleanable/blood/gibs/human/lizard/torso)
+ gibamounts = list(1, 1, 1, 1, 1, 1)
+
+/obj/effect/gibspawner/lizard/bodypartless/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
+ return ..()
+
+/obj/effect/gibspawner/slime
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/slime/up, /obj/effect/decal/cleanable/blood/gibs/slime/down, /obj/effect/decal/cleanable/blood/gibs/slime, /obj/effect/decal/cleanable/blood/gibs/slime, /obj/effect/decal/cleanable/blood/gibs/slime/body, /obj/effect/decal/cleanable/blood/gibs/slime/limb, /obj/effect/decal/cleanable/blood/gibs/slime/core)
+ gibamounts = list(1, 1, 1, 1, 1, 1, 1)
+ gib_mob_type = /mob/living/carbon/human/species/roundstartslime
+ gib_mob_species = /datum/species/jelly/roundstartslime
+ sound_vol = 50
+
+/obj/effect/gibspawner/slime/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
+ return ..()
+
+/obj/effect/gibspawner/slime/bodypartless //only the gibs that don't look like actual full bodyparts (except torso).
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/slime, /obj/effect/decal/cleanable/blood/gibs/slime/core, /obj/effect/decal/cleanable/blood/gibs/slime, /obj/effect/decal/cleanable/blood/gibs/slime/core, /obj/effect/decal/cleanable/blood/gibs/slime, /obj/effect/decal/cleanable/blood/gibs/slime/torso)
+ gibamounts = list(1, 1, 1, 1, 1, 1)
+
+/obj/effect/gibspawner/slime/bodypartless/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
+ return ..()
+
+/obj/effect/gibspawner/ipc
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/ipc/up, /obj/effect/decal/cleanable/blood/gibs/ipc/down, /obj/effect/decal/cleanable/blood/gibs/ipc, /obj/effect/decal/cleanable/blood/gibs/ipc, /obj/effect/decal/cleanable/blood/gibs/ipc/body, /obj/effect/decal/cleanable/blood/gibs/ipc/limb, /obj/effect/decal/cleanable/blood/gibs/ipc/core)
+ gibamounts = list(1, 1, 1, 1, 1, 1, 1)
+ gib_mob_type = /mob/living/carbon/human/species/ipc
+ gib_mob_species = /datum/species/ipc
+ sound_vol = 50
+ sparks = TRUE
+ sound_to_play = 'sound/effects/bang.ogg'
+
+/obj/effect/gibspawner/ipc/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
+ return ..()
+
+/obj/effect/gibspawner/ipc/bodypartless //only the gibs that don't look like actual full bodyparts (except torso).
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/ipc, /obj/effect/decal/cleanable/blood/gibs/ipc/core, /obj/effect/decal/cleanable/blood/gibs/ipc, /obj/effect/decal/cleanable/blood/gibs/ipc/core, /obj/effect/decal/cleanable/blood/gibs/ipc, /obj/effect/decal/cleanable/blood/gibs/ipc/torso)
+ gibamounts = list(1, 1, 1, 1, 1, 1)
+
+/obj/effect/gibspawner/ipc/bodypartless/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
+ return ..()
/obj/effect/gibspawner/xeno
- gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs/up, /obj/effect/decal/cleanable/xenoblood/xgibs/down, /obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs/body, /obj/effect/decal/cleanable/xenoblood/xgibs/limb, /obj/effect/decal/cleanable/xenoblood/xgibs/core)
- gibamounts = list(1,1,1,1,1,1,1)
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/xeno/up, /obj/effect/decal/cleanable/blood/gibs/xeno/down, /obj/effect/decal/cleanable/blood/gibs/xeno, /obj/effect/decal/cleanable/blood/gibs/xeno, /obj/effect/decal/cleanable/blood/gibs/xeno/body, /obj/effect/decal/cleanable/blood/gibs/xeno/limb, /obj/effect/decal/cleanable/blood/gibs/xeno/core)
+ gibamounts = list(1, 1, 1, 1, 1, 1, 1)
+ gib_mob_type = /mob/living/carbon/alien
/obj/effect/gibspawner/xeno/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 60, 1)
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
- . = ..()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs, list())
+ return ..()
-
-/obj/effect/gibspawner/xenobodypartless //only the gibs that don't look like actual full bodyparts (except torso).
- gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs/core, /obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs/core, /obj/effect/decal/cleanable/xenoblood/xgibs, /obj/effect/decal/cleanable/xenoblood/xgibs/torso)
+/obj/effect/gibspawner/xeno/bodypartless //only the gibs that don't look like actual full bodyparts (except torso).
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/xeno, /obj/effect/decal/cleanable/blood/gibs/xeno/core, /obj/effect/decal/cleanable/blood/gibs/xeno, /obj/effect/decal/cleanable/blood/gibs/xeno/core, /obj/effect/decal/cleanable/blood/gibs/xeno, /obj/effect/decal/cleanable/blood/gibs/xeno/torso)
gibamounts = list(1, 1, 1, 1, 1, 1)
+/obj/effect/gibspawner/xeno/bodypartless/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
+ return ..()
-/obj/effect/gibspawner/xenobodypartless/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 60, 1)
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, list())
- . = ..()
+/obj/effect/gibspawner/xeno/xenoperson
+ gib_mob_type = /mob/living/carbon/human/species/xeno
+ gib_mob_species = /datum/species/xeno
+
+/obj/effect/gibspawner/xeno/xenoperson/bodypartless
/obj/effect/gibspawner/larva
- gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva/body, /obj/effect/decal/cleanable/xenoblood/xgibs/larva/body)
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/xeno/larva, /obj/effect/decal/cleanable/blood/gibs/xeno/larva, /obj/effect/decal/cleanable/blood/gibs/xeno/larva/body, /obj/effect/decal/cleanable/blood/gibs/xeno/larva/body)
gibamounts = list(1, 1, 1, 1)
+ gib_mob_type = /mob/living/carbon/alien/larva
/obj/effect/gibspawner/larva/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 60, 1)
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST), list(), GLOB.alldirs)
- . = ..()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST), list(), GLOB.alldirs)
+ return ..()
-/obj/effect/gibspawner/larvabodypartless
- gibtypes = list(/obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva, /obj/effect/decal/cleanable/xenoblood/xgibs/larva)
+/obj/effect/gibspawner/larva/bodypartless
+ gibtypes = list(/obj/effect/decal/cleanable/blood/gibs/xeno/larva, /obj/effect/decal/cleanable/blood/gibs/xeno/larva, /obj/effect/decal/cleanable/blood/gibs/xeno/larva)
gibamounts = list(1, 1, 1)
-/obj/effect/gibspawner/larvabodypartless/Initialize()
- playsound(src, 'sound/effects/blobattack.ogg', 60, 1)
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST), list())
- . = ..()
+/obj/effect/gibspawner/larva/bodypartless/Initialize()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST), list())
+ return ..()
/obj/effect/gibspawner/robot
- sparks = 1
+ sparks = TRUE
gibtypes = list(/obj/effect/decal/cleanable/robot_debris/up, /obj/effect/decal/cleanable/robot_debris/down, /obj/effect/decal/cleanable/robot_debris, /obj/effect/decal/cleanable/robot_debris, /obj/effect/decal/cleanable/robot_debris, /obj/effect/decal/cleanable/robot_debris/limb)
- gibamounts = list(1,1,1,1,1,1)
+ gibamounts = list(1, 1, 1, 1, 1, 1)
+ gib_mob_type = /mob/living/silicon/robot
/obj/effect/gibspawner/robot/Initialize()
- gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs)
- gibamounts[6] = pick(0,1,2)
- . = ..()
+ if(!gibdirections.len)
+ gibdirections = list(list(NORTH, NORTHEAST, NORTHWEST),list(SOUTH, SOUTHEAST, SOUTHWEST),list(WEST, NORTHWEST, SOUTHWEST),list(EAST, NORTHEAST, SOUTHEAST), GLOB.alldirs, GLOB.alldirs)
+ gibamounts[6] = pick(0, 1, 2)
+ return ..()
+
diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
index 7d02d9d383..fbad000098 100644
--- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm
+++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm
@@ -6,7 +6,9 @@
layer = BELOW_MOB_LAYER
var/splatter_type = "splatter"
-/obj/effect/temp_visual/dir_setting/bloodsplatter/Initialize(mapload, set_dir)
+/obj/effect/temp_visual/dir_setting/bloodsplatter/Initialize(mapload, set_dir, new_color)
+ if(new_color)
+ color = new_color
if(set_dir in GLOB.diagonals)
icon_state = "[splatter_type][pick(1, 2, 6)]"
else
@@ -41,7 +43,7 @@
animate(src, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = duration)
/obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter
- splatter_type = "xsplatter"
+ color = BLOOD_COLOR_XENO
/obj/effect/temp_visual/dir_setting/speedbike_trail
name = "speedbike trails"
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 6a706fede9..953036e970 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -97,9 +97,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
// non-clothing items
var/datum/dog_fashion/dog_fashion = null
- var/datum/rpg_loot/rpg_loot = null
-
-
//Tooltip vars
var/force_string //string form of an item's force. Edit this var only to set a custom force string
var/last_force_string_check = 0
@@ -111,7 +108,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/list/grind_results //A reagent list containing the reagents this item produces when ground up in a grinder - this can be an empty list to allow for reagent transferring only
var/list/juice_results //A reagent list containing blah blah... but when JUICED in a grinder!
-
/obj/item/Initialize()
materials = typelist("materials", materials)
@@ -125,7 +121,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
actions_types = null
if(GLOB.rpg_loot_items)
- rpg_loot = new(src)
+ AddComponent(/datum/component/fantasy)
if(force_string)
item_flags |= FORCE_STRING_OVERRIDE
@@ -150,7 +146,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
m.temporarilyRemoveItemFromInventory(src, TRUE)
for(var/X in actions)
qdel(X)
- QDEL_NULL(rpg_loot)
return ..()
/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
@@ -408,12 +403,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot)
for(var/X in actions)
var/datum/action/A = X
- if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot.
+ if(item_action_slot_check(slot, user, A)) //some items only give their actions buttons when in a specific slot.
A.Grant(user)
item_flags |= IN_INVENTORY
//sometimes we only want to grant the item's action if it's equipped in a specific slot.
-/obj/item/proc/item_action_slot_check(slot, mob/user)
+/obj/item/proc/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_IN_BACKPACK || slot == SLOT_LEGCUFFED) //these aren't true slots, so avoid granting actions there
return FALSE
return TRUE
@@ -537,6 +532,17 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
M.become_blind(EYE_DAMAGE)
to_chat(M, "You go blind!")
+/obj/item/clean_blood()
+ . = ..()
+ if(.)
+ if(blood_splatter_icon)
+ cut_overlay(blood_splatter_icon)
+
+/obj/item/clothing/gloves/clean_blood()
+ . = ..()
+ if(.)
+ transfer_blood = 0
+
/obj/item/singularity_pull(S, current_size)
..()
if(current_size >= STAGE_FOUR)
@@ -547,7 +553,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
/obj/item/throw_impact(atom/A, datum/thrownthing/throwingdatum)
if(A && !QDELETED(A))
SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, A, throwingdatum)
- if(is_hot() && isliving(A))
+ if(get_temperature() && isliving(A))
var/mob/living/L = A
L.IgniteMob()
var/itempush = 1
@@ -614,10 +620,10 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
if(flags & ITEM_SLOT_NECK)
owner.update_inv_neck()
-/obj/item/proc/is_hot()
+/obj/item/proc/get_temperature()
return heat
-/obj/item/proc/is_sharp()
+/obj/item/proc/get_sharpness()
return sharpness
/obj/item/proc/get_dismemberment_chance(obj/item/bodypart/affecting)
@@ -644,7 +650,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
location.hotspot_expose(flame_heat, 1)
/obj/item/proc/ignition_effect(atom/A, mob/user)
- if(is_hot())
+ if(get_temperature())
. = "[user] lights [A] with [src]."
else
. = ""
diff --git a/code/game/objects/items/RCD.dm b/code/game/objects/items/RCD.dm
index cf706359f7..8763089464 100644
--- a/code/game/objects/items/RCD.dm
+++ b/code/game/objects/items/RCD.dm
@@ -441,13 +441,16 @@ RLD
var/list/rcd_results = A.rcd_vals(user, src)
if(!rcd_results)
return FALSE
+ var/turf/the_turf = get_turf(A)
+ var/turf_coords = "[COORD(the_turf)]"
+ investigate_log("[user] is attempting to use [src] on [A] (loc [turf_coords] at [the_turf]) with cost [rcd_results["cost"]], delay [rcd_results["delay"]], mode [rcd_results["mode"]].", INVESTIGATE_RCD)
if(do_after(user, rcd_results["delay"] * delay_mod, target = A))
if(checkResource(rcd_results["cost"], user))
var/atom/cached = A
if(A.rcd_act(user, src, rcd_results["mode"]))
useResource(rcd_results["cost"], user)
activate()
- investigate_log("[user] used [src] on [cached] (now [A]) with cost [rcd_results["cost"]], delay [rcd_results["delay"]], mode [rcd_results["mode"]].", INVESTIGATE_RCD)
+ investigate_log("[user] used [src] on [cached] (loc [turf_coords] at [the_turf]) with cost [rcd_results["cost"]], delay [rcd_results["delay"]], mode [rcd_results["mode"]].", INVESTIGATE_RCD)
playsound(src, 'sound/machines/click.ogg', 50, 1)
return TRUE
diff --git a/code/game/objects/items/RCL.dm b/code/game/objects/items/RCL.dm
index 63f460f9aa..93293155a3 100644
--- a/code/game/objects/items/RCL.dm
+++ b/code/game/objects/items/RCL.dm
@@ -20,8 +20,8 @@
var/ghetto = FALSE
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
- var/datum/component/mobhook
var/datum/radial_menu/persistent/wiring_gui_menu
+ var/mob/listeningTo
/obj/item/twohanded/rcl/attackby(obj/item/W, mob/user)
if(istype(W, /obj/item/stack/cable_coil))
@@ -86,7 +86,7 @@
/obj/item/twohanded/rcl/Destroy()
QDEL_NULL(loaded)
last = null
- QDEL_NULL(mobhook)
+ listeningTo = null
QDEL_NULL(wiring_gui_menu)
return ..()
@@ -141,9 +141,8 @@
/obj/item/twohanded/rcl/dropped(mob/wearer)
..()
- if(mobhook)
- active = FALSE
- QDEL_NULL(mobhook)
+ UnregisterSignal(wearer, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
last = null
/obj/item/twohanded/rcl/attack_self(mob/user)
@@ -158,13 +157,12 @@
break
obj/item/twohanded/rcl/proc/getMobhook(mob/to_hook)
- if(to_hook)
- if(mobhook && mobhook.parent != to_hook)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = to_hook.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/trigger)))
- else
- QDEL_NULL(mobhook)
+ if(listeningTo == to_hook)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ RegisterSignal(to_hook, COMSIG_MOVABLE_MOVED, .proc/trigger)
+ listeningTo = to_hook
/obj/item/twohanded/rcl/proc/trigger(mob/user)
if(active)
diff --git a/code/game/objects/items/blueprints.dm b/code/game/objects/items/blueprints.dm
index 699efaac2e..10fbab56be 100644
--- a/code/game/objects/items/blueprints.dm
+++ b/code/game/objects/items/blueprints.dm
@@ -153,7 +153,9 @@
/area/centcom,
/area/asteroid,
/area/tdome,
- /area/wizard_station
+ /area/wizard_station,
+ /area/hilbertshotel,
+ /area/hilbertshotelstorage
)
for (var/type in SPECIALS)
if ( istype(A,type) )
diff --git a/code/game/objects/items/body_egg.dm b/code/game/objects/items/body_egg.dm
index ea72197cf0..f0d20afbbd 100644
--- a/code/game/objects/items/body_egg.dm
+++ b/code/game/objects/items/body_egg.dm
@@ -45,8 +45,8 @@
RemoveInfectionImages()
AddInfectionImages()
-/obj/item/organ/body_egg/proc/AddInfectionImages()
+/obj/item/organ/body_egg/proc/AddInfectionImages(mob/living/carbon/C)
return
-/obj/item/organ/body_egg/proc/RemoveInfectionImages()
+/obj/item/organ/body_egg/proc/RemoveInfectionImages(mob/living/carbon/C)
return
diff --git a/code/game/objects/items/candle.dm b/code/game/objects/items/candle.dm
index 1165501d9a..fa9c25960a 100644
--- a/code/game/objects/items/candle.dm
+++ b/code/game/objects/items/candle.dm
@@ -34,7 +34,7 @@
light() //honk
return ..()
-/obj/item/candle/is_hot()
+/obj/item/candle/get_temperature()
return lit * heat
/obj/item/candle/proc/light(show_message)
diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm
index 05ffcbf2fd..0e422a3fe9 100644
--- a/code/game/objects/items/cards_ids.dm
+++ b/code/game/objects/items/cards_ids.dm
@@ -80,6 +80,7 @@
righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
item_flags = NO_MAT_REDEMPTION | NOBLUDGEON
var/prox_check = TRUE //If the emag requires you to be in range
+ var/uses = 15
/obj/item/card/emag/bluespace
name = "bluespace cryptographic sequencer"
@@ -110,6 +111,37 @@
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/emag/examine(mob/user)
+ . = ..()
+ to_chat(user, "It has [uses ? uses : "no"] charges left.")
+
+/obj/item/card/emag/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/emagrecharge))
+ var/obj/item/emagrecharge/ER = W
+ if(ER.uses)
+ uses += ER.uses
+ to_chat(user, "You have added [ER.uses] charges to [src]. It now has [uses] charges.")
+ playsound(src, "sparks", 100, 1)
+ ER.uses = 0
+ else
+ to_chat(user, "[ER] has no charges left.")
+ return
+ . = ..()
+
+/obj/item/emagrecharge
+ name = "electromagnet charging device"
+ desc = "A small cell with two prongs lazily jabbed into it. It looks like it's made for charging the small batteries found in electromagnetic devices, sadly this can't be recharged like a normal cell."
+ icon = 'icons/obj/module.dmi'
+ icon_state = "cell_mini"
+ item_flags = NOBLUDGEON
+ var/uses = 5 //Dictates how many charges the device adds to compatible items
+
+/obj/item/emagrecharge/examine(mob/user)
+ . = ..()
+ if(uses)
+ to_chat(user, "It can add up to [uses] charges to compatible devices")
+ else
+ to_chat(user, "It has a small, red, blinking light coming from inside of it. It's spent.")
/obj/item/card/emagfake
desc = "It's a card with a magnetic strip attached to some circuitry. Closer inspection shows that this card is a poorly made replica, with a \"DonkCo\" logo stamped on the back."
@@ -342,12 +374,41 @@ update_label("John Doe", "Clowny")
lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
assignment = "Prisoner"
- registered_name = "Scum"
+ access = list(ACCESS_ENTER_GENPOP)
+
+ //Lavaland labor camp
var/goal = 0 //How far from freedom?
var/points = 0
+ //Genpop
+ var/sentence = 0 //When world.time is greater than this number, the card will have its ACCESS_ENTER_GENPOP access replaced with ACCESS_LEAVE_GENPOP the next time it's checked, unless this value is 0/null
+ var/crime= "\[REDACTED\]"
-/obj/item/card/id/prisoner/attack_self(mob/user)
- to_chat(usr, "You have accumulated [points] out of the [goal] points you need for freedom.")
+/obj/item/card/id/prisoner/GetAccess()
+ if((sentence && world.time >= sentence) || (goal && points >= goal))
+ access = list(ACCESS_LEAVE_GENPOP)
+ return ..()
+
+/obj/item/card/id/prisoner/process()
+ if(!sentence)
+ STOP_PROCESSING(SSobj, src)
+ return
+ if(world.time >= sentence)
+ playsound(loc, 'sound/machines/ping.ogg', 50, 1)
+ if(isliving(loc))
+ to_chat(loc, "[src] buzzes: You have served your sentence! You may now exit prison through the turnstiles and collect your belongings.")
+ STOP_PROCESSING(SSobj, src)
+ return
+
+/obj/item/card/id/prisoner/examine(mob/user)
+ . = ..()
+ if(sentence && world.time < sentence)
+ to_chat(user, "You're currently serving a sentence for [crime]. [DisplayTimeText(sentence - world.time)] left.")
+ else if(goal)
+ to_chat(user, "You have accumulated [points] out of the [goal] points you need for freedom.")
+ else if(!sentence)
+ to_chat(user, "You are currently serving a permanent sentence for [crime].")
+ else
+ to_chat(user, "Your sentence is up! You're free!")
/obj/item/card/id/prisoner/one
name = "Prisoner #13-001"
@@ -422,3 +483,58 @@ update_label("John Doe", "Clowny")
name = "APC Access ID"
desc = "A special ID card that allows access to APC terminals."
access = list(ACCESS_ENGINE_EQUIP)
+
+//Polychromatic Knight Badge
+
+/obj/item/card/id/knight
+ var/id_color = "#00FF00" //defaults to green
+ name = "knight badge"
+ icon_state = "knight"
+ desc = "A badge denoting the owner as a knight! It has a strip for swiping like an ID"
+
+/obj/item/card/id/knight/update_label(newname, newjob)
+ if(newname || newjob)
+ name = "[(!newname) ? "knight badge" : "[newname]'s Knight Badge"][(!newjob) ? "" : " ([newjob])"]"
+ return
+
+ name = "[(!registered_name) ? "knight badge" : "[registered_name]'s Knight Badge"][(!assignment) ? "" : " ([assignment])"]"
+
+/obj/item/card/id/knight/update_icon()
+ var/mutable_appearance/id_overlay = mutable_appearance(icon, "knight_overlay")
+
+ if(id_color)
+ id_overlay.color = id_color
+ cut_overlays()
+
+ add_overlay(id_overlay)
+
+/obj/item/card/id/knight/AltClick(mob/living/user)
+ . = ..()
+ if(!in_range(src, user)) //Basic checks to prevent abuse
+ return
+ if(user.incapacitated() || !istype(user))
+ to_chat(user, "You can't do that right now!")
+ return
+ if(alert("Are you sure you want to recolor your id?", "Confirm Repaint", "Yes", "No") == "Yes")
+ var/energy_color_input = input(usr,"","Choose Energy Color",id_color) as color|null
+ if(!in_range(src, user) || !energy_color_input)
+ return
+ if(user.incapacitated() || !istype(user))
+ to_chat(user, "You can't do that right now!")
+ return
+ id_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
+ update_icon()
+
+/obj/item/card/id/knight/Initialize()
+ . = ..()
+ update_icon()
+
+/obj/item/card/id/knight/examine(mob/user)
+ ..()
+ to_chat(user, "Alt-click to recolor it.")
+
+/obj/item/card/id/knight/blue
+ id_color = "#0000FF"
+
+/obj/item/card/id/knight/captain
+ id_color = "#FFD700"
\ No newline at end of file
diff --git a/code/game/objects/items/chrono_eraser.dm b/code/game/objects/items/chrono_eraser.dm
index 5db5aa416e..911a07c288 100644
--- a/code/game/objects/items/chrono_eraser.dm
+++ b/code/game/objects/items/chrono_eraser.dm
@@ -37,7 +37,7 @@
PA = new(src)
user.put_in_hands(PA)
-/obj/item/chrono_eraser/item_action_slot_check(slot, mob/user)
+/obj/item/chrono_eraser/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_BACK)
return 1
diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm
index 09a128c558..cf8d38d9c9 100644
--- a/code/game/objects/items/cigs_lighters.dm
+++ b/code/game/objects/items/cigs_lighters.dm
@@ -90,7 +90,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(istype(mask_item, /obj/item/clothing/mask/cigarette))
return mask_item
-/obj/item/match/is_hot()
+/obj/item/match/get_temperature()
return lit * heat
//////////////////
@@ -255,7 +255,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/clothing/mask/cigarette/fire_act(exposed_temperature, exposed_volume)
light()
-/obj/item/clothing/mask/cigarette/is_hot()
+/obj/item/clothing/mask/cigarette/get_temperature()
return lit * heat
// Cigarette brands.
@@ -530,7 +530,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
add_overlay(lighter_overlay)
/obj/item/lighter/ignition_effect(atom/A, mob/user)
- if(is_hot())
+ if(get_temperature())
. = "With a single flick of [user.p_their()] wrist, [user] smoothly lights [A] with [src]. Damn [user.p_theyre()] cool."
/obj/item/lighter/proc/set_lit(new_lit)
@@ -605,7 +605,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/lighter/process()
open_flame()
-/obj/item/lighter/is_hot()
+/obj/item/lighter/get_temperature()
return lit * heat
@@ -654,7 +654,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
add_overlay(lighter_overlay)
/obj/item/lighter/greyscale/ignition_effect(atom/A, mob/user)
- if(is_hot())
+ if(get_temperature())
. = "After some fiddling, [user] manages to light [A] with [src]."
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index 639d570462..1059a310eb 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -31,6 +31,15 @@
/obj/item/stock_parts/manipulator = 1,
/obj/item/stack/sheet/glass = 1)
+/obj/item/circuitboard/machine/bloodbankgen
+ name = "Blood Bank Generator (Machine Board)"
+ build_path = /obj/machinery/bloodbankgen
+ req_components = list(
+ /obj/item/stock_parts/matter_bin = 1,
+ /obj/item/stock_parts/manipulator = 1,
+ /obj/item/stack/cable_coil = 5,
+ /obj/item/stack/sheet/glass = 1)
+
/obj/item/circuitboard/machine/clonepod
name = "Clone Pod (Machine Board)"
build_path = /obj/machinery/clonepod
diff --git a/code/game/objects/items/control_wand.dm b/code/game/objects/items/control_wand.dm
index fa4524528b..c98484b81e 100644
--- a/code/game/objects/items/control_wand.dm
+++ b/code/game/objects/items/control_wand.dm
@@ -33,7 +33,7 @@
// Airlock remote works by sending NTNet packets to whatever it's pointed at.
/obj/item/door_remote/afterattack(atom/A, mob/user)
. = ..()
- GET_COMPONENT_FROM(target_interface, /datum/component/ntnet_interface, A)
+ var/datum/component/ntnet_interface/target_interface = A.GetComponent(/datum/component/ntnet_interface)
if(!target_interface)
return
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index 102c6a8eed..d014f70315 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -561,7 +561,7 @@
/obj/item/storage/crayons/Initialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 7
STR.can_hold = typecacheof(list(/obj/item/toy/crayon))
diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm
index a4f286bf88..f5799e1a22 100644
--- a/code/game/objects/items/defib.dm
+++ b/code/game/objects/items/defib.dm
@@ -39,7 +39,6 @@
/obj/item/defibrillator/loaded/Initialize() //starts with hicap
. = ..()
- paddles = make_paddles()
cell = new(src)
update_icon()
return
@@ -193,7 +192,7 @@
remove_paddles(user)
update_icon()
-/obj/item/defibrillator/item_action_slot_check(slot, mob/user)
+/obj/item/defibrillator/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == user.getBackSlot())
return 1
@@ -208,8 +207,8 @@
var/M = get(paddles, /mob)
remove_paddles(M)
QDEL_NULL(paddles)
- . = ..()
- update_icon()
+ QDEL_NULL(cell)
+ return ..()
/obj/item/defibrillator/proc/deductcharge(chrgdeductamt)
if(cell)
@@ -244,13 +243,12 @@
w_class = WEIGHT_CLASS_NORMAL
slot_flags = ITEM_SLOT_BELT
-/obj/item/defibrillator/compact/item_action_slot_check(slot, mob/user)
+/obj/item/defibrillator/compact/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == user.getBeltSlot())
return TRUE
/obj/item/defibrillator/compact/loaded/Initialize()
. = ..()
- paddles = make_paddles()
cell = new(src)
update_icon()
@@ -262,7 +260,6 @@
/obj/item/defibrillator/compact/combat/loaded/Initialize()
. = ..()
- paddles = make_paddles()
cell = new /obj/item/stock_parts/cell/infinite(src)
update_icon()
@@ -297,31 +294,28 @@
var/grab_ghost = FALSE
var/tlimit = DEFIB_TIME_LIMIT * 10
- var/datum/component/mobhook
+ var/mob/listeningTo
/obj/item/twohanded/shockpaddles/equipped(mob/user, slot)
. = ..()
- if(req_defib)
- if (mobhook && mobhook.parent != user)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/check_range)))
+ if(!req_defib)
+ return
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/check_range)
/obj/item/twohanded/shockpaddles/Moved()
. = ..()
check_range()
/obj/item/twohanded/shockpaddles/proc/check_range()
- if(!req_defib)
+ if(!req_defib || !defib)
return
if(!in_range(src,defib))
var/mob/living/L = loc
if(istype(L))
to_chat(L, "[defib]'s paddles overextend and come out of your hands!")
- L.temporarilyRemoveItemFromInventory(src,TRUE)
else
visible_message("[src] snap back into [defib].")
- snap_back()
+ snap_back()
/obj/item/twohanded/shockpaddles/proc/recharge(var/time)
if(req_defib || !time)
@@ -362,14 +356,14 @@
/obj/item/twohanded/shockpaddles/dropped(mob/user)
if(!req_defib)
return ..()
- if (mobhook)
- QDEL_NULL(mobhook)
if(user)
+ UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
var/obj/item/twohanded/offhand/O = user.get_inactive_held_item()
if(istype(O))
O.unwield()
- to_chat(user, "The paddles snap back into the main unit.")
- snap_back()
+ if(user != loc)
+ to_chat(user, "The paddles snap back into the main unit.")
+ snap_back()
return unwield(user)
/obj/item/twohanded/shockpaddles/proc/snap_back()
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index b0494539ce..92d936e0d4 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -274,7 +274,7 @@ GLOBAL_LIST_EMPTY(PDAs)
dat += text(" [id ? "Update PDA Info" : ""]
")
dat += "[STATION_TIME_TIMESTAMP("hh:mm:ss")] " //:[world.time / 100 % 6][world.time / 100 % 10]"
- dat += "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer+540]"
+ dat += "[time2text(world.realtime, "MMM DD")] [GLOB.year_integer]"
dat += "
"
diff --git a/code/game/objects/items/devices/PDA/virus_cart.dm b/code/game/objects/items/devices/PDA/virus_cart.dm
index d85c5d72d8..28bc559b93 100644
--- a/code/game/objects/items/devices/PDA/virus_cart.dm
+++ b/code/game/objects/items/devices/PDA/virus_cart.dm
@@ -70,7 +70,7 @@
difficulty++ //if cartridge has manifest access it has extra snowflake difficulty
else
difficulty += 2
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, target)
+ var/datum/component/uplink/hidden_uplink = target.GetComponent(/datum/component/uplink)
if(!target.detonatable || prob(difficulty * 15) || (hidden_uplink))
U.show_message("An error flashes on your [src].", 1)
else
@@ -95,7 +95,7 @@
charges--
var/lock_code = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
to_chat(U, "Virus Sent! The unlock code to the target is: [lock_code]")
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, target)
+ var/datum/component/uplink/hidden_uplink = target.GetComponent(/datum/component/uplink)
if(!hidden_uplink)
hidden_uplink = target.AddComponent(/datum/component/uplink)
hidden_uplink.unlock_code = lock_code
diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm
index 679dbecd10..7c21ac9144 100644
--- a/code/game/objects/items/devices/aicard.dm
+++ b/code/game/objects/items/devices/aicard.dm
@@ -17,6 +17,11 @@
desc = "A stylish upgrade (?) to the intelliCard."
icon_state = "aitater"
+/obj/item/aicard/aispook
+ name = "intelliLantern"
+ desc = "A spoOoOoky upgrade to the intelliCard."
+ icon_state = "aispook"
+
/obj/item/aicard/suicide_act(mob/living/user)
user.visible_message("[user] is trying to upload [user.p_them()]self into [src]! That's not going to work out well!")
return BRUTELOSS
@@ -26,16 +31,18 @@
if(!proximity || !target)
return
if(AI) //AI is on the card, implies user wants to upload it.
- target.transfer_ai(AI_TRANS_FROM_CARD, user, AI, src)
log_combat(user, AI, "carded", src)
+ target.transfer_ai(AI_TRANS_FROM_CARD, user, AI, src)
else //No AI on the card, therefore the user wants to download one.
target.transfer_ai(AI_TRANS_TO_CARD, user, null, src)
+ if(AI)
+ log_combat(user, AI, "carded", src)
update_icon() //Whatever happened, update the card's state (icon, name) to match.
/obj/item/aicard/update_icon()
cut_overlays()
if(AI)
- name = "[initial(name)]- [AI.name]"
+ name = "[initial(name)] - [AI.name]"
if(AI.stat == DEAD)
icon_state = "[initial(icon_state)]-404"
else
diff --git a/code/game/objects/items/devices/chameleonproj.dm b/code/game/objects/items/devices/chameleonproj.dm
index f39d2ba0d6..dffbb46cbb 100644
--- a/code/game/objects/items/devices/chameleonproj.dm
+++ b/code/game/objects/items/devices/chameleonproj.dm
@@ -116,7 +116,7 @@
appearance = saved_appearance
if(istype(M.buckled, /obj/vehicle))
var/obj/vehicle/V = M.buckled
- GET_COMPONENT_FROM(VRD, /datum/component/riding, V)
+ var/datum/component/riding/VRD = V.GetComponent(/datum/component/riding)
if(VRD)
VRD.force_dismount(M)
else
diff --git a/code/game/objects/items/devices/compressionkit.dm b/code/game/objects/items/devices/compressionkit.dm
index 5ac958328d..a5a9377690 100644
--- a/code/game/objects/items/devices/compressionkit.dm
+++ b/code/game/objects/items/devices/compressionkit.dm
@@ -89,30 +89,23 @@
else
to_chat(user, "Anomalous error. Summon a coder.")
- if(istype(target, /mob/living))
- var/mob/living/victim = target
- if(istype(victim, /mob/living/carbon/human))
- if(user.zone_selected == "groin") // pp smol. There's probably a smarter way to do this but im retarded. If you have a simpler method let me know.
- var/list/organs = victim.getorganszone("groin")
- for(var/internal_organ in organs)
- if(istype(internal_organ, /obj/item/organ/genital/penis))
- var/obj/item/organ/genital/penis/O = internal_organ
- playsound(get_turf(src), 'sound/weapons/flash.ogg', 50, 1)
- victim.visible_message("[user] is preparing to shrink [victim]\'s [O.name] with their bluespace compression kit!")
- if(do_mob(user, victim, 40) && charges > 0 && O.length > 0)
- victim.visible_message("[user] has shrunk [victim]\'s [O.name]!")
- playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 50, 1)
- sparks()
- flash_lighting_fx(3, 3, LIGHT_COLOR_CYAN)
- charges -= 1
- O.length -= 5
- if(O.length < 1)
- victim.visible_message("[user]\'s [O.name] vanishes!")
- qdel(O) // no pp for you
- else
- O.update_size()
- O.update_appearance()
-
+ else if(ishuman(target) && user.zone_selected == BODY_ZONE_PRECISE_GROIN)
+ var/mob/living/carbon/human/H = target
+ var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS)
+ if(!P)
+ return
+ playsound(get_turf(src), 'sound/weapons/flash.ogg', 50, 1)
+ H.visible_message("[user] is preparing to shrink [H]\'s [P.name] with their bluespace compression kit!")
+ if(do_mob(user, H, 40) && charges > 0 && P.length > 0)
+ H.visible_message("[user] has shrunk [H]\'s [P.name]!")
+ playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 50, 1)
+ sparks()
+ flash_lighting_fx(3, 3, LIGHT_COLOR_CYAN)
+ charges -= 1
+ var/p_name = P.name
+ P.modify_size(-5)
+ if(QDELETED(P))
+ H.visible_message("[H]\'s [p_name] vanishes!")
/obj/item/compressionkit/attackby(obj/item/I, mob/user, params)
diff --git a/code/game/objects/items/devices/dogborg_sleeper.dm b/code/game/objects/items/devices/dogborg_sleeper.dm
index c1a9136f76..3c945f464e 100644
--- a/code/game/objects/items/devices/dogborg_sleeper.dm
+++ b/code/game/objects/items/devices/dogborg_sleeper.dm
@@ -6,8 +6,7 @@
icon = 'icons/mob/dogborg.dmi'
icon_state = "sleeper"
w_class = WEIGHT_CLASS_TINY
- var/mob/living/carbon/patient = null
- var/mob/living/silicon/robot/hound = null
+ var/mob/living/carbon/patient
var/inject_amount = 10
var/min_health = -100
var/cleaning = FALSE
@@ -61,8 +60,18 @@
/obj/item/dogborg/sleeper/Exit(atom/movable/O)
return 0
+/obj/item/dogborg/sleeper/proc/get_host()
+ if(!loc)
+ return
+ if(iscyborg(loc))
+ return loc
+ else if(iscyborg(loc.loc))
+ return loc.loc //cursed cyborg code
+
/obj/item/dogborg/sleeper/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity)
- hound = loc
+ var/mob/living/silicon/robot/hound = get_host()
+ if(!hound)
+ return
if(!proximity)
return
if(!iscarbon(target))
@@ -82,7 +91,8 @@
if(!in_range(src, target)) //Proximity is probably old news by now, do a new check.
return //If they moved away, you can't eat them.
- if(patient) return //If you try to eat two people at once, you can only eat one.
+ if(patient)
+ return //If you try to eat two people at once, you can only eat one.
else //If you don't have someone in you, proceed.
if(!isjellyperson(target) && ("toxin" in injection_chems))
@@ -94,14 +104,17 @@
target.forceMove(src)
target.reset_perspective(src)
target.ExtinguishMob() //The tongue already puts out fire stacks but being put into the sleeper shouldn't allow you to keep burning.
- update_gut()
+ update_gut(hound)
user.visible_message("[voracious ? "[hound]'s [src.name] lights up and expands as [target] slips inside into their [src.name]." : "[hound]'s sleeper indicator lights up as [target] is scooped up into [hound.p_their()] [src]."]", \
"Your [voracious ? "[src.name] lights up as [target] slips into" : "sleeper indicator light shines brightly as [target] is scooped inside"] your [src]. Life support functions engaged.")
message_admins("[key_name(hound)] has sleeper'd [key_name(patient)] as a dogborg. [ADMIN_JMP(src)]")
playsound(hound, 'sound/effects/bin_close.ogg', 100, 1)
/obj/item/dogborg/sleeper/container_resist(mob/living/user)
- hound = loc
+ var/mob/living/silicon/robot/hound = get_host()
+ if(!hound)
+ go_out(user)
+ return
user.changeNext_move(CLICK_CD_BREAKOUT)
user.last_special = world.time + CLICK_CD_BREAKOUT
if(user.a_intent == INTENT_HELP)
@@ -113,55 +126,41 @@
"[voracious ? "You start struggling inside of [src]'s tight, flexible confines," : "You start pounding against the metallic walls of [src],"] trying to trigger the release... (this will take about [DisplayTimeText(breakout_time)].)", \
"You hear a [voracious ? "couple of thumps" : "loud banging noise"] coming from within [hound].")
if(do_after(user, breakout_time, target = src))
- if(!user || user.stat != CONSCIOUS || user.loc != src )
- return
user.visible_message("[user] successfully broke out of [hound.name]!", \
"You successfully break out of [hound.name]!")
- go_out()
+ go_out(user, hound)
-/obj/item/dogborg/sleeper/proc/go_out(var/target)
- hound = loc
- hound.setClickCooldown(50)
- var/voracious = TRUE
- if(!hound.client || !(hound.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
- voracious = FALSE
- else
- for(var/mob/M in contents)
- if(!M.client || !(M.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
- voracious = FALSE
- if(length(contents) > 0)
- hound.visible_message("[voracious ? "[hound] empties out [hound.p_their()] contents via [hound.p_their()] release port." : "[hound]'s underside slides open with an audible clunk before [hound.p_their()] [src] flips over, carelessly dumping its contents onto the ground below [hound.p_them()] before closing right back up again."]", \
- "[voracious ? "You empty your contents via your release port." : "You open your sleeper hatch, quickly releasing all of the contents within before closing it again."]")
- if(target)
- if(iscarbon(target))
- var/mob/living/carbon/person = target
- person.forceMove(get_turf(src))
- person.reset_perspective()
- else
- var/obj/T = target
- T.loc = hound.loc
+/obj/item/dogborg/sleeper/proc/go_out(atom/movable/target, mob/living/silicon/robot/hound)
+ var/voracious = hound ? TRUE : FALSE
+ var/list/targets = target && hound ? list(target) : contents
+ if(hound)
+ hound.setClickCooldown(50)
+ if(!hound.client || !(hound.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
+ voracious = FALSE
else
- for(var/C in contents)
- if(iscarbon(C))
- var/mob/living/carbon/person = C
- person.forceMove(get_turf(src))
- person.reset_perspective()
- else
- var/obj/T = C
- T.loc = hound.loc
- items_preserved.Cut()
- update_gut()
- cleaning = FALSE
+ for(var/mob/M in targets)
+ if(!M.client || !(M.client.prefs.cit_toggles & MEDIHOUND_SLEEPER))
+ voracious = FALSE
+ if(length(targets))
+ if(hound)
+ hound.visible_message("[voracious ? "[hound] empties out [hound.p_their()] contents via [hound.p_their()] release port." : "[hound]'s underside slides open with an audible clunk before [hound.p_their()] [src] flips over, carelessly dumping its contents onto the ground below [hound.p_them()] before closing right back up again."]", \
+ "[voracious ? "You empty your contents via your release port." : "You open your sleeper hatch, quickly releasing all of the contents within before closing it again."]")
+ for(var/a in contents)
+ var/atom/movable/AM = a
+ AM.forceMove(get_turf(src))
+ if(ismob(AM))
+ var/mob/M = AM
+ M.reset_perspective()
playsound(loc, voracious ? 'sound/effects/splat.ogg' : 'sound/effects/bin_close.ogg', 50, 1)
-
- else //You clicked eject with nothing in you, let's just reset stuff to be sure.
- items_preserved.Cut()
- cleaning = FALSE
- update_gut()
+ items_preserved.Cut()
+ cleaning = FALSE
+ if(hound)
+ update_gut(hound)
/obj/item/dogborg/sleeper/attack_self(mob/user)
- if(..())
+ . = ..()
+ if(. || !iscyborg(user))
return
ui_interact(user)
@@ -219,30 +218,31 @@
return data
/obj/item/dogborg/sleeper/ui_act(action, params)
- if(..())
+ . = ..()
+ if(. || !iscyborg(usr))
return
switch(action)
if("eject")
- go_out()
+ go_out(null, usr)
. = TRUE
if("inject")
var/chem = params["chem"]
if(!patient)
return
- inject_chem(chem)
+ inject_chem(chem, usr)
. = TRUE
if("cleaning")
if(!contents)
to_chat(src, "Your [src] is already cleaned.")
return
if(patient)
- to_chat(patient, "[hound.name]'s [src] fills with caustic enzymes around you!")
+ to_chat(patient, "[usr.name]'s [src] fills with caustic enzymes around you!")
to_chat(src, "Cleaning process enabled.")
- clean_cycle()
+ clean_cycle(usr)
. = TRUE
-/obj/item/dogborg/sleeper/proc/update_gut()
+/obj/item/dogborg/sleeper/proc/update_gut(mob/living/silicon/robot/hound)
//Well, we HAD one, what happened to them?
var/prociconupdate = FALSE
var/currentenvy = hound.sleeper_nv
@@ -291,7 +291,7 @@
//Update icon and return new patient
hound.update_icons()
- return(C)
+ return
//Cleaning looks better with red on, even with nobody in it
if(cleaning && !patient)
@@ -307,8 +307,10 @@
hound.update_icons()
//Gurgleborg process
-/obj/item/dogborg/sleeper/proc/clean_cycle()
+/obj/item/dogborg/sleeper/proc/clean_cycle(mob/living/silicon/robot/hound)
//Sanity
+ if(!hound)
+ return
for(var/I in items_preserved)
if(!(I in contents))
items_preserved -= I
@@ -320,13 +322,12 @@
if(cleaning_cycles)
cleaning_cycles--
cleaning = TRUE
- for(var/mob/living/carbon/human/T in (touchable_items))
- if((T.status_flags & GODMODE) || !T.digestable)
- items_preserved += T
+ for(var/mob/living/carbon/C in (touchable_items))
+ if((C.status_flags & GODMODE) || !C.digestable)
+ items_preserved += C
else
- T.adjustBruteLoss(2)
- T.adjustFireLoss(3)
- update_gut()
+ C.adjustBruteLoss(2)
+ C.adjustFireLoss(3)
if(contents)
var/atom/target = pick(touchable_items)
if(iscarbon(target)) //Handle the target being a mob
@@ -359,7 +360,6 @@
if(!T.dropItemToGround(W))
qdel(W)
qdel(T)
- update_gut()
//Handle the target being anything but a mob
else if(isobj(target))
var/obj/T = target
@@ -374,12 +374,10 @@
cleaning_cycles = initial(cleaning_cycles)
cleaning = FALSE
to_chat(hound, "Your [src] chimes it ends its self-cleaning cycle.")//Belly is entirely empty
- update_gut()
if(!length(contents))
to_chat(hound, "Your [src] is now clean. Ending self-cleaning cycle.")
cleaning = FALSE
- update_gut()
//sound effects
if(prob(50))
@@ -397,13 +395,17 @@
else if(H in contents)
H.playsound_local(source, null, 65, falloff = 0, S = prey_digest)
+ update_gut(hound)
+
if(cleaning)
- addtimer(CALLBACK(src, .proc/clean_cycle), 50)
+ addtimer(CALLBACK(src, .proc/clean_cycle, hound), 50)
/obj/item/dogborg/sleeper/proc/CheckAccepted(obj/item/I)
return is_type_in_typecache(I, important_items)
-/obj/item/dogborg/sleeper/proc/inject_chem(chem)
+/obj/item/dogborg/sleeper/proc/inject_chem(chem, mob/living/silicon/robot/hound)
+ if(!hound)
+ return
if(hound.cell.charge <= 800) //This is so borgs don't kill themselves with it. Remember, 750 charge used every injection.
to_chat(hound, "You don't have enough power to synthesize fluids.")
return
@@ -438,40 +440,27 @@
else
. = ..()
-/obj/item/dogborg/sleeper/K9/afterattack(var/atom/movable/target, mob/living/silicon/user, proximity)
- hound = loc
+/obj/item/dogborg/sleeper/K9/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity)
+ var/mob/living/silicon/robot/hound = get_host()
+ if(!hound || !istype(target) || !proximity || target.anchored)
+ return
+ if (!target.devourable)
+ to_chat(user, "The target registers an error code. Unable to insert into [src].")
+ return
+ if(target)
+ to_chat(user,"Your [src] is already occupied.")
+ return
+ if(target.buckled)
+ to_chat(user,"[target] is buckled and can not be put into your [src].")
+ return
+ user.visible_message("[hound.name] is ingesting [target] into their [src].", "You start ingesting [target] into your [src.name]...")
+ if(do_after(user, 30, target = target) && !patient && !target.buckled)
+ target.forceMove(src)
+ target.reset_perspective(src)
+ update_gut(hound)
+ user.visible_message("[hound.name]'s mobile brig clunks in series as [target] slips inside.", "Your mobile brig groans lightly as [target] slips inside.")
+ playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) // Really don't need ERP sound effects for robots
- if(!istype(target))
- return
- if(!proximity)
- return
- if(target.anchored)
- return
- if(isobj(target))
- to_chat(user, "You are above putting such trash inside of yourself.")
- return
- if(iscarbon(target))
- var/mob/living/carbon/brigman = target
- if (!brigman.devourable)
- to_chat(user, "The target registers an error code. Unable to insert into [src].")
- return
- if(patient)
- to_chat(user,"Your [src] is already occupied.")
- return
- if(brigman.buckled)
- to_chat(user,"[brigman] is buckled and can not be put into your [src].")
- return
- user.visible_message("[hound.name] is ingesting [brigman] into their [src].", "You start ingesting [brigman] into your [src.name]...")
- if(do_after(user, 30, target = brigman) && !patient && !brigman.buckled)
- if(!in_range(src, brigman)) //Proximity is probably old news by now, do a new check.
- return //If they moved away, you can't eat them.
- brigman.forceMove(src)
- brigman.reset_perspective(src)
- update_gut()
- user.visible_message("[hound.name]'s mobile brig clunks in series as [brigman] slips inside.", "Your mobile brig groans lightly as [brigman] slips inside.")
- playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) // Really don't need ERP sound effects for robots
- return
- return
/obj/item/dogborg/sleeper/compactor //Janihound gut.
name = "garbage processor"
@@ -489,31 +478,25 @@
else
. = ..()
-/obj/item/dogborg/sleeper/compactor/afterattack(var/atom/movable/target, mob/living/silicon/user, proximity)//GARBO NOMS
- hound = loc
- var/obj/item/target_obj = target
- if(!istype(target))
- return
- if(!proximity)
- return
- if(target.anchored)
+/obj/item/dogborg/sleeper/compactor/afterattack(atom/movable/target, mob/living/silicon/user, proximity)//GARBO NOMS
+ var/mob/living/silicon/robot/hound = get_host()
+ if(!hound || !istype(target) || !proximity || target.anchored)
return
if(length(contents) > (max_item_count - 1))
to_chat(user,"Your [src] is full. Eject or process contents to continue.")
return
- if(isobj(target))
- if(CheckAccepted(target))
- to_chat(user,"\The [target] registers an error code to your [src]")
+ if(isitem(target))
+ var/obj/item/I = target
+ if(CheckAccepted(I))
+ to_chat(user,"[I] registers an error code to your [src]")
return
- if(target_obj.w_class > WEIGHT_CLASS_NORMAL)
- to_chat(user,"\The [target] is too large to fit into your [src]")
+ if(I.w_class > WEIGHT_CLASS_NORMAL)
+ to_chat(user,"[I] is too large to fit into your [src]")
return
- user.visible_message("[hound.name] is ingesting [target.name] into their [src.name].", "You start ingesting [target] into your [src.name]...")
+ user.visible_message("[hound.name] is ingesting [I] into their [src.name].", "You start ingesting [target] into your [src.name]...")
if(do_after(user, 15, target = target) && length(contents) < max_item_count)
- if(!in_range(src, target)) //Proximity is probably old news by now, do a new check.
- return //If they moved away, you can't eat them. This still applies to items, don't magically eat things I picked up already.
- target.forceMove(src)
- user.visible_message("[hound.name]'s garbage processor groans lightly as [target.name] slips inside.", "Your garbage compactor groans lightly as [target] slips inside.")
+ I.forceMove(src)
+ I.visible_message("[hound.name]'s garbage processor groans lightly as [I] slips inside.", "Your garbage compactor groans lightly as [I] slips inside.")
playsound(hound, 'sound/machines/disposalflush.ogg', 50, 1)
if(length(contents) > 11) //grow that tum after a certain junk amount
hound.sleeper_r = 1
@@ -523,9 +506,9 @@
hound.update_icons()
return
- else if(iscarbon(target))
- var/mob/living/carbon/trashman = target
- if (!trashman.devourable)
+ if(iscarbon(target) || issilicon(target))
+ var/mob/living/trashman = target
+ if(!trashman.devourable)
to_chat(user, "[target] registers an error code to your [src]")
return
if(patient)
@@ -536,34 +519,8 @@
return
user.visible_message("[hound.name] is ingesting [trashman] into their [src].", "You start ingesting [trashman] into your [src.name]...")
if(do_after(user, 30, target = trashman) && !patient && !trashman.buckled && length(contents) < max_item_count)
- if(!in_range(src, trashman)) //Proximity is probably old news by now, do a new check.
- return //If they moved away, you can't eat them.
trashman.forceMove(src)
trashman.reset_perspective(src)
update_gut()
user.visible_message("[hound.name]'s garbage processor groans lightly as [trashman] slips inside.", "Your garbage compactor groans lightly as [trashman] slips inside.")
playsound(hound, 'sound/effects/bin_close.ogg', 80, 1)
- return
- else if(issilicon(target))
- var/mob/living/silicon/trashbot = target
- if (!trashbot.devourable)
- to_chat(user, "[target] registers an error code to your [src]")
- return
- if(patient)
- to_chat(user,"Your [src] is already occupied.")
- return
- if(trashbot.buckled)
- to_chat(user,"[trashbot] is buckled and can not be put into your [src].")
- return
- user.visible_message("[hound.name] is ingesting [trashbot] into their [src].", "You start ingesting [trashbot] into your [src.name]...")
- if(do_after(user, 30, target = trashbot) && !patient && !trashbot.buckled && length(contents) < max_item_count)
- if(!in_range(src, trashbot)) //Proximity is probably old news by now, do a new check.
- return //If they moved away, you can't eat them.
- trashbot.forceMove(src)
- trashbot.reset_perspective(src)
- update_gut()
- user.visible_message("[hound.name]'s garbage processor groans lightly as [trashbot] slips inside.", "Your garbage compactor groans lightly as [trashbot] slips inside.")
- playsound(hound, 'sound/effects/bin_close.ogg', 80, 1)
- return
-
- return
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index b937f961c0..8d7fa05ec6 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -324,7 +324,7 @@
damtype = "fire"
START_PROCESSING(SSobj, src)
-/obj/item/flashlight/flare/is_hot()
+/obj/item/flashlight/flare/get_temperature()
return on * heat
/obj/item/flashlight/flare/torch
diff --git a/code/game/objects/items/devices/geiger_counter.dm b/code/game/objects/items/devices/geiger_counter.dm
index 90cdd0386c..110676de1b 100644
--- a/code/game/objects/items/devices/geiger_counter.dm
+++ b/code/game/objects/items/devices/geiger_counter.dm
@@ -203,21 +203,25 @@
return TRUE
/obj/item/geiger_counter/cyborg
- var/datum/component/mobhook
+ var/mob/listeningTo
/obj/item/geiger_counter/cyborg/equipped(mob/user)
. = ..()
- if (mobhook && mobhook.parent != user)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_ATOM_RAD_ACT = CALLBACK(src, .proc/redirect_rad_act)))
+ if(listeningTo == user)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_ATOM_RAD_ACT)
+ RegisterSignal(user, COMSIG_ATOM_RAD_ACT, .proc/redirect_rad_act)
+ listeningTo = user
/obj/item/geiger_counter/cyborg/proc/redirect_rad_act(datum/source, amount)
rad_act(amount)
/obj/item/geiger_counter/cyborg/dropped()
. = ..()
- QDEL_NULL(mobhook)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_ATOM_RAD_ACT)
+ listeningTo = null
#undef RAD_LEVEL_NORMAL
#undef RAD_LEVEL_MODERATE
diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm
index 207497922e..cf55d4178e 100644
--- a/code/game/objects/items/devices/multitool.dm
+++ b/code/game/objects/items/devices/multitool.dm
@@ -48,7 +48,7 @@
/obj/item/multitool/chaplain/Initialize()
. = ..()
- AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
/obj/item/multitool/examine(mob/user)
..()
diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm
index 1f69db1bbc..7dc2f1d60b 100644
--- a/code/game/objects/items/devices/paicard.dm
+++ b/code/game/objects/items/devices/paicard.dm
@@ -148,9 +148,11 @@
if(10)
src.add_overlay("pai-null")
if(11)
- src.add_overlay(mutable_appearance('modular_citadel/icons/obj/aicards.dmi', "pai-exclamation")) // CITADEL EDIT
+ src.add_overlay("pai-exclamation")
if(12)
- src.add_overlay(mutable_appearance('modular_citadel/icons/obj/aicards.dmi', "pai-question")) // CITADEL EDIT
+ src.add_overlay("pai-question")
+ if(13)
+ src.add_overlay("pai-sunglasses")
/obj/item/paicard/proc/alertUpdate()
visible_message("[src] flashes a message across its screen, \"Additional personalities available for download.\"", "[src] bleeps electronically.")
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 7655654f78..5ad5b41e95 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -338,17 +338,17 @@ SLIME SCANNER
if(report_organs) //we either finish the list, or set it to be empty if no organs were reported in that category
if(!max_damage)
- max_damage = "\tNon-Functional Organs: "
+ max_damage = "\tNon-Functional Organs: \n"
else
- max_damage += ""
+ max_damage += "\n"
if(!major_damage)
- major_damage = "\tSeverely Damaged Organs: "
+ major_damage = "\tSeverely Damaged Organs: \n"
else
- major_damage += ""
+ major_damage += "\n"
if(!minor_damage)
- minor_damage = "\tMildly Damaged Organs: "
+ minor_damage = "\tMildly Damaged Organs: \n"
else
- minor_damage += ""
+ minor_damage += "\n"
msg += "[minor_damage]"
msg += "[major_damage]"
msg += "[max_damage]"
@@ -382,10 +382,11 @@ SLIME SCANNER
else if (S.mutantstomach != initial(S.mutantstomach))
mutant = TRUE
- msg += "Species: [H.dna.custom_species ? H.dna.custom_species : S.name] Base: [S.name]\n"
+ msg += "\tReported Species: [H.dna.custom_species ? H.dna.custom_species : S.name]\n"
+ msg += "\tBase Species: [S.name]\n"
if(mutant)
- msg += "Subject has mutations present."
- msg += "Body temperature: [round(M.bodytemperature-T0C,0.1)] °C ([round(M.bodytemperature*1.8-459.67,0.1)] °F)\n"
+ msg += "\tSubject has mutations present.\n"
+ msg += "\tBody temperature: [round(M.bodytemperature-T0C,0.1)] °C ([round(M.bodytemperature*1.8-459.67,0.1)] °F)\n"
// Time of death
if(M.tod && (M.stat == DEAD || ((HAS_TRAIT(M, TRAIT_FAKEDEATH)) && !advanced)))
@@ -410,7 +411,7 @@ SLIME SCANNER
msg += "Subject is bleeding!\n"
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
+ if(blood_id != ("blood" || "jellyblood"))//special blood substance
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
if(R)
blood_type = R.name
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index 2c234a59ba..fc768cd38e 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -195,7 +195,7 @@ effective or pretty fucking useless.
Deactivate()
return
-/obj/item/shadowcloak/item_action_slot_check(slot, mob/user)
+/obj/item/shadowcloak/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_BELT)
return 1
diff --git a/code/game/objects/items/eightball.dm b/code/game/objects/items/eightball.dm
index bdaa716075..9dc3e421fd 100644
--- a/code/game/objects/items/eightball.dm
+++ b/code/game/objects/items/eightball.dm
@@ -206,7 +206,7 @@
switch(action)
if("vote")
var/selected_answer = params["answer"]
- if(!selected_answer in possible_answers)
+ if(!(selected_answer in possible_answers))
return
else
votes[user.ckey] = selected_answer
diff --git a/code/game/objects/items/granters.dm b/code/game/objects/items/granters.dm
index fdb016df38..6ea68bf548 100644
--- a/code/game/objects/items/granters.dm
+++ b/code/game/objects/items/granters.dm
@@ -432,6 +432,14 @@
user.mind.teach_crafting_recipe(crafting_recipe_type)
to_chat(user,"You learned how to make [initial(R.name)].")
+/obj/item/book/granter/crafting_recipe/threads //Durathread crafting book
+ name = "Credible Threads"
+ desc = "A simple book about sewing and usefull clothing crafting with cloth and durathreads."
+ crafting_recipe_types = list(/datum/crafting_recipe/durathread_duffelbag, /datum/crafting_recipe/durathread_toolbelt, /datum/crafting_recipe/durathread_bandolier, /datum/crafting_recipe/durathread_helmet, /datum/crafting_recipe/durathread_vest)
+ icon_state = "tailers_art1"
+ oneuse = FALSE
+ remarks = list("Durathread is cloth thats also fire-resistant?", "Strong threads that can be used with leather for some light weight storage!", "The cloth can withstand a beating it said but not that much...")
+
/obj/item/book/granter/crafting_recipe/cooking_sweets_101 //We start at 101 for 103 and 105
name = "Cooking Desserts 101"
desc = "A cook book that teaches you some more of the newest desserts. AI approved, and a best seller on Honkplanet."
diff --git a/code/game/objects/items/grenades/plastic.dm b/code/game/objects/items/grenades/plastic.dm
index 709fedbe5a..1956a1f317 100644
--- a/code/game/objects/items/grenades/plastic.dm
+++ b/code/game/objects/items/grenades/plastic.dm
@@ -174,6 +174,7 @@
gender = PLURAL
var/open_panel = 0
can_attach_mob = TRUE
+ full_damage_on_mobs = TRUE
/obj/item/grenade/plastic/c4/New()
wires = new /datum/wires/explosive/c4(src)
diff --git a/code/game/objects/items/his_grace.dm b/code/game/objects/items/his_grace.dm
index 3be57d23f1..7e7dddefb6 100644
--- a/code/game/objects/items/his_grace.dm
+++ b/code/game/objects/items/his_grace.dm
@@ -29,7 +29,7 @@
. = ..()
START_PROCESSING(SSprocessing, src)
GLOB.poi_list += src
- AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_POST_THROW = CALLBACK(src, .proc/move_gracefully)))
+ RegisterSignal(src, COMSIG_MOVABLE_POST_THROW, .proc/move_gracefully)
/obj/item/his_grace/Destroy()
STOP_PROCESSING(SSprocessing, src)
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index ccb82f7029..84439985b2 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -233,7 +233,7 @@
/obj/item/nullrod/Initialize()
. = ..()
- AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
/obj/item/nullrod/suicide_act(mob/user)
user.visible_message("[user] is killing [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to get closer to god!")
diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm
index e7b55d53f5..0786172f25 100644
--- a/code/game/objects/items/implants/implant.dm
+++ b/code/game/objects/items/implants/implant.dm
@@ -89,11 +89,12 @@
return TRUE
/obj/item/implant/proc/removed(mob/living/source, silent = FALSE, special = 0)
+ SEND_SIGNAL(src, COMSIG_IMPLANT_REMOVING, args)
imp_in = null
source.implants -= src
for(var/X in actions)
var/datum/action/A = X
- A.Grant(source)
+ A.Remove(source)
if(ishuman(source))
var/mob/living/carbon/human/H = source
H.sec_hud_set_implants()
diff --git a/code/game/objects/items/implants/implant_storage.dm b/code/game/objects/items/implants/implant_storage.dm
index 739873af00..1dfc0b4580 100644
--- a/code/game/objects/items/implants/implant_storage.dm
+++ b/code/game/objects/items/implants/implant_storage.dm
@@ -12,7 +12,7 @@
/obj/item/implant/storage/removed(source, silent = FALSE, special = 0)
if(!special)
- qdel(pocket)
+ QDEL_NULL(pocket)
else
pocket?.moveToNullspace()
return ..()
@@ -21,7 +21,7 @@
for(var/X in target.implants)
if(istype(X, type))
var/obj/item/implant/storage/imp_e = X
- GET_COMPONENT_FROM(STR, /datum/component/storage, imp_e.pocket)
+ var/datum/component/storage/STR = imp_e.pocket.GetComponent(/datum/component/storage)
if(!STR || (STR && STR.max_items < max_slot_stacking))
imp_e.pocket.AddComponent(/datum/component/storage/concrete/implant)
qdel(src)
@@ -29,7 +29,7 @@
return FALSE
. = ..()
if(.)
- if(pocket)
+ if(!QDELETED(pocket))
pocket.forceMove(target)
else
pocket = new(target)
@@ -41,7 +41,6 @@
desc = "A tiny yet spacious pocket, usually found implanted inside sneaky syndicate agents and nowhere else."
component_type = /datum/component/storage/concrete/implant
resistance_flags = INDESTRUCTIBLE //A bomb!
- item_flags = DROPDEL
/obj/item/implanter/storage
name = "implanter (storage)"
diff --git a/code/game/objects/items/latexballoon.dm b/code/game/objects/items/latexballoon.dm
index 709bc6662a..11be6b88e9 100644
--- a/code/game/objects/items/latexballoon.dm
+++ b/code/game/objects/items/latexballoon.dm
@@ -52,5 +52,5 @@
var/obj/item/tank/T = W
blow(T, user)
return
- if (W.is_sharp() || W.is_hot() || is_pointed(W))
+ if (W.get_sharpness() || W.get_temperature() || is_pointed(W))
burst()
diff --git a/code/game/objects/items/manuals.dm b/code/game/objects/items/manuals.dm
index 02d0a1c36a..6ae34e9ca2 100644
--- a/code/game/objects/items/manuals.dm
+++ b/code/game/objects/items/manuals.dm
@@ -244,7 +244,7 @@
..()
/obj/item/book/manual/wiki/proc/initialize_wikibook()
- var/wikiurl = CONFIG_GET(string/wikiurl)
+ var/wikiurl = CONFIG_GET(string/wikiurltg)
if(wikiurl)
dat = {"
@@ -270,13 +270,67 @@
"}
-/obj/item/book/manual/wiki/chemistry
+/obj/item/book/manual/wiki/cit
+ name = "Citadel infobook"
+ icon_state ="book8"
+ author = "Nanotrasen"
+ title = "Citadel infobook"
+ page_link = ""
+ window_size = "1500x800" //Too squashed otherwise
+
+/obj/item/book/manual/wiki/cit/initialize_wikibook()
+ var/wikiurl = CONFIG_GET(string/wikiurl)
+ if(wikiurl)
+ dat = {"
+
+
+
+
+
+
+
You start skimming through the manual...
+
+
+
+
+
+ "}
+
+/obj/item/book/manual/wiki/cit/chemistry
name = "Chemistry Textbook"
icon_state ="chemistrybook"
author = "Nanotrasen"
title = "Chemistry Textbook"
+ page_link = "main/guides/guide_chemistry"
+
+/obj/item/book/manual/wiki/cit/chem_recipies
+ name = "Chemistry Recipies"
+ icon_state ="chemrecibook"
+ author = "Chemcat"
+ title = "Chemistry Recipies"
+ page_link = "main/guides/chem_recipies"
+
+/obj/item/book/manual/wiki/chemistry
+ name = "Outdated Chemistry Textbook"
+ icon_state ="chemistrybook_old"
+ author = "Nanotrasen"
+ title = "Outdated Chemistry Textbook"
page_link = "Guide_to_chemistry"
+/obj/item/book/manual/wiki/chemistry/Initialize()
+ ..()
+ new /obj/item/book/manual/wiki/cit/chemistry(loc)
+ new /obj/item/book/manual/wiki/cit/chem_recipies(loc)
+
/obj/item/book/manual/wiki/engineering_construction
name = "Station Repairs and Construction"
icon_state ="bookEngineering"
diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm
index 57b9973aa3..51fd2c50d8 100644
--- a/code/game/objects/items/melee/energy.dm
+++ b/code/game/objects/items/melee/energy.dm
@@ -28,7 +28,7 @@
/obj/item/melee/transforming/energy/add_blood_DNA(list/blood_dna)
return FALSE
-/obj/item/melee/transforming/energy/is_sharp()
+/obj/item/melee/transforming/energy/get_sharpness()
return active * sharpness
/obj/item/melee/transforming/energy/process()
@@ -46,7 +46,7 @@
STOP_PROCESSING(SSobj, src)
set_light(0)
-/obj/item/melee/transforming/energy/is_hot()
+/obj/item/melee/transforming/energy/get_temperature()
return active * heat
/obj/item/melee/transforming/energy/ignition_effect(atom/A, mob/user)
@@ -233,3 +233,152 @@
desc = "An extremely sharp blade made out of hard light. Packs quite a punch."
icon_state = "lightblade"
item_state = "lightblade"
+
+/*/////////////////////////////////////////////////////////////////////////
+///////////// The TRUE Energy Sword ///////////////////////////
+*//////////////////////////////////////////////////////////////////////////
+
+/obj/item/melee/transforming/energy/sword/cx
+ name = "non-eutactic blade"
+ desc = "The Non-Eutactic Blade utilizes a hardlight blade that is dynamically 'forged' on demand to create a deadly sharp edge that is unbreakable."
+ icon_state = "cxsword_hilt"
+ item_state = "cxsword"
+ force = 3
+ force_on = 21
+ throwforce = 5
+ throwforce_on = 20
+ hitsound = "swing_hit" //it starts deactivated
+ hitsound_on = 'sound/weapons/nebhit.ogg'
+ attack_verb_off = list("tapped", "poked")
+ throw_speed = 3
+ throw_range = 5
+ sharpness = IS_SHARP
+ embedding = list("embedded_pain_multiplier" = 6, "embed_chance" = 20, "embedded_fall_chance" = 60)
+ armour_penetration = 10
+ block_chance = 35
+ light_color = "#37FFF7"
+ actions_types = list()
+
+/obj/item/melee/transforming/energy/sword/cx/pre_altattackby(atom/A, mob/living/user, params) //checks if it can do right click memes
+ altafterattack(A, user, TRUE, params)
+ return TRUE
+
+/obj/item/melee/transforming/energy/sword/cx/altafterattack(atom/target, mob/living/carbon/user, proximity_flag, click_parameters) //does right click memes
+ if(istype(user))
+ user.visible_message("[user] points the tip of [src] at [target].", "You point the tip of [src] at [target].")
+ return TRUE
+
+/obj/item/melee/transforming/energy/sword/cx/transform_weapon(mob/living/user, supress_message_text)
+ active = !active //I'd use a ..() here but it'd inherit from the regular esword's proc instead, so SPAGHETTI CODE
+ if(active) //also I'd need to rip out the iconstate changing bits
+ force = force_on
+ throwforce = throwforce_on
+ hitsound = hitsound_on
+ throw_speed = 4
+ if(attack_verb_on.len)
+ attack_verb = attack_verb_on
+ w_class = w_class_on
+ START_PROCESSING(SSobj, src)
+ set_light(brightness_on)
+ update_icon()
+ else
+ force = initial(force)
+ throwforce = initial(throwforce)
+ hitsound = initial(hitsound)
+ throw_speed = initial(throw_speed)
+ if(attack_verb_off.len)
+ attack_verb = attack_verb_off
+ w_class = initial(w_class)
+ STOP_PROCESSING(SSobj, src)
+ set_light(0)
+ update_icon()
+ transform_messages(user, supress_message_text)
+ add_fingerprint(user)
+ return TRUE
+
+/obj/item/melee/transforming/energy/sword/cx/transform_messages(mob/living/user, supress_message_text)
+ playsound(user, active ? 'sound/weapons/nebon.ogg' : 'sound/weapons/neboff.ogg', 65, 1)
+ if(!supress_message_text)
+ to_chat(user, "[src] [active ? "is now active":"can now be concealed"].")
+
+/obj/item/melee/transforming/energy/sword/cx/update_icon()
+ var/mutable_appearance/blade_overlay = mutable_appearance(icon, "cxsword_blade")
+ var/mutable_appearance/gem_overlay = mutable_appearance(icon, "cxsword_gem")
+
+ if(light_color)
+ blade_overlay.color = light_color
+ gem_overlay.color = light_color
+
+ cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
+
+ add_overlay(gem_overlay)
+
+ if(active)
+ add_overlay(blade_overlay)
+ if(ismob(loc))
+ var/mob/M = loc
+ M.update_inv_hands()
+
+/obj/item/melee/transforming/energy/sword/cx/AltClick(mob/living/user)
+ if(!in_range(src, user)) //Basic checks to prevent abuse
+ return
+ if(user.incapacitated() || !istype(user))
+ to_chat(user, "You can't do that right now!")
+ return
+
+ if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes")
+ var/energy_color_input = input(usr,"","Choose Energy Color",light_color) as color|null
+ if(energy_color_input)
+ light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
+ update_icon()
+ update_light()
+
+/obj/item/melee/transforming/energy/sword/cx/examine(mob/user)
+ ..()
+ to_chat(user, "Alt-click to recolor it.")
+
+/obj/item/melee/transforming/energy/sword/cx/worn_overlays(isinhands, icon_file)
+ . = ..()
+ if(active)
+ if(isinhands)
+ var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "cxsword_blade")
+ blade_inhand.color = light_color
+ . += blade_inhand
+
+//Broken version. Not a toy, but not as strong.
+/obj/item/melee/transforming/energy/sword/cx/broken
+ name = "misaligned non-eutactic blade"
+ desc = "The Non-Eutactic Blade utilizes a hardlight blade that is dynamically 'forged' on demand to create a deadly sharp edge that is unbreakable. This one seems to have a damaged handle and misaligned components, causing the blade to be unstable at best"
+ force_on = 15 //As strong a survival knife/bone dagger
+
+/obj/item/melee/transforming/energy/sword/cx/attackby(obj/item/W, mob/living/user, params)
+ if(istype(W, /obj/item/melee/transforming/energy/sword/cx))
+ if(HAS_TRAIT(W, TRAIT_NODROP) || HAS_TRAIT(src, TRAIT_NODROP))
+ to_chat(user, "\the [HAS_TRAIT(src, TRAIT_NODROP) ? src : W] is stuck to your hand, you can't attach it to \the [HAS_TRAIT(src, TRAIT_NODROP) ? W : src]!")
+ return
+ else
+ to_chat(user, "You combine the two light swords, making a single supermassive blade! You're cool.")
+ new /obj/item/twohanded/dualsaber/hypereutactic(user.drop_location())
+ qdel(W)
+ qdel(src)
+ else
+ return ..()
+
+//////// Tatortot NEB /////////////// (same stats as regular esword)
+/obj/item/melee/transforming/energy/sword/cx/traitor
+ name = "\improper Dragon's Tooth Sword"
+ desc = "The Dragon's Tooth sword is a blackmarket modification of a Non-Eutactic Blade, \
+ which utilizes a hardlight blade that is dynamically 'forged' on demand to create a deadly sharp edge that is unbreakable. \
+ It appears to have a wooden grip and a shaved down guard."
+ icon_state = "cxsword_hilt_traitor"
+ force_on = 30
+ armour_penetration = 50
+ embedding = list("embedded_pain_multiplier" = 10, "embed_chance" = 75, "embedded_fall_chance" = 0, "embedded_impact_pain_multiplier" = 10)
+ block_chance = 50
+ hitsound_on = 'sound/weapons/blade1.ogg'
+ light_color = "#37F0FF"
+
+/obj/item/melee/transforming/energy/sword/cx/traitor/transform_messages(mob/living/user, supress_message_text)
+ playsound(user, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 35, 1)
+ if(!supress_message_text)
+ to_chat(user, "[src] [active ? "is now active":"can now be concealed"].")
diff --git a/code/game/objects/items/melee/transforming.dm b/code/game/objects/items/melee/transforming.dm
index aabb930bb2..7eb35ed06b 100644
--- a/code/game/objects/items/melee/transforming.dm
+++ b/code/game/objects/items/melee/transforming.dm
@@ -23,7 +23,7 @@
else
if(attack_verb_off.len)
attack_verb = attack_verb_off
- if(is_sharp())
+ if(get_sharpness())
AddComponent(/datum/component/butchering, 50, 100, 0, hitsound, !active)
/obj/item/melee/transforming/attack_self(mob/living/carbon/user)
@@ -65,11 +65,11 @@
icon_state = initial(icon_state)
w_class = initial(w_class)
total_mass = initial(total_mass)
- if(is_sharp())
+ if(get_sharpness())
var/datum/component/butchering/BT = LoadComponent(/datum/component/butchering)
BT.butchering_enabled = TRUE
else
- GET_COMPONENT(BT, /datum/component/butchering)
+ var/datum/component/butchering/BT = GetComponent(/datum/component/butchering)
if(BT)
BT.butchering_enabled = FALSE
transform_messages(user, supress_message_text)
diff --git a/code/game/objects/items/mop.dm b/code/game/objects/items/mop.dm
index 7524fc9007..3f7fe7ee8d 100644
--- a/code/game/objects/items/mop.dm
+++ b/code/game/objects/items/mop.dm
@@ -27,6 +27,7 @@
/obj/item/mop/proc/clean(turf/A)
if(reagents.has_reagent("water", 1) || reagents.has_reagent("holywater", 1) || reagents.has_reagent("vodka", 1) || reagents.has_reagent("cleaner", 1))
SEND_SIGNAL(A, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_MEDIUM)
+ A.clean_blood()
for(var/obj/effect/O in A)
if(is_cleanable(O))
qdel(O)
diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm
index a73be6e12e..30442d7304 100644
--- a/code/game/objects/items/pet_carrier.dm
+++ b/code/game/objects/items/pet_carrier.dm
@@ -122,7 +122,7 @@
if(user.mob_size <= MOB_SIZE_SMALL)
to_chat(user, "You poke a limb through [src]'s bars and start fumbling for the lock switch... (This will take some time.)")
to_chat(loc, "You see [user] reach through the bars and fumble for the lock switch!")
- if(!do_after(user, rand(300, 400), target = user) || open || !locked || !user in occupants)
+ if(!do_after(user, rand(300, 400), target = user) || open || !locked || !(user in occupants))
return
loc.visible_message("[user] flips the lock switch on [src] by reaching through!", null, null, null, user)
to_chat(user, "Bingo! The lock pops open!")
@@ -132,7 +132,7 @@
else
loc.visible_message("[src] starts rattling as something pushes against the door!", null, null, null, user)
to_chat(user, "You start pushing out of [src]... (This will take about 20 seconds.)")
- if(!do_after(user, 200, target = user) || open || !locked || !user in occupants)
+ if(!do_after(user, 200, target = user) || open || !locked || !(user in occupants))
return
loc.visible_message("[user] shoves out of [src]!", null, null, null, user)
to_chat(user, "You shove open [src]'s door against the lock's resistance and fall out!")
@@ -185,7 +185,7 @@
occupant_weight += occupant.mob_size
/obj/item/pet_carrier/proc/remove_occupant(mob/living/occupant, turf/new_turf)
- if(!occupant in occupants || !istype(occupant))
+ if(!(occupant in occupants) || !istype(occupant))
return
occupant.forceMove(new_turf ? new_turf : drop_location())
occupants -= occupant
diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm
index 48588cf9f3..973fb0c0ab 100644
--- a/code/game/objects/items/plushes.dm
+++ b/code/game/objects/items/plushes.dm
@@ -117,7 +117,7 @@
to_chat(user, "You try to pet [src], but it has no stuffing. Aww...")
/obj/item/toy/plush/attackby(obj/item/I, mob/living/user, params)
- if(I.is_sharp())
+ if(I.get_sharpness())
if(!grenade)
if(!stuffed)
to_chat(user, "You already murdered it!")
@@ -366,10 +366,10 @@
/obj/item/toy/plush/random
name = "Illegal plushie"
desc = "Something fucked up"
+ var/blacklisted_plushes = list(/obj/item/toy/plush/carpplushie/dehy_carp, /obj/item/toy/plush/awakenedplushie, /obj/item/toy/plush/random)
/obj/item/toy/plush/random/Initialize()
- ..()
- var/newtype = pick(subtypesof(/obj/item/toy/plush))
+ var/newtype = pick(subtypesof(/obj/item/toy/plush) - typecacheof(blacklisted_plushes))
new newtype(loc)
return INITIALIZE_HINT_QDEL
diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm
index 8582725cda..7b3dcb1e00 100644
--- a/code/game/objects/items/religion.dm
+++ b/code/game/objects/items/religion.dm
@@ -82,14 +82,6 @@
/obj/item/banner/security/mundane
inspiration_available = FALSE
-/datum/crafting_recipe/security_banner
- name = "Securistan Banner"
- result = /obj/item/banner/security/mundane
- time = 40
- reqs = list(/obj/item/stack/rods = 2,
- /obj/item/clothing/under/rank/security = 1)
- category = CAT_MISC
-
/obj/item/banner/medical
name = "meditopia banner"
desc = "The banner of Meditopia, generous benefactors that cure wounds and shelter the weak."
@@ -103,14 +95,6 @@
/obj/item/banner/medical/check_inspiration(mob/living/carbon/human/H)
return H.stat //Meditopia is moved to help those in need
-/datum/crafting_recipe/medical_banner
- name = "Meditopia Banner"
- result = /obj/item/banner/medical/mundane
- time = 40
- reqs = list(/obj/item/stack/rods = 2,
- /obj/item/clothing/under/rank/medical = 1)
- category = CAT_MISC
-
/obj/item/banner/medical/special_inspiration(mob/living/carbon/human/H)
H.adjustToxLoss(-15)
H.setOxyLoss(0)
@@ -129,14 +113,6 @@
/obj/item/banner/science/check_inspiration(mob/living/carbon/human/H)
return H.on_fire //Sciencia is pleased by dedication to the art of Toxins
-/datum/crafting_recipe/science_banner
- name = "Sciencia Banner"
- result = /obj/item/banner/science/mundane
- time = 40
- reqs = list(/obj/item/stack/rods = 2,
- /obj/item/clothing/under/rank/scientist = 1)
- category = CAT_MISC
-
/obj/item/banner/cargo
name = "cargonia banner"
desc = "The banner of the eternal Cargonia, with the mystical power of conjuring any object into existence."
@@ -147,14 +123,6 @@
/obj/item/banner/cargo/mundane
inspiration_available = FALSE
-/datum/crafting_recipe/cargo_banner
- name = "Cargonia Banner"
- result = /obj/item/banner/cargo/mundane
- time = 40
- reqs = list(/obj/item/stack/rods = 2,
- /obj/item/clothing/under/rank/cargotech = 1)
- category = CAT_MISC
-
/obj/item/banner/engineering
name = "engitopia banner"
desc = "The banner of Engitopia, wielders of limitless power."
@@ -168,14 +136,6 @@
/obj/item/banner/engineering/special_inspiration(mob/living/carbon/human/H)
H.radiation = 0
-/datum/crafting_recipe/engineering_banner
- name = "Engitopia Banner"
- result = /obj/item/banner/engineering/mundane
- time = 40
- reqs = list(/obj/item/stack/rods = 2,
- /obj/item/clothing/under/rank/engineer = 1)
- category = CAT_MISC
-
/obj/item/banner/command
name = "command banner"
desc = "The banner of Command, a staunch and ancient line of bueraucratic kings and queens."
@@ -189,14 +149,6 @@
/obj/item/banner/command/check_inspiration(mob/living/carbon/human/H)
return HAS_TRAIT(H, TRAIT_MINDSHIELD) //Command is stalwart but rewards their allies.
-/datum/crafting_recipe/command_banner
- name = "Command Banner"
- result = /obj/item/banner/command/mundane
- time = 40
- reqs = list(/obj/item/stack/rods = 2,
- /obj/item/clothing/under/captainparade = 1)
- category = CAT_MISC
-
/obj/item/banner/red
name = "red banner"
icon_state = "banner-red"
@@ -216,7 +168,7 @@
/obj/item/storage/backpack/bannerpack/Initialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 27 //6 more then normal, for the tradeoff of declaring yourself an antag at all times.
/obj/item/storage/backpack/bannerpack/red
@@ -286,7 +238,6 @@
var/staffcooldown = 0
var/staffwait = 30
-
/obj/item/godstaff/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()
if(staffcooldown + staffwait > world.time)
@@ -332,19 +283,16 @@
heat_protection = FEET
max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT
-
/obj/item/clothing/shoes/plate/red
icon_state = "crusader-red"
/obj/item/clothing/shoes/plate/blue
icon_state = "crusader-blue"
-
/obj/item/storage/box/itemset/crusader
name = "Crusader's Armour Set" //i can't into ck2 references
desc = "This armour is said to be based on the armor of kings on another world thousands of years ago, who tended to assassinate, conspire, and plot against everyone who tried to do the same to them. Some things never change."
-
/obj/item/storage/box/itemset/crusader/blue/New()
..()
contents = list()
@@ -354,7 +302,6 @@
new /obj/item/clothing/gloves/plate/blue(src)
new /obj/item/clothing/shoes/plate/blue(src)
-
/obj/item/storage/box/itemset/crusader/red/New()
..()
contents = list()
@@ -364,7 +311,6 @@
new /obj/item/clothing/gloves/plate/red(src)
new /obj/item/clothing/shoes/plate/red(src)
-
/obj/item/claymore/weak
desc = "This one is rusted."
force = 30
diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm
index 5454b0fdb8..77bc7ed810 100644
--- a/code/game/objects/items/robot/robot_items.dm
+++ b/code/game/objects/items/robot/robot_items.dm
@@ -313,7 +313,7 @@
if(M.get_ear_protection() == FALSE)
M.confused += 6
audible_message("HUMAN HARM")
- playsound(get_turf(src), 'sound/ai/harmalarm.ogg', 70, 3)
+ playsound(get_turf(src), 'sound/effects/harmalarm.ogg', 70, 3)
cooldown = world.time + 200
log_game("[key_name(user)] used a Cyborg Harm Alarm in [AREACOORD(user)]")
if(iscyborg(user))
@@ -430,7 +430,7 @@
A.BB.nodamage = FALSE
A.BB.speed = 0.5
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
- A.fire_casing(target, user, params, 0, 0, null, 0)
+ A.fire_casing(target, user, params, 0, 0, null, 0, src)
user.visible_message("[user] blasts a flying lollipop at [target]!")
check_amount()
@@ -446,7 +446,7 @@
A.BB.speed = 0.5
A.BB.color = rgb(rand(0, 255), rand(0, 255), rand(0, 255))
playsound(src.loc, 'sound/weapons/bulletflyby3.ogg', 50, 1)
- A.fire_casing(target, user, params, 0, 0, null, 0)
+ A.fire_casing(target, user, params, 0, 0, null, 0, src)
user.visible_message("[user] shoots a high-velocity gumball at [target]!")
check_amount()
@@ -746,3 +746,73 @@
..()
hud = new /obj/item/clothing/glasses/hud/security(src)
return
+
+
+/**********************************************************************
+ Grippers oh god oh fuck
+***********************************************************************/
+
+/obj/item/weapon/gripper
+ name = "circuit gripper"
+ desc = "A simple grasping tool for inserting circuitboards into machinary."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "gripper"
+
+ item_flags = NOBLUDGEON
+
+ //Has a list of items that it can hold.
+ var/list/can_hold = list(
+ /obj/item/circuitboard
+ )
+
+ var/obj/item/wrapped = null // Item currently being held.
+
+/obj/item/weapon/gripper/attack_self()
+ if(wrapped)
+ wrapped.forceMove(get_turf(wrapped))
+ wrapped = null
+ return ..()
+
+/obj/item/weapon/gripper/afterattack(var/atom/target, var/mob/living/user, proximity, params)
+
+ if(!proximity)
+ return
+
+ if(!wrapped)
+ for(var/obj/item/thing in src.contents)
+ wrapped = thing
+ break
+
+ if(wrapped) //Already have an item.
+ //Temporary put wrapped into user so target's attackby() checks pass.
+ wrapped.loc = user
+
+ //Pass the attack on to the target. This might delete/relocate wrapped.
+ var/resolved = target.attackby(wrapped,user)
+ if(!resolved && wrapped && target)
+ wrapped.afterattack(target,user,1)
+ //If wrapped was neither deleted nor put into target, put it back into the gripper.
+ if(wrapped && user && (wrapped.loc == user))
+ wrapped.loc = src
+ else
+ wrapped = null
+ return
+
+ else if(istype(target,/obj/item))
+
+ var/obj/item/I = target
+
+ var/grab = 0
+ for(var/typepath in can_hold)
+ if(istype(I,typepath))
+ grab = 1
+ break
+
+ //We can grab the item, finally.
+ if(grab)
+ to_chat(user, "You collect \the [I].")
+ I.loc = src
+ wrapped = I
+ return
+ else
+ to_chat(user, "Your gripper cannot hold \the [target].")
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index 9c929a6ebf..d9045a7a34 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -89,32 +89,36 @@
R.speed = initial(R.speed)
/obj/item/borg/upgrade/disablercooler
- name = "cyborg rapid disabler cooling module"
- desc = "Used to cool a mounted disabler, increasing the potential current in it and thus its recharge rate."
+ name = "cyborg rapid energy blaster cooling module"
+ desc = "Used to cool a mounted energy-based firearm, increasing the potential current in it and thus its recharge rate."
icon_state = "cyborg_upgrade3"
require_module = 1
/obj/item/borg/upgrade/disablercooler/action(mob/living/silicon/robot/R, user = usr)
. = ..()
if(.)
- var/obj/item/gun/energy/disabler/cyborg/T = locate() in R.module.modules
- if(!T)
- to_chat(user, "There's no disabler in this unit!")
+ var/successflag
+ for(var/obj/item/gun/energy/T in R.module.modules)
+ if(T.charge_delay <= 2)
+ successflag = successflag || 2
+ continue
+ T.charge_delay = max(2, T.charge_delay - 4)
+ successflag = 1
+ if(!successflag)
+ to_chat(user, "There's no energy-based firearm in this unit!")
return FALSE
- if(T.charge_delay <= 2)
+ if(successflag == 2)
to_chat(R, "A cooling unit is already installed!")
to_chat(user, "There's no room for another cooling unit!")
return FALSE
- T.charge_delay = max(2 , T.charge_delay - 4)
-
/obj/item/borg/upgrade/disablercooler/deactivate(mob/living/silicon/robot/R, user = usr)
. = ..()
if (.)
- var/obj/item/gun/energy/disabler/cyborg/T = locate() in R.module.modules
- if(!T)
- return FALSE
- T.charge_delay = initial(T.charge_delay)
+ for(var/obj/item/gun/energy/T in R.module.modules)
+ T.charge_delay = initial(T.charge_delay)
+ return .
+ return FALSE
/obj/item/borg/upgrade/thrusters
name = "ion thruster upgrade"
@@ -598,10 +602,10 @@
R.update_transform()
/obj/item/borg/upgrade/rped
- name = "engineering cyborg RPED"
+ name = "engineering cyborg BSRPED"
desc = "A rapid part exchange device for the engineering cyborg."
icon = 'icons/obj/storage.dmi'
- icon_state = "borgrped"
+ icon_state = "borg_BS_RPED"
require_module = TRUE
module_type = list(/obj/item/robot_module/engineering)
@@ -609,14 +613,21 @@
. = ..()
if(.)
+ var/obj/item/storage/part_replacer/bluespace/cyborg/BSRPED = locate() in R
var/obj/item/storage/part_replacer/cyborg/RPED = locate() in R
- if(RPED)
- to_chat(user, "This unit is already equipped with a RPED module.")
+ if(!RPED)
+ RPED = locate() in R.module
+ if(!BSRPED)
+ BSRPED = locate() in R.module //There's gotta be a smarter way to do this.
+ if(BSRPED)
+ to_chat(user, "This unit is already equipped with a BSRPED module.")
return FALSE
- RPED = new(R.module)
- R.module.basic_modules += RPED
- R.module.add_module(RPED, FALSE, TRUE)
+ BSRPED = new(R.module)
+ SEND_SIGNAL(RPED, COMSIG_TRY_STORAGE_QUICK_EMPTY)
+ qdel(RPED)
+ R.module.basic_modules += BSRPED
+ R.module.add_module(BSRPED, FALSE, TRUE)
/obj/item/borg/upgrade/rped/deactivate(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -680,7 +691,7 @@
action_icon_state = "Chevron_State_0"
var/currentState = 0
- var/maxReduction = 2
+ var/maxReduction = 1
/obj/effect/proc_holder/silicon/cyborg/vtecControl/Click(mob/living/silicon/robot/user)
@@ -688,14 +699,14 @@
currentState = (currentState + 1) % 3
- if(usr)
+ if(istype(self))
switch(currentState)
if (0)
- self.speed = maxReduction
+ self.speed = initial(self.speed)
if (1)
- self.speed -= maxReduction*0.5
+ self.speed = initial(self.speed) - maxReduction * 0.5
if (2)
- self.speed -= maxReduction*1.25
+ self.speed = initial(self.speed) - maxReduction * 1
action.button_icon_state = "Chevron_State_[currentState]"
action.UpdateButtonIcon()
diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm
index 5610cbad9a..9f3e5f6bd4 100644
--- a/code/game/objects/items/stacks/medical.dm
+++ b/code/game/objects/items/stacks/medical.dm
@@ -17,7 +17,6 @@
var/self_delay = 50
/obj/item/stack/medical/attack(mob/living/M, mob/user)
-
if(M.stat == DEAD && !stop_bleeding)
var/t_him = "it"
if(M.gender == MALE)
@@ -129,7 +128,7 @@
/obj/item/stack/medical/gauze/attackby(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/wirecutters) || I.is_sharp())
+ if(istype(I, /obj/item/wirecutters) || I.get_sharpness())
if(get_amount() < 2)
to_chat(user, "You need at least two gauzes to do this!")
return
diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm
index 01351ab2e2..7297bb3aae 100644
--- a/code/game/objects/items/stacks/sheets/leather.dm
+++ b/code/game/objects/items/stacks/sheets/leather.dm
@@ -219,7 +219,7 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \
//Step one - dehairing.
/obj/item/stack/sheet/animalhide/attackby(obj/item/W, mob/user, params)
- if(W.is_sharp())
+ if(W.get_sharpness())
playsound(loc, 'sound/weapons/slice.ogg', 50, 1, -1)
user.visible_message("[user] starts cutting hair off \the [src].", "You start cutting the hair off \the [src]...", "You hear the sound of a knife rubbing against flesh.")
if(do_after(user, 50, target = src))
diff --git a/code/game/objects/items/stacks/sheets/mineral.dm b/code/game/objects/items/stacks/sheets/mineral.dm
index 46c0d47388..96546d6eb6 100644
--- a/code/game/objects/items/stacks/sheets/mineral.dm
+++ b/code/game/objects/items/stacks/sheets/mineral.dm
@@ -178,11 +178,11 @@ GLOBAL_LIST_INIT(plasma_recipes, list ( \
. = ..()
/obj/item/stack/sheet/mineral/plasma/attackby(obj/item/W as obj, mob/user as mob, params)
- if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
+ if(W.get_temperature() > 300)//If the temperature of the object is over 300, then ignite
var/turf/T = get_turf(src)
message_admins("Plasma sheets ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(T)]")
log_game("Plasma sheets ignited by [key_name(user)] in [AREACOORD(T)]")
- fire_act(W.is_hot())
+ fire_act(W.get_temperature())
else
return ..()
diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm
index 155d1f1643..7654199cf5 100644
--- a/code/game/objects/items/stacks/stack.dm
+++ b/code/game/objects/items/stacks/stack.dm
@@ -390,9 +390,9 @@
. = ..()
/obj/item/stack/proc/copy_evidences(obj/item/stack/from)
- add_blood_DNA(from.return_blood_DNA())
- add_fingerprint_list(from.return_fingerprints())
- add_hiddenprint_list(from.return_hiddenprints())
+ blood_DNA = from.blood_DNA
+ fingerprints = from.fingerprints
+ fingerprintshidden = from.fingerprintshidden
fingerprintslast = from.fingerprintslast
//TODO bloody overlay
@@ -437,4 +437,4 @@
/datum/stack_recipe_list/New(title, recipes)
src.title = title
- src.recipes = recipes
+ src.recipes = recipes
\ No newline at end of file
diff --git a/code/game/objects/items/stacks/telecrystal.dm b/code/game/objects/items/stacks/telecrystal.dm
index 7c34ae87bf..9b5ca2b066 100644
--- a/code/game/objects/items/stacks/telecrystal.dm
+++ b/code/game/objects/items/stacks/telecrystal.dm
@@ -13,7 +13,7 @@
var/mob/living/L = user
for(var/obj/item/implant/uplink/I in L.implants)
if(I?.imp_in)
- GET_COMPONENT_FROM(hidden_uplink, /datum/component/uplink, I)
+ var/datum/component/uplink/hidden_uplink = I.GetComponent(/datum/component/uplink)
if(hidden_uplink)
hidden_uplink.telecrystals += amount
use(amount)
diff --git a/code/game/objects/items/storage/backpack.dm b/code/game/objects/items/storage/backpack.dm
index ad8c4306a5..a79eb299da 100644
--- a/code/game/objects/items/storage/backpack.dm
+++ b/code/game/objects/items/storage/backpack.dm
@@ -23,7 +23,7 @@
/obj/item/storage/backpack/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 21
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_items = 21
@@ -34,7 +34,7 @@
/obj/item/storage/backpack/old/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 12
/obj/item/storage/backpack/holding
@@ -58,7 +58,7 @@
/obj/item/storage/backpack/holding/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.allow_big_nesting = TRUE
STR.max_w_class = WEIGHT_CLASS_GIGANTIC
STR.max_combined_w_class = 35
@@ -87,7 +87,7 @@
/obj/item/storage/backpack/santabag/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 60
@@ -260,7 +260,7 @@
/obj/item/storage/backpack/satchel/bone/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 20
STR.max_items = 15
@@ -286,7 +286,7 @@
/obj/item/storage/backpack/satchel/flat/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 6
STR.cant_hold = typecacheof(list(/obj/item/storage/backpack/satchel/flat)) //muh recursive backpacks
@@ -338,7 +338,7 @@
/obj/item/storage/backpack/duffelbag/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 30
/obj/item/storage/backpack/duffelbag/captain
@@ -444,7 +444,7 @@
/obj/item/storage/backpack/duffelbag/syndie/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.silent = TRUE
/obj/item/storage/backpack/duffelbag/syndie/hitman
@@ -594,7 +594,7 @@
// For ClownOps.
/obj/item/storage/backpack/duffelbag/clown/syndie/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
slowdown = 0
STR.silent = TRUE
diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm
index 232d1bd5c9..eafa79798e 100644
--- a/code/game/objects/items/storage/bags.dm
+++ b/code/game/objects/items/storage/bags.dm
@@ -21,7 +21,7 @@
/obj/item/storage/bag/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.allow_quick_gather = TRUE
STR.allow_quick_empty = TRUE
STR.display_numerical_stacking = TRUE
@@ -44,11 +44,13 @@
/obj/item/storage/bag/trash/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_SMALL
STR.max_combined_w_class = 30
STR.max_items = 30
STR.cant_hold = typecacheof(list(/obj/item/disk/nuclear))
+ STR.limited_random_access = TRUE
+ STR.limited_random_access_stack_position = 3
/obj/item/storage/bag/trash/suicide_act(mob/user)
user.visible_message("[user] puts [src] over [user.p_their()] head and starts chomping at the insides! Disgusting!")
@@ -85,9 +87,10 @@
/obj/item/storage/bag/trash/bluespace/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 60
STR.max_items = 60
+ STR.limited_random_access_stack_position = 5
/obj/item/storage/bag/trash/bluespace/cyborg
insertable = FALSE
@@ -105,12 +108,12 @@
w_class = WEIGHT_CLASS_NORMAL
component_type = /datum/component/storage/concrete/stack
var/spam_protection = FALSE //If this is TRUE, the holder won't receive any messages when they fail to pick up ore through crossing it
- var/datum/component/mobhook
+ var/mob/listeningTo
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
/obj/item/storage/bag/ore/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
+ var/datum/component/storage/concrete/stack/STR = GetComponent(/datum/component/storage/concrete/stack)
STR.allow_quick_empty = TRUE
STR.can_hold = typecacheof(list(/obj/item/stack/ore))
STR.max_w_class = WEIGHT_CLASS_HUGE
@@ -118,15 +121,17 @@
/obj/item/storage/bag/ore/equipped(mob/user)
. = ..()
- if (mobhook && mobhook.parent != user)
- QDEL_NULL(mobhook)
- if (!mobhook)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/Pickup_ores)))
+ if(listeningTo == user)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/Pickup_ores)
+ listeningTo = user
/obj/item/storage/bag/ore/dropped()
. = ..()
- if (mobhook)
- QDEL_NULL(mobhook)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
/obj/item/storage/bag/ore/proc/Pickup_ores(mob/living/user)
var/show_message = FALSE
@@ -136,7 +141,7 @@
return
if (istype(user.pulling, /obj/structure/ore_box))
box = user.pulling
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
if(STR)
for(var/A in tile)
if (!is_type_in_typecache(A, STR.can_hold))
@@ -166,7 +171,7 @@
/obj/item/storage/bag/ore/cyborg/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
+ var/datum/component/storage/concrete/stack/STR = GetComponent(/datum/component/storage/concrete/stack)
STR.allow_quick_empty = TRUE
STR.can_hold = typecacheof(list(/obj/item/stack/ore))
STR.max_w_class = WEIGHT_CLASS_HUGE
@@ -178,7 +183,7 @@
/obj/item/storage/bag/ore/large/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
+ var/datum/component/storage/concrete/stack/STR = GetComponent(/datum/component/storage/concrete/stack)
STR.allow_quick_empty = TRUE
STR.can_hold = typecacheof(list(/obj/item/stack/ore))
STR.max_w_class = WEIGHT_CLASS_HUGE
@@ -191,7 +196,7 @@
/obj/item/storage/bag/ore/holding/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
+ var/datum/component/storage/concrete/stack/STR = GetComponent(/datum/component/storage/concrete/stack)
STR.max_items = INFINITY
STR.max_combined_w_class = INFINITY
STR.max_combined_stack_amount = INFINITY
@@ -209,7 +214,7 @@
/obj/item/storage/bag/plants/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 100
STR.max_items = 100
@@ -249,7 +254,7 @@
/obj/item/storage/bag/sheetsnatcher/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
+ var/datum/component/storage/concrete/stack/STR = GetComponent(/datum/component/storage/concrete/stack)
STR.allow_quick_empty = TRUE
STR.can_hold = typecacheof(list(/obj/item/stack/sheet))
STR.cant_hold = typecacheof(list(/obj/item/stack/sheet/mineral/sandstone, /obj/item/stack/sheet/mineral/wood))
@@ -266,7 +271,7 @@
/obj/item/storage/bag/sheetsnatcher/borg/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage/concrete/stack)
+ var/datum/component/storage/concrete/stack/STR = GetComponent(/datum/component/storage/concrete/stack)
STR.max_combined_stack_amount = 500
// -----------------------------
@@ -283,7 +288,7 @@
/obj/item/storage/bag/books/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 21
STR.max_items = 7
@@ -308,15 +313,14 @@
/obj/item/storage/bag/tray/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.insert_preposition = "on"
/obj/item/storage/bag/tray/attack(mob/living/M, mob/living/user)
. = ..()
// Drop all the things. All of them.
var/list/obj/item/oldContents = contents.Copy()
- GET_COMPONENT(STR, /datum/component/storage)
- STR.quick_empty()
+ SEND_SIGNAL(src, COMSIG_TRY_STORAGE_QUICK_EMPTY)
// Make each item scatter a bit
for(var/obj/item/I in oldContents)
spawn()
@@ -362,11 +366,11 @@
/obj/item/storage/bag/chemistry/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 200
STR.max_items = 50
STR.insert_preposition = "in"
- STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle))
+ STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/syringe/dart))
/*
* Biowaste bag (mostly for xenobiologists)
@@ -382,7 +386,7 @@
/obj/item/storage/bag/bio/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 200
STR.max_items = 25
STR.insert_preposition = "in"
@@ -397,6 +401,6 @@
/obj/item/storage/bag/bio/holding/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = INFINITY
STR.max_items = 100
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index a2b497cc07..713dbe4133 100755
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -44,7 +44,7 @@
/obj/item/storage/belt/utility/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
var/static/list/can_hold = typecacheof(list(
/obj/item/crowbar,
/obj/item/screwdriver,
@@ -127,7 +127,7 @@
/obj/item/storage/belt/medical/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_BULKY
STR.can_hold = typecacheof(list(
/obj/item/healthanalyzer,
@@ -199,7 +199,7 @@
/obj/item/storage/belt/security/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 5
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.can_hold = typecacheof(list(
@@ -238,7 +238,7 @@
/obj/item/storage/belt/mining/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.max_w_class = WEIGHT_CLASS_BULKY
STR.max_combined_w_class = 20
@@ -297,7 +297,7 @@
/obj/item/storage/belt/mining/primitive/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 5
/obj/item/storage/belt/soulstone
@@ -308,7 +308,7 @@
/obj/item/storage/belt/soulstone/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(
/obj/item/soulstone
@@ -331,7 +331,7 @@
/obj/item/storage/belt/champion/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 1
STR.can_hold = list(
/obj/item/clothing/mask/luchador
@@ -346,7 +346,7 @@
/obj/item/storage/belt/military/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_SMALL
/obj/item/storage/belt/military/snack
@@ -359,7 +359,7 @@
/obj/item/storage/belt/military/snack/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.max_w_class = WEIGHT_CLASS_SMALL
STR.can_hold = typecacheof(list(
@@ -427,7 +427,7 @@
/obj/item/storage/belt/military/assault/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
/obj/item/storage/belt/durathread
@@ -480,7 +480,7 @@
/obj/item/storage/belt/grenade/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 30
STR.display_numerical_stacking = TRUE
STR.max_combined_w_class = 60
@@ -533,7 +533,7 @@
/obj/item/storage/belt/wands/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(
/obj/item/gun/magic/wand
@@ -559,7 +559,7 @@
/obj/item/storage/belt/janitor/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.max_w_class = WEIGHT_CLASS_BULKY // Set to this so the light replacer can fit.
STR.can_hold = typecacheof(list(
@@ -586,7 +586,7 @@
/obj/item/storage/belt/bandolier/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 18
STR.display_numerical_stacking = TRUE
STR.can_hold = typecacheof(list(
@@ -602,7 +602,7 @@
/obj/item/storage/belt/bandolier/durathread/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 32
STR.display_numerical_stacking = TRUE
STR.can_hold = typecacheof(list(
@@ -617,9 +617,12 @@
/obj/item/storage/belt/medolier/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 15
STR.display_numerical_stacking = FALSE
+ STR.allow_quick_gather = TRUE
+ STR.allow_quick_empty = TRUE
+ STR.click_gather = TRUE
STR.can_hold = typecacheof(list(
/obj/item/reagent_containers/syringe/dart
))
@@ -628,6 +631,25 @@
for(var/i in 1 to 16)
new /obj/item/reagent_containers/syringe/dart/(src)
+/obj/item/storage/belt/medolier/afterattack(obj/target, mob/user , proximity)
+ if(!(istype(target, /obj/item/reagent_containers/glass/beaker)))
+ return
+ if(!proximity)
+ return
+ if(!target.reagents)
+ return
+
+ for(var/obj/item/reagent_containers/syringe/dart/D in contents)
+ if(round(target.reagents.total_volume, 1) <= 0)
+ to_chat(user, "You soak as many of the darts as you can with the contents from [target].")
+ return
+ if(D.mode == SYRINGE_INJECT)
+ continue
+
+ D.afterattack(target, user, proximity)
+
+ ..()
+
/obj/item/storage/belt/holster
name = "shoulder holster"
desc = "A holster to carry a handgun and ammo. WARNING: Badasses only."
@@ -637,7 +659,7 @@
/obj/item/storage/belt/holster/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 3
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.can_hold = typecacheof(list(
@@ -661,7 +683,7 @@
/obj/item/storage/belt/fannypack/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 3
STR.max_w_class = WEIGHT_CLASS_SMALL
@@ -728,7 +750,7 @@
/obj/item/storage/belt/sabre/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 1
STR.rustle_sound = FALSE
STR.max_w_class = WEIGHT_CLASS_BULKY
diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm
index 85a06f0c1e..c658eee3d5 100644
--- a/code/game/objects/items/storage/book.dm
+++ b/code/game/objects/items/storage/book.dm
@@ -11,7 +11,7 @@
/obj/item/storage/book/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 1
/obj/item/storage/book/attack_self(mob/user)
diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm
index dd6a6b8453..e053ff2a5c 100644
--- a/code/game/objects/items/storage/boxes.dm
+++ b/code/game/objects/items/storage/boxes.dm
@@ -398,7 +398,7 @@
/obj/item/storage/box/donkpockets/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/donkpocket))
/obj/item/storage/box/donkpockets/PopulateContents()
@@ -413,7 +413,7 @@
/obj/item/storage/box/monkeycubes/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 7
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/monkeycube))
@@ -568,7 +568,7 @@
/obj/item/storage/box/snappops/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.can_hold = typecacheof(list(/obj/item/toy/snappop))
STR.max_items = 8
@@ -586,7 +586,7 @@
/obj/item/storage/box/matches/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 10
STR.can_hold = typecacheof(list(/obj/item/match))
@@ -609,7 +609,7 @@
/obj/item/storage/box/lights/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 21
STR.can_hold = typecacheof(list(/obj/item/light/tube, /obj/item/light/bulb))
STR.max_combined_w_class = 21
@@ -855,7 +855,7 @@
if(SMILEY)
desc = "A paper sack with a crude smile etched onto the side."
return 0
- else if(W.is_sharp())
+ else if(W.get_sharpness())
if(!contents.len)
if(item_state == "paperbag_None")
user.show_message("You cut eyeholes into [src].", 1)
@@ -1144,7 +1144,7 @@
if(can_expire)
expiration_date = rand(expiration_date_min, expiration_date_max)
desc += "\nAn expiry date is listed on it. It reads: [expiration_date]"
- var/spess_current_year = GLOB.year_integer + 540
+ var/spess_current_year = GLOB.year_integer
if(expiration_date < spess_current_year)
var/gross_risk = min(round(spess_current_year - expiration_date * 0.1), 1)
var/toxic_risk = min(round(spess_current_year - expiration_date * 0.01), 1)
diff --git a/code/game/objects/items/storage/briefcase.dm b/code/game/objects/items/storage/briefcase.dm
index ed547bc17d..782ffd3add 100644
--- a/code/game/objects/items/storage/briefcase.dm
+++ b/code/game/objects/items/storage/briefcase.dm
@@ -17,7 +17,7 @@
/obj/item/storage/briefcase/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 21
@@ -48,7 +48,7 @@
/obj/item/storage/briefcase/lawyer/family/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 14
diff --git a/code/game/objects/items/storage/dakis.dm b/code/game/objects/items/storage/dakis.dm
index 08748bf37e..2703581a94 100644
--- a/code/game/objects/items/storage/dakis.dm
+++ b/code/game/objects/items/storage/dakis.dm
@@ -13,7 +13,7 @@
/obj/item/storage/daki/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_SMALL
STR.max_combined_w_class = 21
STR.max_items = 3
diff --git a/code/game/objects/items/storage/fancy.dm b/code/game/objects/items/storage/fancy.dm
index 95639918bb..44e122e4b9 100644
--- a/code/game/objects/items/storage/fancy.dm
+++ b/code/game/objects/items/storage/fancy.dm
@@ -25,7 +25,7 @@
var/fancy_open = FALSE
/obj/item/storage/fancy/PopulateContents()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
for(var/i = 1 to STR.max_items)
new spawn_type(src)
@@ -72,7 +72,7 @@
/obj/item/storage/fancy/donut_box/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/donut))
@@ -93,7 +93,7 @@
/obj/item/storage/fancy/egg_box/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 12
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/egg))
@@ -115,7 +115,7 @@
/obj/item/storage/fancy/candle_box/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 5
/obj/item/storage/fancy/candle_box/attack_self(mob_user)
@@ -138,7 +138,7 @@
/obj/item/storage/fancy/cigarettes/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(/obj/item/clothing/mask/cigarette, /obj/item/lighter))
@@ -276,7 +276,7 @@
/obj/item/storage/fancy/rollingpapers/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 10
STR.can_hold = typecacheof(list(/obj/item/rollingpaper))
@@ -300,7 +300,7 @@
/obj/item/storage/fancy/cigarettes/cigars/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 5
STR.can_hold = typecacheof(list(/obj/item/clothing/mask/cigarette/cigar))
@@ -309,9 +309,10 @@
if(fancy_open)
icon_state = "[initial(icon_state)]_open"
- var/cigar_position = 1 //generate sprites for cigars in the box
+ var/cigar_position = 0 //to keep track of the pixel_x offset of each new overlay.
for(var/obj/item/clothing/mask/cigarette/cigar/smokes in contents)
- var/mutable_appearance/cigar_overlay = mutable_appearance(icon, "[smokes.icon_off]_[cigar_position]")
+ var/mutable_appearance/cigar_overlay = mutable_appearance(icon, "[smokes.icon_off]")
+ cigar_overlay.pixel_x = 3 * cigar_position
add_overlay(cigar_overlay)
cigar_position++
@@ -347,6 +348,6 @@
/obj/item/storage/fancy/heart_box/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 8
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/food/snacks/tinychocolate))
diff --git a/code/game/objects/items/storage/firstaid.dm b/code/game/objects/items/storage/firstaid.dm
index 312ef35430..822a1d5011 100644
--- a/code/game/objects/items/storage/firstaid.dm
+++ b/code/game/objects/items/storage/firstaid.dm
@@ -170,7 +170,7 @@
/obj/item/storage/firstaid/tactical/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
/obj/item/storage/firstaid/tactical/PopulateContents()
@@ -200,7 +200,7 @@
/obj/item/storage/pill_bottle/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/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))
@@ -337,7 +337,7 @@
/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."
@@ -363,7 +363,7 @@
/obj/item/storage/belt/organbox/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 16
STR.max_w_class = WEIGHT_CLASS_BULKY
STR.max_combined_w_class = 20
diff --git a/code/game/objects/items/storage/lockbox.dm b/code/game/objects/items/storage/lockbox.dm
index eeebc6f4c5..1607b19c2f 100644
--- a/code/game/objects/items/storage/lockbox.dm
+++ b/code/game/objects/items/storage/lockbox.dm
@@ -15,7 +15,7 @@
/obj/item/storage/lockbox/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 14
STR.max_items = 4
@@ -101,7 +101,7 @@
/obj/item/storage/lockbox/medal/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_SMALL
STR.max_items = 10
STR.max_combined_w_class = 20
diff --git a/code/game/objects/items/storage/secure.dm b/code/game/objects/items/storage/secure.dm
index 20dae54a71..8618e4c3ae 100644
--- a/code/game/objects/items/storage/secure.dm
+++ b/code/game/objects/items/storage/secure.dm
@@ -26,7 +26,7 @@
/obj/item/storage/secure/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_SMALL
STR.max_combined_w_class = 14
@@ -136,7 +136,7 @@
/obj/item/storage/secure/briefcase/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 21
STR.max_w_class = WEIGHT_CLASS_NORMAL
@@ -146,7 +146,7 @@
/obj/item/storage/secure/briefcase/syndie/PopulateContents()
..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
for(var/i = 0, i < STR.max_items - 2, i++)
new /obj/item/stack/spacecash/c1000(src)
@@ -170,7 +170,7 @@
/obj/item/storage/secure/safe/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.cant_hold = typecacheof(list(/obj/item/storage/secure/briefcase))
STR.max_w_class = 8 //??
diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm
index d18212be42..251703f907 100644
--- a/code/game/objects/items/storage/toolbox.dm
+++ b/code/game/objects/items/storage/toolbox.dm
@@ -35,6 +35,8 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/storage/toolbox/update_icon()
..()
cut_overlays()
+ if(blood_DNA && blood_DNA.len)
+ add_blood_overlay()
if(has_latches)
var/icon/I = icon('icons/obj/storage.dmi', latches)
add_overlay(I)
@@ -122,7 +124,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/storage/toolbox/syndicate/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.silent = TRUE
/obj/item/storage/toolbox/syndicate/PopulateContents()
@@ -163,7 +165,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/storage/toolbox/brass/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 28
STR.max_items = 28
@@ -218,7 +220,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/storage/toolbox/artistic/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 20
STR.max_items = 10
@@ -256,7 +258,7 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
/obj/item/storage/toolbox/gold_real/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 40
STR.max_items = 12
diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm
index cf5d685b4a..84ebc28afa 100644
--- a/code/game/objects/items/storage/uplink_kits.dm
+++ b/code/game/objects/items/storage/uplink_kits.dm
@@ -220,7 +220,7 @@
/obj/item/storage/box/syndie_kit/space/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.can_hold = typecacheof(list(/obj/item/clothing/suit/space/syndicate, /obj/item/clothing/head/helmet/space/syndicate))
@@ -244,7 +244,7 @@
/obj/item/storage/box/syndie_kit/chemical/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 14
/obj/item/storage/box/syndie_kit/chemical/PopulateContents()
diff --git a/code/game/objects/items/storage/wallets.dm b/code/game/objects/items/storage/wallets.dm
index cb5790e45f..7a6899ad15 100644
--- a/code/game/objects/items/storage/wallets.dm
+++ b/code/game/objects/items/storage/wallets.dm
@@ -11,7 +11,7 @@
/obj/item/storage/wallet/ComponentInitialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 4
STR.cant_hold = typecacheof(list(/obj/item/screwdriver/power))
STR.can_hold = typecacheof(list(
diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm
index bfe630ba01..ee126971a7 100644
--- a/code/game/objects/items/stunbaton.dm
+++ b/code/game/objects/items/stunbaton.dm
@@ -1,4 +1,5 @@
#define STUNBATON_CHARGE_LENIENCY 0.3
+#define STUNBATON_DEPLETION_RATE 0.006
/obj/item/melee/baton
name = "stunbaton"
@@ -76,7 +77,7 @@
update_icon()
/obj/item/melee/baton/process()
- deductcharge(hitcost * 0.004, FALSE, FALSE)
+ deductcharge(round(hitcost * STUNBATON_DEPLETION_RATE), FALSE, FALSE)
/obj/item/melee/baton/update_icon()
if(status)
@@ -250,4 +251,5 @@
sparkler?.activate()
. = ..()
-#undef STUNBATON_CHARGE_LENIENCY
\ No newline at end of file
+#undef STUNBATON_CHARGE_LENIENCY
+#undef STUNBATON_DEPLETION_RATE
diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm
index b672eb01ca..f592055338 100644
--- a/code/game/objects/items/tanks/jetpack.dm
+++ b/code/game/objects/items/tanks/jetpack.dm
@@ -17,7 +17,7 @@
/obj/item/tank/jetpack/New()
..()
if(gas_type)
- air_contents.gases[gas_type] = (6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)
+ air_contents.gases[gas_type] = ((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
ion_trail = new
ion_trail.set_up(src)
@@ -37,42 +37,50 @@
return
if(!on)
- turn_on()
+ turn_on(user)
to_chat(user, "You turn the jetpack on.")
else
- turn_off()
+ turn_off(user)
to_chat(user, "You turn the jetpack off.")
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
-/obj/item/tank/jetpack/proc/turn_on()
+/obj/item/tank/jetpack/proc/turn_on(mob/user)
on = TRUE
icon_state = "[initial(icon_state)]-on"
ion_trail.start()
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/move_react)
+ if(full_speed)
+ user.add_movespeed_modifier(MOVESPEED_ID_JETPACK, priority=100, multiplicative_slowdown=-2, movetypes=FLOATING, conflict=MOVE_CONFLICT_JETPACK)
-/obj/item/tank/jetpack/proc/turn_off()
+/obj/item/tank/jetpack/proc/turn_off(mob/user)
on = FALSE
stabilizers = FALSE
icon_state = initial(icon_state)
ion_trail.stop()
+ UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
+ user.remove_movespeed_modifier(MOVESPEED_ID_JETPACK)
+
+/obj/item/tank/jetpack/proc/move_react(mob/user)
+ allow_thrust(0.01, user)
/obj/item/tank/jetpack/proc/allow_thrust(num, mob/living/user)
if(!on)
return
if((num < 0.005 || air_contents.total_moles() < num))
- turn_off()
+ turn_off(user)
return
var/datum/gas_mixture/removed = air_contents.remove(num)
if(removed.total_moles() < 0.005)
- turn_off()
+ turn_off(user)
return
var/turf/T = get_turf(user)
T.assume_air(removed)
- return 1
+ return TRUE
/obj/item/tank/jetpack/suicide_act(mob/user)
if (istype(user, /mob/living/carbon/human/))
@@ -96,22 +104,22 @@
if(!on)
return
if((num < 0.005 || air_contents.total_moles() < num))
- turn_off()
+ turn_off(user)
return
if(rand(0,250) == 0)
to_chat(user, "You feel your jetpack's engines cut out.")
- turn_off()
+ turn_off(user)
return
var/datum/gas_mixture/removed = air_contents.remove(num)
if(removed.total_moles() < 0.005)
- turn_off()
+ turn_off(user)
return
var/turf/T = get_turf(user)
T.assume_air(removed)
- return 1
+ return TRUE
/obj/item/tank/jetpack/void
name = "void jetpack (oxygen)"
@@ -178,6 +186,7 @@
full_speed = FALSE
var/datum/gas_mixture/temp_air_contents
var/obj/item/tank/internals/tank = null
+ var/mob/living/carbon/human/cur_user
/obj/item/tank/jetpack/suit/New()
..()
@@ -198,28 +207,30 @@
return
..()
-/obj/item/tank/jetpack/suit/turn_on()
- if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc))
+/obj/item/tank/jetpack/suit/turn_on(mob/user)
+ if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc) || loc.loc != user)
return
- var/mob/living/carbon/human/H = loc.loc
+ var/mob/living/carbon/human/H = user
tank = H.s_store
air_contents = tank.air_contents
START_PROCESSING(SSobj, src)
+ cur_user = user
..()
-/obj/item/tank/jetpack/suit/turn_off()
+/obj/item/tank/jetpack/suit/turn_off(mob/user)
tank = null
air_contents = temp_air_contents
STOP_PROCESSING(SSobj, src)
+ cur_user = null
..()
/obj/item/tank/jetpack/suit/process()
if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc))
- turn_off()
+ turn_off(cur_user)
return
var/mob/living/carbon/human/H = loc.loc
if(!tank || tank != H.s_store)
- turn_off()
+ turn_off(cur_user)
return
..()
diff --git a/code/game/objects/items/tanks/watertank.dm b/code/game/objects/items/tanks/watertank.dm
index 8f2b85098d..f3be8cefc8 100644
--- a/code/game/objects/items/tanks/watertank.dm
+++ b/code/game/objects/items/tanks/watertank.dm
@@ -24,7 +24,7 @@
/obj/item/watertank/ui_action_click(mob/user)
toggle_mister(user)
-/obj/item/watertank/item_action_slot_check(slot, mob/user)
+/obj/item/watertank/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == user.getBackSlot())
return 1
@@ -341,7 +341,7 @@
/obj/item/reagent_containers/chemtank/ui_action_click()
toggle_injection()
-/obj/item/reagent_containers/chemtank/item_action_slot_check(slot, mob/user)
+/obj/item/reagent_containers/chemtank/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_BACK)
return 1
diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm
index 5fa0624c0a..e16b0dd690 100644
--- a/code/game/objects/items/teleportation.dm
+++ b/code/game/objects/items/teleportation.dm
@@ -187,8 +187,13 @@
user.show_message("\The [src] is recharging!")
return
var/atom/T = L[t1]
+ var/implantcheckmate = FALSE
+ if(isliving(T))
+ var/mob/living/M = T
+ if(!locate(/obj/item/implant/tracking) in M.implants) //The user was too slow and let the target mob's tracking implant expire or get removed.
+ implantcheckmate = TRUE
var/area/A = get_area(T)
- if(A.noteleport)
+ if(A.noteleport || implantcheckmate)
to_chat(user, "\The [src] is malfunctioning.")
return
current_location = get_turf(user) //Recheck.
diff --git a/code/game/objects/items/teleprod.dm b/code/game/objects/items/teleprod.dm
index 40392c19c3..f427bf6c4c 100644
--- a/code/game/objects/items/teleprod.dm
+++ b/code/game/objects/items/teleprod.dm
@@ -6,11 +6,11 @@
item_state = "teleprod"
slot_flags = null
-/obj/item/melee/baton/cattleprod/teleprod/baton_stun(mob/living/carbon/M, mob/living/carbon/user)//handles making things teleport when hit
+/obj/item/melee/baton/cattleprod/teleprod/baton_stun(mob/living/L, mob/living/carbon/user)//handles making things teleport when hit
. = ..()
- if(!. || !istype(M) || M.anchored)
+ if(!. || L.anchored)
return
- do_teleport(M, get_turf(M), 15, channel = TELEPORT_CHANNEL_BLUESPACE)
+ do_teleport(L, get_turf(L), 15, channel = TELEPORT_CHANNEL_BLUESPACE)
/obj/item/melee/baton/cattleprod/teleprod/clowning_around(mob/living/user)
user.visible_message("[user] accidentally hits [user.p_them()]self with [src]!", \
diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/theft_tools.dm
index b99be7e988..d52c280f1b 100644
--- a/code/game/objects/items/theft_tools.dm
+++ b/code/game/objects/items/theft_tools.dm
@@ -49,6 +49,10 @@
lefthand_file = 'icons/mob/inhands/misc/sheets_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/sheets_righthand.dmi'
var/obj/item/nuke_core/core
+ var/nt =FALSE //For the lid
+
+/obj/item/nuke_core_container/nt
+ nt = TRUE
/obj/item/nuke_core_container/Destroy()
QDEL_NULL(core)
@@ -67,10 +71,13 @@
/obj/item/nuke_core_container/proc/seal()
if(istype(core))
STOP_PROCESSING(SSobj, core)
- icon_state = "core_container_sealed"
playsound(src, 'sound/items/deconstruct.ogg', 60, 1)
if(ismob(loc))
to_chat(loc, "[src] is permanently sealed, [core]'s radiation is contained.")
+ if(nt != TRUE)
+ icon_state = "core_container_sealed"
+ else
+ icon_state = "core_container_sealed_nt"
/obj/item/nuke_core_container/attackby(obj/item/nuke_core/core, mob/user)
if(istype(core))
@@ -92,6 +99,11 @@
toolspeed = 0.5
random_color = FALSE
+/obj/item/screwdriver/nuke/nt
+ desc = "A screwdriver with an ultra thin diamon tip."
+ toolspeed = 0.25
+ icon_state = "screwdriver_nt"
+
/obj/item/paper/guides/antag/nuke_instructions
info = "How to break into a Nanotrasen self-destruct terminal and remove its plutonium core: \
\
@@ -103,6 +115,18 @@
???
\
"
+/obj/item/paper/guides/nt/nuke_instructions
+ info = "How to remove its plutonium core: \
+
\
+
Use a screwdriver with a very thin tip (provided) to unscrew the terminal's front panel
\
+
Dislodge and remove the front panel with a crowbar
\
+
Cut the inner metal plate with a welding tool
\
+
Pry off the inner plate with a crowbar to expose the radioactive core
\
+
Use the core container to remove the plutonium core; the container will take some time to seal
\
+
Send core back to CC
\
+
"
+
+
// STEALING SUPERMATTER
/obj/item/paper/guides/antag/supermatter_sliver
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm
index fb38e4335e..b04d96dc80 100644
--- a/code/game/objects/items/tools/weldingtool.dm
+++ b/code/game/objects/items/tools/weldingtool.dm
@@ -223,7 +223,7 @@
..()
to_chat(user, "It contains [get_fuel()] unit\s of fuel out of [max_fuel].")
-/obj/item/weldingtool/is_hot()
+/obj/item/weldingtool/get_temperature()
return welding * heat
//Returns whether or not the welding tool is currently on.
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 46fabea8b0..de5a53fd9c 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -79,7 +79,7 @@
to_chat(user, "You fill the balloon with the contents of [I].")
I.reagents.trans_to(src, 10)
update_icon()
- else if(I.is_sharp())
+ else if(I.get_sharpness())
balloon_burst()
else
return ..()
@@ -276,6 +276,106 @@
/obj/item/toy/sword/getweight()
return (active ? total_mass_on : total_mass) || w_class *1.25
+/obj/item/toy/sword/cx
+ name = "\improper DX Non-Euplastic LightSword"
+ desc = "A deluxe toy replica of an energy sword. Realistic visuals and sounds! Ages 8 and up."
+ icon = 'icons/obj/items_and_weapons.dmi'
+ icon_state = "cxsword_hilt"
+ item_state = "cxsword"
+ active = FALSE
+ w_class = WEIGHT_CLASS_SMALL
+ attack_verb = list("poked", "jabbed", "hit")
+ light_color = "#37FFF7"
+ var/light_brightness = 3
+ actions_types = list()
+
+/obj/item/toy/sword/cx/pre_altattackby(atom/A, mob/living/user, params) //checks if it can do right click memes
+ altafterattack(A, user, TRUE, params)
+ return TRUE
+
+/obj/item/toy/sword/cx/altafterattack(atom/target, mob/living/carbon/user, proximity_flag, click_parameters) //does right click memes
+ if(istype(user))
+ user.visible_message("[user] points the tip of [src] at [target].", "You point the tip of [src] at [target].")
+ return TRUE
+
+/obj/item/toy/sword/cx/attack_self(mob/user)
+ active = !( active )
+
+ if (active)
+ to_chat(user, "You activate the holographic blade with a press of a button.")
+ playsound(user, 'sound/weapons/nebon.ogg', 50, 1)
+ w_class = WEIGHT_CLASS_BULKY
+ attack_verb = list("slashed", "stabbed", "ravaged")
+ set_light(light_brightness)
+ update_icon()
+
+ else
+ to_chat(user, "You deactivate the holographic blade with a press of a button.")
+ playsound(user, 'sound/weapons/neboff.ogg', 50, 1)
+ w_class = WEIGHT_CLASS_SMALL
+ attack_verb = list("poked", "jabbed", "hit")
+ set_light(0)
+ update_icon()
+
+ add_fingerprint(user)
+
+/obj/item/toy/sword/cx/update_icon()
+ var/mutable_appearance/blade_overlay = mutable_appearance(icon, "cxsword_blade")
+ var/mutable_appearance/gem_overlay = mutable_appearance(icon, "cxsword_gem")
+
+ if(light_color)
+ blade_overlay.color = light_color
+ gem_overlay.color = light_color
+
+ cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
+
+ add_overlay(gem_overlay)
+
+ if(active)
+ add_overlay(blade_overlay)
+ if(ismob(loc))
+ var/mob/M = loc
+ M.update_inv_hands()
+
+/obj/item/toy/sword/cx/AltClick(mob/living/user)
+ if(!in_range(src, user)) //Basic checks to prevent abuse
+ return
+ if(user.incapacitated() || !istype(user))
+ to_chat(user, "You can't do that right now!")
+ return
+
+ if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes")
+ var/energy_color_input = input(usr,"","Choose Energy Color",light_color) as color|null
+ if(energy_color_input)
+ light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
+ update_icon()
+ update_light()
+
+/obj/item/toy/sword/cx/worn_overlays(isinhands, icon_file)
+ . = ..()
+ if(active)
+ if(isinhands)
+ var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "cxsword_blade")
+ blade_inhand.color = light_color
+ . += blade_inhand
+
+/obj/item/toy/sword/cx/attackby(obj/item/W, mob/living/user, params)
+ if(istype(W, /obj/item/toy/sword/cx))
+ if(HAS_TRAIT(W, TRAIT_NODROP) || HAS_TRAIT(src, TRAIT_NODROP))
+ to_chat(user, "\the [HAS_TRAIT(src, TRAIT_NODROP) ? src : W] is stuck to your hand, you can't attach it to \the [HAS_TRAIT(src, TRAIT_NODROP) ? W : src]!")
+ return
+ else
+ to_chat(user, "You combine the two plastic swords, making a single supermassive toy! You're fake-cool.")
+ new /obj/item/twohanded/dualsaber/hypereutactic/toy(user.loc)
+ qdel(W)
+ qdel(src)
+ else
+ return ..()
+
+/obj/item/toy/sword/cx/examine(mob/user)
+ ..()
+ to_chat(user, "Alt-click to recolor it.")
+
/*
* Foam armblade
*/
@@ -337,6 +437,30 @@
/obj/item/twohanded/dualsaber/toy/IsReflect()//Stops Toy Dualsabers from reflecting energy projectiles
return FALSE
+/obj/item/twohanded/dualsaber/hypereutactic/toy
+ name = "\improper DX Hyper-Euplastic LightSword"
+ desc = "A supermassive toy envisioned to cleave the very fabric of space and time itself in twain. Realistic visuals and sounds! Ages 8 and up."
+ force = 0
+ throwforce = 0
+ throw_speed = 3
+ throw_range = 5
+ force_unwielded = 0
+ force_wielded = 0
+ attack_verb = list("attacked", "struck", "hit")
+ total_mass_on = TOTAL_MASS_TOY_SWORD
+ slowdown_wielded = 0
+
+/obj/item/twohanded/dualsaber/hypereutactic/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 FALSE
+
+/obj/item/twohanded/dualsaber/hypereutactic/toy/IsReflect()//Stops it from reflecting energy projectiles
+ return FALSE
+
+/obj/item/twohanded/dualsaber/hypereutactic/toy/rainbow
+ name = "\improper Hyper-Euclidean Reciprocating Trigonometric Zweihander"
+ desc = "A custom-built toy with fancy rainbow lights built-in."
+ hacked = TRUE
+
/obj/item/toy/katana
name = "replica katana"
desc = "Woefully underpowered in D20."
diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm
index b1c2c36585..14f924a27e 100644
--- a/code/game/objects/items/twohanded.dm
+++ b/code/game/objects/items/twohanded.dm
@@ -6,6 +6,7 @@
* Spears
* CHAINSAWS
* Bone Axe and Spear
+ * And more
*/
/*##################################################################
@@ -346,7 +347,8 @@
icon_state = "dualsaber[item_color][wielded]"
else
icon_state = "dualsaber0"
- SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+
+ clean_blood()
/obj/item/twohanded/dualsaber/attack(mob/target, mob/living/carbon/human/user)
if(user.has_dna())
@@ -463,6 +465,116 @@
else
return ..()
+/////////////////////////////////////////////////////
+// HYPEREUTACTIC Blades /////////////////////////
+/////////////////////////////////////////////////////
+
+/obj/item/twohanded/dualsaber/hypereutactic
+ icon = 'icons/obj/1x2.dmi'
+ icon_state = "hypereutactic"
+ lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi'
+ righthand_file = 'icons/mob/inhands/64x64_righthand.dmi'
+ item_state = "hypereutactic"
+ inhand_x_dimension = 64
+ inhand_y_dimension = 64
+ name = "hypereutactic blade"
+ desc = "A supermassive weapon envisioned to cleave the very fabric of space and time itself in twain, the hypereutactic blade dynamically flash-forges a hypereutactic crystaline nanostructure capable of passing through most known forms of matter like a hot knife through butter."
+ force = 7
+ force_unwielded = 7
+ force_wielded = 40
+ wieldsound = 'sound/weapons/nebon.ogg'
+ unwieldsound = 'sound/weapons/neboff.ogg'
+ hitsound_on = 'sound/weapons/nebhit.ogg'
+ slowdown_wielded = 1
+ armour_penetration = 60
+ light_color = "#37FFF7"
+ rainbow_colors = list("#FF0000", "#FFFF00", "#00FF00", "#00FFFF", "#0000FF","#FF00FF", "#3399ff", "#ff9900", "#fb008b", "#9800ff", "#00ffa3", "#ccff00")
+ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "destroyed", "ripped", "devastated", "shredded")
+ spinnable = FALSE
+ total_mass_on = 4
+
+/obj/item/twohanded/dualsaber/hypereutactic/chaplain
+ name = "\improper divine lightblade"
+ desc = "A giant blade of bright and holy light, said to cut down the wicked with ease."
+ force = 5
+ force_unwielded = 5
+ force_wielded = 20
+ block_chance = 50
+ armour_penetration = 0
+ var/chaplain_spawnable = TRUE
+ obj_flags = UNIQUE_RENAME
+
+/obj/item/twohanded/dualsaber/hypereutactic/chaplain/Initialize()
+ . = ..()
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
+
+/obj/item/twohanded/dualsaber/hypereutactic/chaplain/IsReflect()
+ return FALSE
+
+/obj/item/twohanded/dualsaber/hypereutactic/pre_altattackby(atom/A, mob/living/user, params) //checks if it can do right click memes
+ altafterattack(A, user, TRUE, params)
+ return TRUE
+
+/obj/item/twohanded/dualsaber/hypereutactic/altafterattack(atom/target, mob/living/user, proximity_flag, click_parameters) //does right click memes
+ if(istype(user))
+ user.visible_message("[user] points the tip of [src] at [target].", "You point the tip of [src] at [target].")
+ return TRUE
+
+/obj/item/twohanded/dualsaber/hypereutactic/update_icon()
+ var/mutable_appearance/blade_overlay = mutable_appearance(icon, "hypereutactic_blade")
+ var/mutable_appearance/gem_overlay = mutable_appearance(icon, "hypereutactic_gem")
+
+ if(light_color)
+ blade_overlay.color = light_color
+ gem_overlay.color = light_color
+
+ cut_overlays() //So that it doesn't keep stacking overlays non-stop on top of each other
+
+ add_overlay(gem_overlay)
+
+ if(wielded)
+ add_overlay(blade_overlay)
+ if(ismob(loc))
+ var/mob/M = loc
+ M.update_inv_hands()
+
+ clean_blood()
+
+/obj/item/twohanded/dualsaber/hypereutactic/AltClick(mob/living/user)
+ if(!user.canUseTopic(src, BE_CLOSE, FALSE) || hacked)
+ return
+ if(user.incapacitated() || !istype(user))
+ to_chat(user, "You can't do that right now!")
+ return
+ if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes")
+ var/energy_color_input = input(usr,"","Choose Energy Color",light_color) as color|null
+ if(!energy_color_input || !user.canUseTopic(src, BE_CLOSE, FALSE) || hacked)
+ return
+ light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
+ update_icon()
+ update_light()
+
+/obj/item/twohanded/dualsaber/hypereutactic/worn_overlays(isinhands, icon_file)
+ . = ..()
+ if(isinhands)
+ var/mutable_appearance/gem_inhand = mutable_appearance(icon_file, "hypereutactic_gem")
+ gem_inhand.color = light_color
+ . += gem_inhand
+ if(wielded)
+ var/mutable_appearance/blade_inhand = mutable_appearance(icon_file, "hypereutactic_blade")
+ blade_inhand.color = light_color
+ . += blade_inhand
+
+/obj/item/twohanded/dualsaber/hypereutactic/examine(mob/user)
+ ..()
+ if(!hacked)
+ to_chat(user, "Alt-click to recolor it.")
+
+/obj/item/twohanded/dualsaber/hypereutactic/rainbow_process()
+ . = ..()
+ update_icon()
+ update_light()
+
//spears
/obj/item/twohanded/spear
icon_state = "spearglass0"
@@ -624,7 +736,7 @@
force = on ? force_on : initial(force)
throwforce = on ? force_on : initial(force)
icon_state = "chainsaw_[on ? "on" : "off"]"
- GET_COMPONENT_FROM(butchering, /datum/component/butchering, src)
+ var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.butchering_enabled = on
if(on)
@@ -847,18 +959,20 @@
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
- var/datum/component/mobhook
+ var/mob/listeningTo
var/zoom_out_amt = 6
var/zoom_amt = 10
+/obj/item/twohanded/binoculars/Destroy()
+ listeningTo = null
+ return ..()
+
/obj/item/twohanded/binoculars/wield(mob/user)
. = ..()
if(!wielded)
return
- if(QDELETED(mobhook))
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/unwield)))
- else
- user.TakeComponent(mobhook)
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/unwield)
+ listeningTo = user
user.visible_message("[user] holds [src] up to [user.p_their()] eyes.","You hold [src] up to your eyes.")
item_state = "binoculars_wielded"
user.regenerate_icons()
@@ -882,7 +996,8 @@
/obj/item/twohanded/binoculars/unwield(mob/user)
. = ..()
- mobhook.RemoveComponent()
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
user.visible_message("[user] lowers [src].","You lower [src].")
item_state = "binoculars"
user.regenerate_icons()
@@ -891,4 +1006,4 @@
var/client/C = user.client
C.change_view(CONFIG_GET(string/default_view))
user.client.pixel_x = 0
- user.client.pixel_y = 0
+ user.client.pixel_y = 0
\ No newline at end of file
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index 4552e846ad..fec17cfa69 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -528,7 +528,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/melee/baseball_bat/chaplain/Initialize()
. = ..()
- AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
/obj/item/melee/baseball_bat/homerun
name = "home run bat"
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index 5f21862c17..7526807eeb 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -8,6 +8,7 @@
var/climbable = FALSE
var/mob/living/structureclimber
var/broken = 0 //similar to machinery's stat BROKEN
+ layer = BELOW_OBJ_LAYER
/obj/structure/Initialize()
if (!armor)
diff --git a/code/game/objects/structures/barsigns.dm b/code/game/objects/structures/barsigns.dm
index 2093ae5660..053512a256 100644
--- a/code/game/objects/structures/barsigns.dm
+++ b/code/game/objects/structures/barsigns.dm
@@ -1,4 +1,4 @@
-/obj/structure/sign/barsign // All Signs are 64 by 32 pixels, they take two tiles
+/obj/structure/sign/barsign // All Signs are 64 by 64 pixels, though most of them are made to fit 64 x 32 and only take the two lowermost tiles.
name = "Bar Sign"
desc = "A bar sign with no writing on it."
icon = 'icons/obj/barsigns.dmi'
diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm
index dde9bce1bc..cec97d5d8b 100644
--- a/code/game/objects/structures/beds_chairs/chair.dm
+++ b/code/game/objects/structures/beds_chairs/chair.dm
@@ -495,7 +495,25 @@
icon_state = "sofamiddle"
icon = 'icons/obj/sofa.dmi'
buildstackamount = 1
- item_chair = null
+ var/mutable_appearance/armrest
+
+/obj/structure/chair/sofa/Initialize()
+ armrest = mutable_appearance(icon, "[icon_state]_armrest")
+ return ..()
+
+/obj/structure/chair/sofa/post_buckle_mob(mob/living/M)
+ . = ..()
+ update_armrest()
+
+/obj/structure/chair/sofa/proc/update_armrest()
+ if(has_buckled_mobs())
+ add_overlay(armrest)
+ else
+ cut_overlay(armrest)
+
+/obj/structure/chair/sofa/post_unbuckle_mob()
+ . = ..()
+ update_armrest()
/obj/structure/chair/sofa/left
icon_state = "sofaend_left"
@@ -504,4 +522,7 @@
icon_state = "sofaend_right"
/obj/structure/chair/sofa/corner
- icon_state = "sofacorner"
\ No newline at end of file
+ icon_state = "sofacorner"
+
+/obj/structure/chair/sofa/corner/handle_layer() //only the armrest/back of this chair should cover the mob.
+ return
\ No newline at end of file
diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm
index 1f7f0ab391..1e1fee0bfe 100644
--- a/code/game/objects/structures/bedsheet_bin.dm
+++ b/code/game/objects/structures/bedsheet_bin.dm
@@ -41,7 +41,7 @@ LINEN BINS
return
/obj/item/bedsheet/attackby(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/wirecutters) || I.is_sharp())
+ if(istype(I, /obj/item/wirecutters) || I.get_sharpness())
var/obj/item/stack/sheet/cloth/C = new (get_turf(src), 3)
transfer_fingerprints_to(C)
C.add_fingerprint(user)
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index edcb4a6181..172120861b 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -4,7 +4,6 @@
icon = 'icons/obj/closet.dmi'
icon_state = "generic"
density = TRUE
- layer = BELOW_OBJ_LAYER
var/icon_door = null
var/icon_door_override = FALSE //override to have open overlay use icon different to its base's
var/secure = FALSE //secure locker or not, also used if overriding a non-secure locker with a secure door overlay to add fancy lights
@@ -615,3 +614,6 @@
user.resting = FALSE
togglelock(user)
T1.visible_message("[user] dives into [src]!")
+
+/obj/structure/closet/canReachInto(atom/user, atom/target, list/next, view_only, obj/item/tool)
+ return ..() && opened
diff --git a/code/game/objects/structures/crates_lockers/closets/genpop.dm b/code/game/objects/structures/crates_lockers/closets/genpop.dm
new file mode 100644
index 0000000000..80b64aaedc
--- /dev/null
+++ b/code/game/objects/structures/crates_lockers/closets/genpop.dm
@@ -0,0 +1,117 @@
+/obj/structure/closet/secure_closet/genpop
+ desc = "It's a secure locker for inmates's personal belongings."
+ var/default_desc = "It's a secure locker for the storage inmates's personal belongings during their time in prison."
+ name = "prisoner closet"
+ var/default_name = "prisoner closet"
+ req_access = list(ACCESS_BRIG)
+ var/obj/item/card/id/prisoner/registered_id = null
+ icon_state = "prisoner"
+ locked = FALSE
+ anchored = TRUE
+ opened = TRUE
+ density = FALSE
+
+/obj/structure/closet/secure_closet/genpop/attackby(obj/item/W, mob/user, params)
+ if(!broken && locked && W == registered_id) //Prisoner opening
+ handle_prisoner_id(user)
+ return
+
+ return ..()
+
+/obj/structure/closet/secure_closet/genpop/proc/handle_prisoner_id(mob/user)
+ var/obj/item/card/id/prisoner/prisoner_id = null
+ for(prisoner_id in user.held_items)
+ if(prisoner_id != registered_id)
+ prisoner_id = null
+ else
+ break
+
+ if(!prisoner_id)
+ to_chat(user, "Access Denied.")
+ return FALSE
+
+ qdel(registered_id)
+ registered_id = null
+ locked = FALSE
+ open(user)
+ desc = "It's a secure locker for prisoner effects."
+ to_chat(user, "You insert your prisoner id into \the [src] and it springs open!")
+
+ return TRUE
+
+/obj/structure/closet/secure_closet/genpop/proc/handle_edit_sentence(mob/user)
+ var/prisoner_name = input(user, "Please input the name of the prisoner.", "Prisoner Name", registered_id.registered_name) as text|null
+ if(prisoner_name == null | !user.Adjacent(src))
+ return FALSE
+ var/sentence_length = input(user, "Please input the length of their sentence in minutes (0 for perma).", "Sentence Length", registered_id.sentence) as num|null
+ if(sentence_length == null | !user.Adjacent(src))
+ return FALSE
+ var/crimes = input(user, "Please input their crimes.", "Crimes", registered_id.crime) as text|null
+ if(crimes == null | !user.Adjacent(src))
+ return FALSE
+
+ registered_id.registered_name = prisoner_name
+ var/filteredsentlength = text2num(sentence_length)
+ registered_id.sentence = filteredsentlength ? (filteredsentlength MINUTES) + world.time : 0
+ registered_id.crime = crimes
+ registered_id.update_label(prisoner_name, registered_id.assignment)
+ if(registered_id.sentence)
+ START_PROCESSING(SSobj, registered_id)
+ else
+ STOP_PROCESSING(SSobj, registered_id)
+
+ name = "[default_name] ([prisoner_name])"
+ desc = "[default_desc] It contains the personal effects of [prisoner_name]."
+
+ return TRUE
+
+/obj/structure/closet/secure_closet/genpop/togglelock(mob/living/user)
+ if(!allowed(user))
+ return ..()
+
+ if(!broken && locked && registered_id != null)
+ var/name = registered_id.registered_name
+ var/result = alert(user, "This locker currently contains [name]'s personal belongings ","Locker In Use","Reset","Amend ID", "Open")
+ if(!user.Adjacent(src))
+ return
+ if(result == "Reset")
+ name = default_name
+ desc = default_desc
+ registered_id = null
+ if(result == "Open" | result == "Reset")
+ locked = FALSE
+ open(user)
+ if(result == "Amend ID")
+ handle_edit_sentence(user)
+ else
+ return ..()
+
+/obj/structure/closet/secure_closet/genpop/close(mob/living/user)
+ if(registered_id != null)
+ locked = TRUE
+ return ..()
+
+/obj/structure/closet/secure_closet/genpop/attack_hand(mob/user)
+ if(user.lying && get_dist(src, user) > 0)
+ return
+
+ if(!broken && registered_id != null && registered_id in user.held_items)
+ handle_prisoner_id(user)
+ return
+
+ if(!broken && opened && !locked && allowed(user) && !registered_id) //Genpop setup
+
+ registered_id = new /obj/item/card/id/prisoner/(src.contents)
+ if(handle_edit_sentence(user))
+ close(user)
+ locked = TRUE
+ update_icon()
+ registered_id.forceMove(src.loc)
+ new /obj/item/clothing/under/rank/prisoner(src.loc)
+ else
+ qdel(registered_id)
+ registered_id = null
+
+ return
+
+ ..()
\ No newline at end of file
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 a7adafdad4..f173ac0662 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
@@ -10,7 +10,7 @@
new /obj/item/clothing/under/rank/chief_engineer(src)
new /obj/item/clothing/under/rank/chief_engineer/skirt(src)
new /obj/item/clothing/head/hardhat/white(src)
- new /obj/item/clothing/head/welding(src)
+ new /obj/item/clothing/head/hardhat/weldhat/white(src)
new /obj/item/clothing/gloves/color/yellow(src)
new /obj/item/clothing/shoes/sneakers/brown(src)
new /obj/item/tank/jetpack/suit(src)
diff --git a/code/game/objects/structures/false_walls.dm b/code/game/objects/structures/false_walls.dm
index d52ec81a05..d7e2d5564a 100644
--- a/code/game/objects/structures/false_walls.dm
+++ b/code/game/objects/structures/false_walls.dm
@@ -236,7 +236,7 @@
canSmoothWith = list(/obj/structure/falsewall/plasma, /turf/closed/wall/mineral/plasma)
/obj/structure/falsewall/plasma/attackby(obj/item/W, mob/user, params)
- if(W.is_hot() > 300)
+ if(W.get_temperature() > 300)
var/turf/T = get_turf(src)
message_admins("Plasma falsewall ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(T)]")
log_game("Plasma falsewall ignited by [key_name(user)] in [AREACOORD(T)]")
diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm
index 7c73a1fd8c..12529fb9e0 100644
--- a/code/game/objects/structures/flora.dm
+++ b/code/game/objects/structures/flora.dm
@@ -300,18 +300,9 @@
throw_speed = 2
throw_range = 4
-
-/obj/item/twohanded/required/kirbyplants/equipped(mob/living/user)
- var/image/I = image(icon = 'icons/obj/flora/plants.dmi' , icon_state = src.icon_state, loc = user)
- I.copy_overlays(src)
- I.override = 1
- add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I)
- I.layer = ABOVE_MOB_LAYER
- ..()
-
-/obj/item/twohanded/required/kirbyplants/dropped(mob/living/user)
- ..()
- user.remove_alt_appearance("sneaking_mission")
+/obj/item/twohanded/required/kirbyplants/Initialize()
+ . = ..()
+ AddComponent(/datum/component/tactical)
/obj/item/twohanded/required/kirbyplants/random
icon = 'icons/obj/flora/_flora.dmi'
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index cd87075258..31bf9318ce 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -4,7 +4,6 @@
desc = "A large structural assembly made out of metal; It requires a layer of metal before it can be considered a wall."
anchored = TRUE
density = TRUE
- layer = BELOW_OBJ_LAYER
var/state = GIRDER_NORMAL
var/girderpasschance = 20 // percentage chance that a projectile passes through the girder.
var/can_displace = TRUE //If the girder can be moved around by wrenching it
diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm
index 13ca421daa..efb12ae34a 100644
--- a/code/game/objects/structures/mineral_doors.dm
+++ b/code/game/objects/structures/mineral_doors.dm
@@ -6,6 +6,7 @@
density = TRUE
anchored = TRUE
opacity = TRUE
+ layer = CLOSED_DOOR_LAYER
icon = 'icons/obj/doors/mineral_doors.dmi'
icon_state = "metal"
@@ -90,6 +91,7 @@
flick("[initial_state]opening",src)
sleep(10)
density = FALSE
+ layer = OPEN_DOOR_LAYER
state = 1
air_update_turf(1)
update_icon()
@@ -111,6 +113,7 @@
density = TRUE
set_opacity(TRUE)
state = 0
+ layer = initial(layer)
air_update_turf(1)
update_icon()
isSwitchingStates = 0
@@ -190,7 +193,7 @@
return
/obj/structure/mineral_door/transparent/plasma/attackby(obj/item/W, mob/user, params)
- if(W.is_hot())
+ if(W.get_temperature())
var/turf/T = get_turf(src)
message_admins("Plasma mineral door ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(T)]")
log_game("Plasma mineral door ignited by [key_name(user)] in [AREACOORD(T)]")
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index eaf3629718..e7be30520e 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -133,9 +133,11 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an
/obj/structure/bodycontainer/proc/close()
playsound(src, 'sound/effects/roll.ogg', 5, 1)
- playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
+ playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
for(var/atom/movable/AM in connected.loc)
if(!AM.anchored || AM == connected)
+ if(ismob(AM) && !isliving(AM))
+ continue
AM.forceMove(src)
recursive_organ_check(src)
update_icon()
@@ -305,7 +307,7 @@ GLOBAL_LIST_EMPTY(crematoriums)
/obj/structure/tray
icon = 'icons/obj/stationobjs.dmi'
density = TRUE
- layer = BELOW_OBJ_LAYER
+ layer = TRAY_LAYER
var/obj/structure/bodycontainer/connected = null
anchored = TRUE
pass_flags = LETPASSTHROW
diff --git a/code/game/objects/structures/reflector.dm b/code/game/objects/structures/reflector.dm
index 889cdab388..419502e2b0 100644
--- a/code/game/objects/structures/reflector.dm
+++ b/code/game/objects/structures/reflector.dm
@@ -5,7 +5,6 @@
desc = "A base for reflector assemblies."
anchored = FALSE
density = FALSE
- layer = BELOW_OBJ_LAYER
var/deflector_icon_state
var/image/deflector_overlay
var/finished = FALSE
diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm
index dd28168ccc..5e6b35ba4f 100644
--- a/code/game/objects/structures/statues.dm
+++ b/code/game/objects/structures/statues.dm
@@ -127,11 +127,11 @@
..()
/obj/structure/statue/plasma/attackby(obj/item/W, mob/user, params)
- if(W.is_hot() > 300 && !QDELETED(src))//If the temperature of the object is over 300, then ignite
+ if(W.get_temperature() > 300 && !QDELETED(src))//If the temperature of the object is over 300, then ignite
var/turf/T = get_turf(src)
message_admins("Plasma statue ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(T)]")
log_game("Plasma statue ignited by [key_name(user)] in [AREACOORD(T)]")
- ignite(W.is_hot())
+ ignite(W.get_temperature())
else
return ..()
diff --git a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
index ee46538be1..392c802ed8 100644
--- a/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
+++ b/code/game/objects/structures/transit_tubes/transit_tube_pod.dm
@@ -4,7 +4,6 @@
animate_movement = FORWARD_STEPS
anchored = TRUE
density = TRUE
- layer = BELOW_OBJ_LAYER
var/moving = 0
var/datum/gas_mixture/air_contents = new()
diff --git a/code/game/objects/structures/traps.dm b/code/game/objects/structures/traps.dm
index ffc2c344f9..176779abd7 100644
--- a/code/game/objects/structures/traps.dm
+++ b/code/game/objects/structures/traps.dm
@@ -65,6 +65,8 @@
var/mob/M = AM
if(M.mind in immune_minds)
return
+ if(M.anti_magic_check())
+ flare()
if(charges <= 0)
return
flare()
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 46db567b10..76c8f7f11f 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -318,6 +318,7 @@
/obj/machinery/shower/proc/wash_obj(obj/O)
. = SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ . = O.clean_blood()
O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
if(isitem(O))
var/obj/item/I = O
@@ -328,8 +329,9 @@
/obj/machinery/shower/proc/wash_turf()
if(isturf(loc))
var/turf/tile = loc
- SEND_SIGNAL(tile, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
tile.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
+ tile.clean_blood()
+ SEND_SIGNAL(tile, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
for(var/obj/effect/E in tile)
if(is_cleanable(E))
qdel(E)
@@ -381,7 +383,8 @@
else if(H.w_uniform && wash_obj(H.w_uniform))
H.update_inv_w_uniform()
if(washgloves)
- SEND_SIGNAL(H, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ H.clean_blood()
+ SEND_SIGNAL(H, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
if(H.shoes && washshoes && wash_obj(H.shoes))
H.update_inv_shoes()
if(H.wear_mask && washmask && wash_obj(H.wear_mask))
@@ -398,9 +401,11 @@
else
if(M.wear_mask && wash_obj(M.wear_mask))
M.update_inv_wear_mask(0)
- SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ M.clean_blood()
+ SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
else
- SEND_SIGNAL(L, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ L.clean_blood()
+ SEND_SIGNAL(L, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
/obj/machinery/shower/proc/contamination_cleanse(atom/movable/thing)
var/datum/component/radioactive/healthy_green_glow = thing.GetComponent(/datum/component/radioactive)
@@ -498,7 +503,8 @@
H.regenerate_icons()
user.drowsyness = max(user.drowsyness - rand(2,3), 0) //Washing your face wakes you up if you're falling asleep
else
- SEND_SIGNAL(user, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(user, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ user.clean_blood()
/obj/structure/sink/attackby(obj/item/O, mob/living/user, params)
if(busy)
@@ -554,7 +560,8 @@
busy = FALSE
return 1
busy = FALSE
- SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ O.clean_blood()
O.acid_level = 0
create_reagents(5)
reagents.add_reagent(dispensedreagent, 5)
@@ -675,4 +682,4 @@
else
playsound(loc, 'sound/weapons/tap.ogg', 50, 1)
if(BURN)
- playsound(loc, 'sound/items/welder.ogg', 80, 1)
+ playsound(loc, 'sound/items/welder.ogg', 80, 1)
\ No newline at end of file
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 9fc055c2ba..794776cfa5 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -731,8 +731,8 @@
/obj/structure/window/paperframe/attackby(obj/item/W, mob/user)
- if(W.is_hot())
- fire_act(W.is_hot())
+ if(W.get_temperature())
+ fire_act(W.get_temperature())
return
if(user.a_intent == INTENT_HARM)
return ..()
diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm
index e441ccd6cc..f1c5080c8f 100644
--- a/code/game/turfs/change_turf.dm
+++ b/code/game/turfs/change_turf.dm
@@ -41,7 +41,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
/turf/open/copyTurf(turf/T, copy_air = FALSE)
. = ..()
if (isopenturf(T))
- GET_COMPONENT(slip, /datum/component/wet_floor)
+ var/datum/component/wet_floor/slip = GetComponent(/datum/component/wet_floor)
if(slip)
var/datum/component/wet_floor/WF = T.AddComponent(/datum/component/wet_floor)
WF.InheritComponent(slip)
diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm
index f6d234b346..bd24e0ff93 100644
--- a/code/game/turfs/open.dm
+++ b/code/game/turfs/open.dm
@@ -251,6 +251,7 @@
M.apply_water()
SEND_SIGNAL(src, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ clean_blood()
for(var/obj/effect/O in src)
if(is_cleanable(O))
qdel(O)
diff --git a/code/game/turfs/simulated/chasm.dm b/code/game/turfs/simulated/chasm.dm
index 677fba2990..0a7b507488 100644
--- a/code/game/turfs/simulated/chasm.dm
+++ b/code/game/turfs/simulated/chasm.dm
@@ -15,11 +15,11 @@
AddComponent(/datum/component/chasm, SSmapping.get_turf_below(src))
/turf/open/chasm/proc/set_target(turf/target)
- GET_COMPONENT(chasm_component, /datum/component/chasm)
+ var/datum/component/chasm/chasm_component = GetComponent(/datum/component/chasm)
chasm_component.target_turf = target
/turf/open/chasm/proc/drop(atom/movable/AM)
- GET_COMPONENT(chasm_component, /datum/component/chasm)
+ var/datum/component/chasm/chasm_component = GetComponent(/datum/component/chasm)
chasm_component.drop(AM)
/turf/open/chasm/MakeSlippery(wet_setting, min_wet_time, wet_time_to_add, max_wet_time, permanent)
diff --git a/code/game/turfs/simulated/floor/mineral_floor.dm b/code/game/turfs/simulated/floor/mineral_floor.dm
index a77417e4e4..b71fb51123 100644
--- a/code/game/turfs/simulated/floor/mineral_floor.dm
+++ b/code/game/turfs/simulated/floor/mineral_floor.dm
@@ -43,10 +43,10 @@
PlasmaBurn(exposed_temperature)
/turf/open/floor/mineral/plasma/attackby(obj/item/W, mob/user, params)
- if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
+ if(W.get_temperature() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma flooring was ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(src)]")
log_game("Plasma flooring was ignited by [key_name(user)] in [AREACOORD(src)]")
- ignite(W.is_hot())
+ ignite(W.get_temperature())
return
..()
diff --git a/code/game/turfs/simulated/wall/mineral_walls.dm b/code/game/turfs/simulated/wall/mineral_walls.dm
index dbffd1010b..9962f72d4a 100644
--- a/code/game/turfs/simulated/wall/mineral_walls.dm
+++ b/code/game/turfs/simulated/wall/mineral_walls.dm
@@ -94,10 +94,10 @@
canSmoothWith = list(/turf/closed/wall/mineral/plasma, /obj/structure/falsewall/plasma)
/turf/closed/wall/mineral/plasma/attackby(obj/item/W, mob/user, params)
- if(W.is_hot() > 300)//If the temperature of the object is over 300, then ignite
+ if(W.get_temperature() > 300)//If the temperature of the object is over 300, then ignite
message_admins("Plasma wall ignited by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(src)]")
log_game("Plasma wall ignited by [key_name(user)] in [AREACOORD(src)]")
- ignite(W.is_hot())
+ ignite(W.get_temperature())
return
..()
diff --git a/code/modules/NTNet/services/_service.dm b/code/modules/NTNet/services/_service.dm
index 8611c2d25d..3622dc3881 100644
--- a/code/modules/NTNet/services/_service.dm
+++ b/code/modules/NTNet/services/_service.dm
@@ -17,7 +17,7 @@
/datum/ntnet_service/proc/connect(datum/ntnet/net)
if(!istype(net))
return FALSE
- GET_COMPONENT(interface, /datum/component/ntnet_interface)
+ var/datum/component/ntnet_interface/interface = GetComponent(/datum/component/ntnet_interface)
if(!interface.register_connection(net))
return FALSE
if(!net.register_service(src))
@@ -29,7 +29,7 @@
/datum/ntnet_service/proc/disconnect(datum/ntnet/net, force = FALSE)
if(!istype(net) || (!net.unregister_service(src) && !force))
return FALSE
- GET_COMPONENT(interface, /datum/component/ntnet_interface)
+ var/datum/component/ntnet_interface/interface = GetComponent(/datum/component/ntnet_interface)
interface.unregister_connection(net)
networks_by_id -= net.network_id
return TRUE
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 555c35980d..7fafca69f0 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -682,7 +682,7 @@
log_admin("[key_name(usr)] delayed the round start.")
else
to_chat(world, "The game will start in [DisplayTimeText(newtime)].")
- SEND_SOUND(world, sound('sound/ai/attention.ogg'))
+ SEND_SOUND(world, sound(get_announcer_sound("attention")))
log_admin("[key_name(usr)] set the pre-game delay to [DisplayTimeText(newtime)].")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Delay Game Start") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm
index cff7faadd8..eae59fcb93 100644
--- a/code/modules/admin/create_mob.dm
+++ b/code/modules/admin/create_mob.dm
@@ -25,6 +25,9 @@
H.facial_hair_color = H.hair_color
H.eye_color = random_eye_color()
H.dna.blood_type = random_blood_type()
+ H.saved_underwear = H.underwear
+ H.saved_undershirt = H.undershirt
+ H.saved_socks = H.socks
// Mutant randomizing, doesn't affect the mob appearance unless it's the specific mutant.
H.dna.features["mcolor"] = random_short_color()
diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm
index 58fd627c74..70ae133a31 100644
--- a/code/modules/admin/secrets.dm
+++ b/code/modules/admin/secrets.dm
@@ -400,7 +400,7 @@
SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Chinese Cartoons"))
message_admins("[key_name_admin(usr)] made everything kawaii.")
for(var/mob/living/carbon/human/H in GLOB.carbon_list)
- SEND_SOUND(H, sound('sound/ai/animes.ogg'))
+ SEND_SOUND(H, sound(get_announcer_sound("animes")))
if(H.dna.species.id == "human")
if(H.dna.features["tail_human"] == "None" || H.dna.features["ears"] == "None")
@@ -469,7 +469,7 @@
if(is_station_level(W.z) && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison))
W.req_access = list()
message_admins("[key_name_admin(usr)] activated Egalitarian Station mode")
- priority_announce("CentCom airlock control override activated. Please take this time to get acquainted with your coworkers.", null, 'sound/ai/commandreport.ogg')
+ priority_announce("CentCom airlock control override activated. Please take this time to get acquainted with your coworkers.", null, "commandreport")
if("ak47s")
if(!check_rights(R_FUN))
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index 4e58a9cba5..ce4b8f7e39 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -318,6 +318,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
RemoveActive()
state = AHELP_CLOSED
GLOB.ahelp_tickets.ListInsert(src)
+ to_chat(initiator, "Ticket closed by [usr?.client?.holder?.fakekey? usr.client.holder.fakekey : "an administrator"].")
AddInteraction("Closed by [key_name].")
if(!silent)
SSblackbox.record_feedback("tally", "ahelp_stats", 1, "closed")
@@ -336,7 +337,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
addtimer(CALLBACK(initiator, /client/proc/giveadminhelpverb), 50)
AddInteraction("Resolved by [key_name].")
- to_chat(initiator, "Your ticket has been resolved by an admin. The Adminhelp verb will be returned to you shortly.")
+ to_chat(initiator, "Your ticket has been resolved by [usr?.client?.holder?.fakekey? usr.client.holder.fakekey : "an administrator"]. The Adminhelp verb will be returned to you shortly.")
if(!silent)
SSblackbox.record_feedback("tally", "ahelp_stats", 1, "resolved")
var/msg = "Ticket [TicketHref("#[id]")] resolved by [key_name]"
@@ -353,7 +354,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
SEND_SOUND(initiator, sound('sound/effects/adminhelp.ogg'))
- to_chat(initiator, "- AdminHelp Rejected! -")
+ to_chat(initiator, "- AdminHelp Rejected by [usr?.client?.holder?.fakekey? usr.client.holder.fakekey : "an administrator"]! -")
to_chat(initiator, "Your admin help was rejected. The adminhelp verb has been returned to you so that you may try again.")
to_chat(initiator, "Please try to be calm, clear, and descriptive in admin helps, do not assume the admin has seen any related events, and clearly state the names of anybody you are reporting.")
@@ -369,7 +370,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(state != AHELP_ACTIVE)
return
- var/msg = "- AdminHelp marked as IC issue! - "
+ var/msg = "- AdminHelp marked as IC issue by [usr?.client?.holder?.fakekey? usr.client.holder.fakekey : "an administrator"]! - "
msg += "Losing is part of the game! "
msg += "It is also possible that your ahelp is unable to be answered properly, due to events occurring in the round."
if(initiator)
diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm
index 5b74ae7c5b..e70ea1c1b3 100644
--- a/code/modules/admin/verbs/modifyvariables.dm
+++ b/code/modules/admin/verbs/modifyvariables.dm
@@ -534,7 +534,7 @@ GLOBAL_PROTECT(VVpixelmovement)
if (prompt != "Continue")
return FALSE
return TRUE
-
+
/client/proc/modify_variables(atom/O, param_var_name = null, autodetect_class = 0)
if(!check_rights(R_VAREDIT))
@@ -545,7 +545,7 @@ GLOBAL_PROTECT(VVpixelmovement)
var/var_value
if(param_var_name)
- if(!param_var_name in O.vars)
+ if(!(param_var_name in O.vars))
to_chat(src, "A variable with this name ([param_var_name]) doesn't exist in this datum ([O])")
return
variable = param_var_name
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 246ccb1d07..d7dd8db08d 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -560,7 +560,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/announce_command_report = TRUE
switch(confirm)
if("Yes")
- priority_announce(input, null, 'sound/ai/commandreport.ogg')
+ priority_announce(input, null, "commandreport")
announce_command_report = FALSE
if("Cancel")
return
diff --git a/code/modules/antagonists/_common/antag_datum.dm b/code/modules/antagonists/_common/antag_datum.dm
index 42719e28bd..1894d8c7ae 100644
--- a/code/modules/antagonists/_common/antag_datum.dm
+++ b/code/modules/antagonists/_common/antag_datum.dm
@@ -96,7 +96,6 @@ GLOBAL_LIST_EMPTY(antagonists)
LAZYREMOVE(owner.antag_datums, src)
if(!silent && owner.current)
farewell()
- owner.objectives -= objectives
var/datum/team/team = get_team()
if(team)
team.remove_member(owner)
@@ -132,14 +131,14 @@ GLOBAL_LIST_EMPTY(antagonists)
report += printplayer(owner)
var/objectives_complete = TRUE
- if(owner.objectives.len)
- report += printobjectives(owner)
- for(var/datum/objective/objective in owner.objectives)
+ if(objectives.len)
+ report += printobjectives(objectives)
+ for(var/datum/objective/objective in objectives)
if(!objective.check_completion())
objectives_complete = FALSE
break
- if(owner.objectives.len == 0 || objectives_complete)
+ if(objectives.len == 0 || objectives_complete)
report += "The [name] was successful!"
else
report += "The [name] has failed!"
@@ -216,25 +215,6 @@ GLOBAL_LIST_EMPTY(antagonists)
return
antag_memory = new_memo
-//This datum will autofill the name with special_role
-//Used as placeholder for minor antagonists, please create proper datums for these
-/datum/antagonist/auto_custom
- show_in_antagpanel = FALSE
- antagpanel_category = "Other"
- show_name_in_check_antagonists = TRUE
-
-/datum/antagonist/auto_custom/on_gain()
- ..()
- name = owner.special_role
- //Add all objectives not already owned by other datums to this one.
- var/list/already_registered_objectives = list()
- for(var/datum/antagonist/A in owner.antag_datums)
- if(A == src)
- continue
- else
- already_registered_objectives |= A.objectives
- objectives = owner.objectives - already_registered_objectives
-
//This one is created by admin tools for custom objectives
/datum/antagonist/custom
antagpanel_category = "Custom"
diff --git a/code/modules/antagonists/abductor/abductor.dm b/code/modules/antagonists/abductor/abductor.dm
index 0fca957ffe..e8d30e8dbe 100644
--- a/code/modules/antagonists/abductor/abductor.dm
+++ b/code/modules/antagonists/abductor/abductor.dm
@@ -26,7 +26,7 @@
sub_role = "Scientist"
outfit = /datum/outfit/abductor/scientist
landmark_type = /obj/effect/landmark/abductor/scientist
- greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve."
+ greet_text = "Use your experimental console and surgical equipment to monitor your agent and experiment upon abducted humans."
show_in_antagpanel = TRUE
/datum/antagonist/abductor/create_team(datum/team/abductor_team/new_team)
@@ -40,17 +40,18 @@
return team
/datum/antagonist/abductor/on_gain()
- owner.special_role = "[name] [sub_role]"
- owner.assigned_role = "[name] [sub_role]"
- owner.objectives += team.objectives
+ owner.special_role = "[name]"
+ owner.assigned_role = "[name]"
+ objectives += team.objectives
finalize_abductor()
+ ADD_TRAIT(owner, TRAIT_ABDUCTOR_TRAINING, ABDUCTOR_ANTAGONIST)
return ..()
/datum/antagonist/abductor/on_removal()
- owner.objectives -= team.objectives
if(owner.current)
to_chat(owner.current,"You are no longer the [owner.special_role]!")
owner.special_role = null
+ REMOVE_TRAIT(owner, TRAIT_ABDUCTOR_TRAINING, ABDUCTOR_ANTAGONIST)
return ..()
/datum/antagonist/abductor/greet()
@@ -64,6 +65,7 @@
//Equip
var/mob/living/carbon/human/H = owner.current
H.set_species(/datum/species/abductor)
+
H.real_name = "[team.name] [sub_role]"
H.equipOutfit(outfit)
@@ -75,11 +77,15 @@
update_abductor_icons_added(owner,"abductor")
-/datum/antagonist/abductor/scientist/finalize_abductor()
- ..()
- var/mob/living/carbon/human/H = owner.current
- var/datum/species/abductor/A = H.dna.species
- A.scientist = TRUE
+/datum/antagonist/abductor/scientist/on_gain()
+ ADD_TRAIT(owner, TRAIT_ABDUCTOR_SCIENTIST_TRAINING, ABDUCTOR_ANTAGONIST)
+ ADD_TRAIT(owner, TRAIT_SURGEON, ABDUCTOR_ANTAGONIST)
+ . = ..()
+
+/datum/antagonist/abductor/scientist/on_removal()
+ REMOVE_TRAIT(owner, TRAIT_ABDUCTOR_SCIENTIST_TRAINING, ABDUCTOR_ANTAGONIST)
+ REMOVE_TRAIT(owner, TRAIT_SURGEON, ABDUCTOR_ANTAGONIST)
+ . = ..()
/datum/antagonist/abductor/admin_add(datum/mind/new_owner,mob/admin)
var/list/current_teams = list()
@@ -93,8 +99,8 @@
else
return
new_owner.add_antag_datum(src)
- log_admin("[key_name(usr)] made [key_name(new_owner.current)] [name] on [choice]!")
- message_admins("[key_name_admin(usr)] made [key_name_admin(new_owner.current)] [name] on [choice] !")
+ log_admin("[key_name(usr)] made [key_name(new_owner)] [name] on [choice]!")
+ message_admins("[key_name_admin(usr)] made [key_name_admin(new_owner)] [name] on [choice] !")
/datum/antagonist/abductor/get_admin_commands()
. = ..()
@@ -147,7 +153,7 @@
result += "The abductors of [name] were:"
for(var/datum/mind/abductor_mind in members)
result += printplayer(abductor_mind)
- result += printobjectives(abductor_mind)
+ result += printobjectives(objectives)
return "
[result.Join(" ")]
"
@@ -172,7 +178,6 @@
var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random))
var/datum/objective/abductee/O = new objtype()
objectives += O
- owner.objectives += objectives
/datum/antagonist/abductee/apply_innate_effects(mob/living/mob_override)
update_abductor_icons_added(mob_override ? mob_override.mind : owner,"abductee")
@@ -214,4 +219,4 @@
/datum/antagonist/proc/update_abductor_icons_removed(datum/mind/alien_mind)
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_ABDUCTOR]
hud.leave_hud(alien_mind.current)
- set_antag_hud(alien_mind.current, null)
\ No newline at end of file
+ set_antag_hud(alien_mind.current, null)
diff --git a/code/modules/antagonists/abductor/equipment/abduction_gear.dm b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
index 1573204d88..c1088cbb3d 100644
--- a/code/modules/antagonists/abductor/equipment/abduction_gear.dm
+++ b/code/modules/antagonists/abductor/equipment/abduction_gear.dm
@@ -55,7 +55,7 @@
var/datum/action/A = X
A.UpdateButtonIcon()
-/obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user)
+/obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_WEAR_SUIT) //we only give the mob the ability to activate the vest if he's actually wearing it.
return 1
@@ -132,22 +132,26 @@
/obj/item/abductor
icon = 'icons/obj/abductor.dmi'
-/obj/item/abductor/proc/AbductorCheck(user)
- if(isabductor(user))
+/obj/item/abductor/proc/AbductorCheck(mob/user)
+ if(HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING))
+ return TRUE
+ if (istype(user) && user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
return TRUE
to_chat(user, "You can't figure how this works!")
return FALSE
-/obj/item/abductor/proc/ScientistCheck(user)
- if(!AbductorCheck(user))
- return FALSE
+/obj/item/abductor/proc/ScientistCheck(mob/user)
+ var/training = HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING) || (user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
+ var/sci_training = HAS_TRAIT(user, TRAIT_ABDUCTOR_SCIENTIST_TRAINING) || (user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_SCIENTIST_TRAINING))
- var/mob/living/carbon/human/H = user
- var/datum/species/abductor/S = H.dna.species
- if(S.scientist)
- return TRUE
- to_chat(user, "You're not trained to use this!")
- return FALSE
+ if(training && !sci_training)
+ to_chat(user, "You're not trained to use this!")
+ . = FALSE
+ else if(!training && !sci_training)
+ to_chat(user, "You can't figure how this works!")
+ . = FALSE
+ else
+ . = TRUE
/obj/item/abductor/gizmo
name = "science tool"
@@ -341,8 +345,8 @@
if(QDELETED(G))
return
- if(istype(C.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
- to_chat(user, "Your target seems to have some sort of protective headgear on, blocking the message from being sent!")
+ if(C.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ to_chat(user, "Your target seems to have some sort of tinfoil protection on, blocking the message from being sent!")
return
G.mind_control(command, user)
@@ -520,10 +524,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
/obj/item/abductor_baton/proc/SleepAttack(mob/living/L,mob/living/user)
if(L.incapacitated(TRUE, TRUE))
- if(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
- to_chat(user, "The specimen's protective headgear is interfering with the sleep inducement!")
- L.visible_message("[user] tried to induced sleep in [L] with [src], but [L.p_their()] headgear protected [L.p_them()]!", \
- "You feel a strange wave of heavy drowsiness wash over you, but your headgear deflects most of it!")
+ if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ to_chat(user, "The specimen's tinfoil protection is interfering with the sleep inducement!")
+ L.visible_message("[user] tried to induced sleep in [L] with [src], but [L.p_their()] tinfoil protected [L.p_them()]!", \
+ "You feel a strange wave of heavy drowsiness wash over you, but your tinfoil protection deflects most of it!")
L.drowsyness += 2
return
L.visible_message("[user] has induced sleep in [L] with [src]!", \
@@ -532,10 +536,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
L.Sleeping(1200)
log_combat(user, L, "put to sleep")
else
- if(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
- to_chat(user, "The specimen's protective headgear is completely blocking our sleep inducement methods!")
- L.visible_message("[user] tried to induce sleep in [L] with [src], but [L.p_their()] headgear completely protected [L.p_them()]!", \
- "Any sense of drowsiness is quickly diminished as your headgear deflects the effects!")
+ if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ to_chat(user, "The specimen's tinfoil protection is completely blocking our sleep inducement methods!")
+ L.visible_message("[user] tried to induce sleep in [L] with [src], but [L.p_their()] tinfoil completely protected [L.p_them()]!", \
+ "Any sense of drowsiness is quickly diminished as your tinfoil protection deflects the effects!")
return
L.drowsyness += 1
to_chat(user, "Sleep inducement works fully only on stunned specimens! ")
@@ -683,7 +687,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
desc = "Abduct with style - spiky style. Prevents digital tracking."
icon_state = "alienhelmet"
item_state = "alienhelmet"
- blockTracking = 1
+ blockTracking = TRUE
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
// Operating Table / Beds / Lockers
diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm
index 8e722ec33e..a35cbbf0e4 100644
--- a/code/modules/antagonists/abductor/equipment/gland.dm
+++ b/code/modules/antagonists/abductor/equipment/gland.dm
@@ -5,6 +5,7 @@
icon_state = "gland"
status = ORGAN_ROBOTIC
beating = TRUE
+ var/true_name = "baseline placebo referencer"
var/cooldown_low = 300
var/cooldown_high = 300
var/next_activation = 0
@@ -16,6 +17,11 @@
var/mind_control_duration = 1800
var/active_mind_control = FALSE
+/obj/item/organ/heart/gland/examine(mob/user)
+ . = ..()
+ if((user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_SCIENTIST_TRAINING)) || isobserver(user))
+ to_chat(user, "It is \a [true_name].")
+
/obj/item/organ/heart/gland/proc/ownerCheck()
if(ishuman(owner))
return TRUE
@@ -42,19 +48,19 @@
/obj/item/organ/heart/gland/proc/mind_control(command, mob/living/user)
if(!ownerCheck() || !mind_control_uses || active_mind_control)
- return
+ return FALSE
mind_control_uses--
to_chat(owner, "You suddenly feel an irresistible compulsion to follow an order...")
to_chat(owner, "[command]")
active_mind_control = TRUE
- log_admin("[key_name(user)] sent an abductor mind control message to [key_name(owner)]: [command]")
+ message_admins("[key_name(user)] sent an abductor mind control message to [key_name(owner)]: [command]")
update_gland_hud()
addtimer(CALLBACK(src, .proc/clear_mind_control), mind_control_duration)
/obj/item/organ/heart/gland/proc/clear_mind_control()
if(!ownerCheck() || !active_mind_control)
- return
+ return FALSE
to_chat(owner, "You feel the compulsion fade, and you completely forget about your previous orders.")
active_mind_control = FALSE
@@ -95,6 +101,7 @@
return
/obj/item/organ/heart/gland/heals
+ true_name = "coherency harmonizer"
cooldown_low = 200
cooldown_high = 400
uses = -1
@@ -109,6 +116,7 @@
owner.adjustOxyLoss(-20)
/obj/item/organ/heart/gland/slime
+ true_name = "gastric animation galvanizer"
cooldown_low = 600
cooldown_high = 1200
uses = -1
@@ -130,6 +138,7 @@
Slime.Leader = owner
/obj/item/organ/heart/gland/mindshock
+ true_name = "neural crosstalk uninhibitor"
cooldown_low = 400
cooldown_high = 700
uses = -1
@@ -156,6 +165,7 @@
H.hallucination += 60
/obj/item/organ/heart/gland/pop
+ true_name = "anthropmorphic translocator"
cooldown_low = 900
cooldown_high = 1800
uses = -1
@@ -171,6 +181,7 @@
owner.set_species(species)
/obj/item/organ/heart/gland/ventcrawling
+ true_name = "pliant cartilage enabler"
cooldown_low = 1800
cooldown_high = 2400
uses = 1
@@ -183,6 +194,7 @@
owner.ventcrawler = VENTCRAWLER_ALWAYS
/obj/item/organ/heart/gland/viral
+ true_name = "contamination incubator"
cooldown_low = 1800
cooldown_high = 2400
uses = 1
@@ -217,6 +229,7 @@
return A
/obj/item/organ/heart/gland/trauma
+ true_name = "white matter randomiser"
cooldown_low = 800
cooldown_high = 1200
uses = 5
@@ -235,6 +248,7 @@
owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
/obj/item/organ/heart/gland/spiderman
+ true_name = "araneae cloister accelerator"
cooldown_low = 450
cooldown_high = 900
uses = -1
@@ -249,6 +263,7 @@
S.directive = "Protect your nest inside [owner.real_name]."
/obj/item/organ/heart/gland/egg
+ true_name = "roe/enzymatic synthesizer"
cooldown_low = 300
cooldown_high = 400
uses = -1
@@ -264,6 +279,7 @@
new /obj/item/reagent_containers/food/snacks/egg/gland(T)
/obj/item/organ/heart/gland/electric
+ true_name = "electron accumulator/discharger"
cooldown_low = 800
cooldown_high = 1200
uses = -1
@@ -289,6 +305,7 @@
playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, 1)
/obj/item/organ/heart/gland/chem
+ true_name = "intrinsic pharma-provider"
cooldown_low = 50
cooldown_high = 50
uses = -1
@@ -315,6 +332,7 @@
..()
/obj/item/organ/heart/gland/plasma
+ true_name = "effluvium sanguine-synonym emitter"
cooldown_low = 1200
cooldown_high = 1800
uses = -1
diff --git a/code/modules/antagonists/abductor/machinery/camera.dm b/code/modules/antagonists/abductor/machinery/camera.dm
index 41cfa6a954..00e48cb1c7 100644
--- a/code/modules/antagonists/abductor/machinery/camera.dm
+++ b/code/modules/antagonists/abductor/machinery/camera.dm
@@ -55,8 +55,7 @@
actions += set_droppoint_action
/obj/machinery/computer/camera_advanced/abductor/proc/IsScientist(mob/living/carbon/human/H)
- var/datum/species/abductor/S = H.dna.species
- return S.scientist
+ return HAS_TRAIT(H, TRAIT_ABDUCTOR_SCIENTIST_TRAINING)
/datum/action/innate/teleport_in
name = "Send To"
diff --git a/code/modules/antagonists/abductor/machinery/console.dm b/code/modules/antagonists/abductor/machinery/console.dm
index 46d69ba9bb..bcf02bda01 100644
--- a/code/modules/antagonists/abductor/machinery/console.dm
+++ b/code/modules/antagonists/abductor/machinery/console.dm
@@ -28,7 +28,7 @@
. = ..()
if(.)
return
- if(!isabductor(user))
+ if(!HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING) && !HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
to_chat(user, "You start mashing alien buttons at random!")
if(do_after(user,100, target = src))
TeleporterSend()
@@ -178,8 +178,8 @@
c.console = src
/obj/machinery/abductor/console/proc/AddSnapshot(mob/living/carbon/human/target)
- if(istype(target.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
- say("Subject wearing specialized protective headgear, unable to get a proper scan!")
+ if(target.anti_magic_check(FALSE, FALSE, TRUE, 0))
+ say("Subject wearing specialized protective tinfoil gear, unable to get a proper scan!")
return
var/datum/icon_snapshot/entry = new
entry.name = target.name
diff --git a/code/modules/antagonists/abductor/machinery/pad.dm b/code/modules/antagonists/abductor/machinery/pad.dm
index 1cb95fbf05..ab636f7d0e 100644
--- a/code/modules/antagonists/abductor/machinery/pad.dm
+++ b/code/modules/antagonists/abductor/machinery/pad.dm
@@ -53,4 +53,4 @@
. = ..()
var/datum/effect_system/spark_spread/S = new
S.set_up(10,0,loc)
- S.start()
\ No newline at end of file
+ S.start()
diff --git a/code/modules/antagonists/blob/blob.dm b/code/modules/antagonists/blob/blob.dm
index 964bc99311..3d6db983dc 100644
--- a/code/modules/antagonists/blob/blob.dm
+++ b/code/modules/antagonists/blob/blob.dm
@@ -30,7 +30,6 @@
var/datum/objective/blob_takeover/main = new
main.owner = owner
objectives += main
- owner.objectives |= objectives
/datum/antagonist/blob/apply_innate_effects(mob/living/mob_override)
if(!isovermind(owner.current))
diff --git a/code/modules/antagonists/blob/blob/blobs/core.dm b/code/modules/antagonists/blob/blob/blobs/core.dm
index 81792ca4f6..58f79e1c73 100644
--- a/code/modules/antagonists/blob/blob/blobs/core.dm
+++ b/code/modules/antagonists/blob/blob/blobs/core.dm
@@ -27,7 +27,7 @@
. = ..()
/obj/structure/blob/core/proc/generate_announcement()
- priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak5.ogg')
+ priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", "outbreak5")
/obj/structure/blob/core/scannerreport()
return "Directs the blob's expansion, gradually expands, and sustains nearby blob spores and blobbernauts."
diff --git a/code/modules/antagonists/blood_contract/blood_contract.dm b/code/modules/antagonists/blood_contract/blood_contract.dm
new file mode 100644
index 0000000000..4e7238647e
--- /dev/null
+++ b/code/modules/antagonists/blood_contract/blood_contract.dm
@@ -0,0 +1,33 @@
+
+/datum/antagonist/blood_contract
+ name = "Blood Contract Target"
+ show_in_roundend = FALSE
+ show_in_antagpanel = FALSE
+
+/datum/antagonist/blood_contract/on_gain()
+ . = ..()
+ give_objective()
+ start_the_hunt()
+
+/datum/antagonist/blood_contract/proc/give_objective()
+ var/datum/objective/survive/survive = new
+ survive.owner = owner
+ objectives += survive
+
+/datum/antagonist/blood_contract/greet()
+ . = ..()
+ to_chat(owner, "You've been marked for death! Don't let the demons get you! KILL THEM ALL!")
+
+/datum/antagonist/blood_contract/proc/start_the_hunt()
+ var/mob/living/carbon/human/H = owner.current
+ if(!istype(H))
+ return
+ H.add_atom_colour("#FF0000", ADMIN_COLOUR_PRIORITY)
+ var/obj/effect/mine/pickup/bloodbath/B = new(H)
+ INVOKE_ASYNC(B, /obj/effect/mine/pickup/bloodbath/.proc/mineEffect, H) //could use moving out from the mine
+
+ for(var/mob/living/carbon/human/P in GLOB.player_list)
+ if(P == H)
+ continue
+ to_chat(P, "You have an overwhelming desire to kill [H]. [H.p_theyve(TRUE)] been marked red! Whoever [H.p_they()] [H.p_were()], friend or foe, go kill [H.p_them()]!")
+ P.put_in_hands(new /obj/item/kitchen/knife/butcher(P), TRUE)
diff --git a/code/modules/antagonists/brainwashing/brainwashing.dm b/code/modules/antagonists/brainwashing/brainwashing.dm
index f1cff2bff4..491ee9d2e5 100644
--- a/code/modules/antagonists/brainwashing/brainwashing.dm
+++ b/code/modules/antagonists/brainwashing/brainwashing.dm
@@ -9,7 +9,6 @@
for(var/O in directives)
var/datum/objective/brainwashing/objective = new(O)
B.objectives += objective
- M.objectives += objective
B.greet()
else
B = new()
@@ -32,10 +31,6 @@
antagpanel_category = "Other"
show_name_in_check_antagonists = TRUE
-/datum/antagonist/brainwashed/on_gain()
- owner.objectives |= objectives
- . = ..()
-
/datum/antagonist/brainwashed/greet()
to_chat(owner, "Your mind reels as it begins focusing on a single purpose...")
to_chat(owner, "Follow the Directives, at any cost!")
diff --git a/code/modules/antagonists/brother/brother.dm b/code/modules/antagonists/brother/brother.dm
index f63e81acbf..7c589bb3ab 100644
--- a/code/modules/antagonists/brother/brother.dm
+++ b/code/modules/antagonists/brother/brother.dm
@@ -20,7 +20,6 @@
/datum/antagonist/brother/on_gain()
SSticker.mode.brothers += owner
objectives += team.objectives
- owner.objectives += objectives
owner.special_role = special_role
finalize_brother()
return ..()
diff --git a/code/modules/antagonists/changeling/changeling.dm b/code/modules/antagonists/changeling/changeling.dm
index b6e3d66c35..0d68660d9d 100644
--- a/code/modules/antagonists/changeling/changeling.dm
+++ b/code/modules/antagonists/changeling/changeling.dm
@@ -459,8 +459,6 @@
objectives += identity_theft
escape_objective_possible = FALSE
- owner.objectives |= objectives
-
/datum/antagonist/changeling/proc/update_changeling_icons_added()
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_CHANGELING]
hud.join_hud(owner.current)
diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm
index c428c56d45..92a4f28308 100644
--- a/code/modules/antagonists/changeling/powers/mutations.dm
+++ b/code/modules/antagonists/changeling/powers/mutations.dm
@@ -334,7 +334,7 @@
/obj/item/projectile/tentacle/proc/tentacle_stab(mob/living/carbon/human/H, mob/living/carbon/C)
if(H.Adjacent(C))
for(var/obj/item/I in H.held_items)
- if(I.is_sharp())
+ if(I.get_sharpness())
C.visible_message("[H] impales [C] with [H.p_their()] [I.name]!", "[H] impales you with [H.p_their()] [I.name]!")
C.apply_damage(I.force, BRUTE, BODY_ZONE_CHEST)
H.do_item_attack_animation(C, used_item = I)
diff --git a/code/modules/antagonists/changeling/powers/strained_muscles.dm b/code/modules/antagonists/changeling/powers/strained_muscles.dm
index 081b1181dc..1f25e06324 100644
--- a/code/modules/antagonists/changeling/powers/strained_muscles.dm
+++ b/code/modules/antagonists/changeling/powers/strained_muscles.dm
@@ -21,7 +21,7 @@
to_chat(user, "Our muscles tense and strengthen.")
changeling.chem_recharge_slowdown += 0.5
else
- REMOVE_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
+ user.remove_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES)
to_chat(user, "Our muscles relax.")
changeling.chem_recharge_slowdown -= 0.5
if(stacks >= 20)
@@ -36,12 +36,12 @@
/obj/effect/proc_holder/changeling/strained_muscles/proc/muscle_loop(mob/living/carbon/user)
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
while(active)
- ADD_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
+ user.add_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
if(user.stat != CONSCIOUS || user.staminaloss >= 90)
active = !active
to_chat(user, "Our muscles relax without the energy to strengthen them.")
user.Knockdown(40)
- REMOVE_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
+ user.remove_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES)
changeling.chem_recharge_slowdown -= 0.5
break
diff --git a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
index 2018067b77..8000be87e6 100644
--- a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
+++ b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm
@@ -366,6 +366,8 @@
break
if(!GLOB.ratvar_awakens)
+ if(GLOB.clockwork_vitality <= 0)
+ break
GLOB.clockwork_vitality -= vitality_used
sleep(2)
diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
index 3ad6684725..07b4366194 100644
--- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
+++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm
@@ -35,7 +35,7 @@
/obj/item/clockwork/weapon/ratvarian_spear/attack(mob/living/target, mob/living/carbon/human/user)
. = ..()
- if(!QDELETED(target) && target.stat != DEAD && !target.anti_magic_check() && !is_servant_of_ratvar(target)) //we do bonus damage on attacks unless they're a servant, have a null rod, or are dead
+ if(!QDELETED(target) && target.stat != DEAD && !target.anti_magic_check(chargecost = 0) && !is_servant_of_ratvar(target)) //we do bonus damage on attacks unless they're a servant, have a null rod, or are dead
var/bonus_damage = bonus_burn //normally a total of 20 damage, 30 with ratvar
if(issilicon(target))
target.visible_message("[target] shudders violently at [src]'s touch!", "ERROR: Temperature rising!")
diff --git a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm b/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
index f44f67e9cb..644d9eedd5 100644
--- a/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
+++ b/code/modules/antagonists/clockcult/clock_items/judicial_visor.dm
@@ -27,7 +27,7 @@
qdel(blaster)
return ..()
-/obj/item/clothing/glasses/judicial_visor/item_action_slot_check(slot, mob/user)
+/obj/item/clothing/glasses/judicial_visor/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot != SLOT_GLASSES)
return 0
return ..()
@@ -190,8 +190,8 @@
for(var/mob/living/L in range(1, src))
if(is_servant_of_ratvar(L))
continue
- if(L.anti_magic_check())
- var/atom/I = L.anti_magic_check()
+ var/atom/I = L.anti_magic_check()
+ if(I)
if(isitem(I))
L.visible_message("Strange energy flows into [L]'s [I.name]!", \
"Your [I.name] shields you from [src]!")
diff --git a/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm b/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm
index da499065d7..3d467350ff 100644
--- a/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm
+++ b/code/modules/antagonists/clockcult/clock_scriptures/scripture_applications.dm
@@ -119,3 +119,33 @@
var/datum/clockwork_scripture/create_object/construct/clockwork_marauder/CM = new()
CM.recent_marauders--
qdel(CM)
+
+//Summon Neovgre: Summon a very powerful combat mech that explodes when destroyed for massive damage.
+/datum/clockwork_scripture/create_object/summon_arbiter
+ descname = "Powerful Assault Mech"
+ name = "Summon Neovgre, the Anima Bulwark"
+ desc = "Calls forth the mighty Anima Bulwark, a weapon of unmatched power,\
+ mech with superior defensive and offensive capabilities. It will \
+ steadily regenerate HP and triple its regeneration speed while standing \
+ on a clockwork tile. It will automatically draw power from nearby sigils of \
+ transmission should the need arise. Its Arbiter laser cannon can decimate foes \
+ from a range and is capable of smashing through any barrier presented to it. \
+ Be warned, choosing to pilot Neovgre is a lifetime commitment, once you are \
+ in you cannot leave and when it is destroyed it will explode catastrophically with you inside."
+ invocations = list("By the strength of the alloy...!!", "...call forth the Arbiter!!")
+ channel_time = 200 // This is a strong fucking weapon, 20 seconds channel time is getting off light I tell ya.
+ power_cost = 75000 //75 KW
+ usage_tip = "Neovgre is a powerful mech that will crush your enemies!"
+ invokers_required = 5
+ multiple_invokers_used = TRUE
+ object_path = /obj/mecha/combat/neovgre
+ tier = SCRIPTURE_APPLICATION
+ primary_component = BELLIGERENT_EYE
+ sort_priority = 2
+ creator_message = "Neovgre, the Anima Bulwark towers over you... your enemies reckoning has come."
+
+/datum/clockwork_scripture/create_object/summon_arbiter/check_special_requirements()
+ if(GLOB.neovgre_exists)
+ to_chat(invoker, "\"You've already got one...\"")
+ return FALSE
+ return ..()
diff --git a/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm b/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm
index 7654c0203b..3a461b7745 100644
--- a/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/heralds_beacon.dm
@@ -78,7 +78,7 @@
return
voters += user.key
else
- if(!user.key in voters)
+ if(!(user.key in voters))
return
voters -= user.key
var/votes_left = votes_needed - voters.len
diff --git a/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm b/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
index df0083e845..7afd9e7dbc 100644
--- a/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/ocular_warden.dm
@@ -60,7 +60,7 @@
else
if(isliving(target))
var/mob/living/L = target
- if(!L.anti_magic_check())
+ if(!L.anti_magic_check(chargecost = 0))
if(isrevenant(L))
var/mob/living/simple_animal/revenant/R = L
if(R.revealed)
diff --git a/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm b/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
index 10c68b606f..1158b02a4c 100644
--- a/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/taunting_trail.dm
@@ -53,7 +53,7 @@
/obj/structure/destructible/clockwork/taunting_trail/proc/affect_mob(mob/living/L)
if(istype(L) && !is_servant_of_ratvar(L))
- if(!L.anti_magic_check())
+ if(!L.anti_magic_check(chargecost = 0))
L.confused = min(L.confused + 15, 50)
L.dizziness = min(L.dizziness + 15, 50)
if(L.confused >= 25)
diff --git a/code/modules/antagonists/clockcult/clock_structures/traps/steam_vent.dm b/code/modules/antagonists/clockcult/clock_structures/traps/steam_vent.dm
index 8d65574987..6aede1592e 100644
--- a/code/modules/antagonists/clockcult/clock_structures/traps/steam_vent.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/traps/steam_vent.dm
@@ -7,7 +7,6 @@
break_message = "The vent snaps and collapses!"
max_integrity = 100
density = FALSE
- layer = BELOW_OBJ_LAYER
/obj/structure/destructible/clockwork/trap/steam_vent/activate()
opacity = !opacity
diff --git a/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm b/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm
index fb8397eed7..32b1b61dd1 100644
--- a/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm
+++ b/code/modules/antagonists/clockcult/clock_structures/wall_gear.dm
@@ -5,7 +5,6 @@
unanchored_icon = "wall_gear"
climbable = TRUE
max_integrity = 100
- layer = BELOW_OBJ_LAYER
construction_value = 3
desc = "A massive brass gear. You could probably secure or unsecure it with a wrench, or just climb over it."
break_message = "The gear breaks apart into shards of alloy!"
diff --git a/code/modules/antagonists/cult/cult.dm b/code/modules/antagonists/cult/cult.dm
index 47cf2abf3f..9989058d43 100644
--- a/code/modules/antagonists/cult/cult.dm
+++ b/code/modules/antagonists/cult/cult.dm
@@ -35,7 +35,6 @@
/datum/antagonist/cult/proc/add_objectives()
objectives |= cult_team.objectives
- owner.objectives |= objectives
/datum/antagonist/cult/Destroy()
QDEL_NULL(communion)
diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index 10759afcd0..06ea2cbe0a 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -275,7 +275,7 @@
desc = "A torn, dust-caked hood. Strange letters line the inside."
flags_inv = HIDEFACE|HIDEHAIR|HIDEEARS
flags_cover = HEADCOVERSEYES
- armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
+ armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 65, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
cold_protection = HEAD
min_cold_protection_temperature = HELMET_MIN_TEMP_PROTECT
heat_protection = HEAD
@@ -288,7 +288,7 @@
item_state = "cultrobes"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
allowed = list(/obj/item/tome, /obj/item/melee/cultblade)
- armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
+ armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 65, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
flags_inv = HIDEJUMPSUIT
cold_protection = CHEST|GROIN|LEGS|ARMS
min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT
diff --git a/code/modules/antagonists/cult/ritual.dm b/code/modules/antagonists/cult/ritual.dm
index 69941f582d..b9e4da8677 100644
--- a/code/modules/antagonists/cult/ritual.dm
+++ b/code/modules/antagonists/cult/ritual.dm
@@ -107,7 +107,7 @@ This file contains the cult dagger and rune list code
if(!(A in summon_objective.summon_spots)) // Check again to make sure they didn't move
to_chat(user, "The Geometer can only be summoned where the veil is weak - in [english_list(summon_objective.summon_spots)]!")
return
- priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", 'sound/ai/spanomalies.ogg')
+ priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", "spanomalies")
for(var/B in spiral_range_turfs(1, user, 1))
var/obj/structure/emergency_shield/sanguine/N = new(B)
shields += N
diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm
index 1eac059d36..e6ac9b5f73 100644
--- a/code/modules/antagonists/cult/runes.dm
+++ b/code/modules/antagonists/cult/runes.dm
@@ -237,7 +237,7 @@ structure_check() searches for nearby cultist structures required for the invoca
to_chat(M, "You need at least two invokers to convert [convertee]!")
log_game("Offer rune failed - tried conversion with one invoker")
return 0
- if(convertee.anti_magic_check(TRUE, TRUE, FALSE, 0)) //Not chargecost because it can be spammed
+ if(convertee.anti_magic_check(TRUE, TRUE, chargecost = 0)) //Not major because it can be spammed
for(var/M in invokers)
to_chat(M, "Something is shielding [convertee]'s mind!")
log_game("Offer rune failed - convertee had anti-magic")
@@ -767,7 +767,7 @@ structure_check() searches for nearby cultist structures required for the invoca
set_light(6, 1, color)
for(var/mob/living/L in viewers(T))
if(!iscultist(L) && L.blood_volume)
- var/atom/I = L.anti_magic_check()
+ var/atom/I = L.anti_magic_check(chargecost = 0)
if(I)
if(isitem(I))
to_chat(L, "[I] suddenly burns hotly before returning to normal!")
@@ -797,7 +797,7 @@ structure_check() searches for nearby cultist structures required for the invoca
set_light(6, 1, color)
for(var/mob/living/L in viewers(T))
if(!iscultist(L) && L.blood_volume)
- if(L.anti_magic_check())
+ if(L.anti_magic_check(chargecost = 0))
continue
L.take_overall_damage(tick_damage*multiplier, tick_damage*multiplier)
if(is_servant_of_ratvar(L))
diff --git a/code/modules/antagonists/devil/devil.dm b/code/modules/antagonists/devil/devil.dm
index dc649025d2..2e38734b6f 100644
--- a/code/modules/antagonists/devil/devil.dm
+++ b/code/modules/antagonists/devil/devil.dm
@@ -549,7 +549,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
var/list/parts = list()
parts += printplayer(owner)
parts += printdevilinfo()
- parts += printobjectives(owner)
+ parts += printobjectives(objectives)
return parts.Join(" ")
//A simple super light weight datum for the codex gigas.
diff --git a/code/modules/antagonists/devil/imp/imp.dm b/code/modules/antagonists/devil/imp/imp.dm
index da51a5d698..fa5263059a 100644
--- a/code/modules/antagonists/devil/imp/imp.dm
+++ b/code/modules/antagonists/devil/imp/imp.dm
@@ -57,3 +57,18 @@
visible_message("[src] screams in agony as it sublimates into a sulfurous smoke.")
ghostize()
qdel(src)
+
+/datum/antagonist/imp
+ name = "Imp"
+ antagpanel_category = "Devil"
+ show_in_roundend = FALSE
+
+/datum/antagonist/imp/on_gain()
+ . = ..()
+ give_objectives()
+
+/datum/antagonist/imp/proc/give_objectives()
+ var/datum/objective/newobjective = new
+ newobjective.explanation_text = "Try to get a promotion to a higher devilic rank."
+ newobjective.owner = owner
+ objectives += newobjective
\ No newline at end of file
diff --git a/code/modules/antagonists/devil/true_devil/_true_devil.dm b/code/modules/antagonists/devil/true_devil/_true_devil.dm
index afe439f02c..df761ac183 100644
--- a/code/modules/antagonists/devil/true_devil/_true_devil.dm
+++ b/code/modules/antagonists/devil/true_devil/_true_devil.dm
@@ -147,13 +147,8 @@
if(ascended || user.mind.soulOwner == src.mind)
var/mob/living/simple_animal/imp/S = new(get_turf(loc))
user.transfer_ckey(S, FALSE)
- S.mind.assigned_role = "Imp"
- S.mind.special_role = "Imp"
- var/datum/objective/newobjective = new
- newobjective.explanation_text = "Try to get a promotion to a higher devilic rank."
- S.mind.objectives += newobjective
- to_chat(S, S.playstyle_string)
- to_chat(S, "Objective #[1]: [newobjective.explanation_text]")
+ var/datum/antagonist/imp/A = new()
+ S.mind.add_antag_datum(A)
else
return ..()
diff --git a/code/modules/antagonists/disease/disease_datum.dm b/code/modules/antagonists/disease/disease_datum.dm
index eb0feac0a2..1aef9ceba6 100644
--- a/code/modules/antagonists/disease/disease_datum.dm
+++ b/code/modules/antagonists/disease/disease_datum.dm
@@ -10,12 +10,10 @@
var/datum/objective/O = new /datum/objective/disease_infect()
O.owner = owner
objectives += O
- owner.objectives += O
O = new /datum/objective/disease_infect_centcom()
O.owner = owner
objectives += O
- owner.objectives += O
. = ..()
diff --git a/code/modules/antagonists/disease/disease_mob.dm b/code/modules/antagonists/disease/disease_mob.dm
index 49c34131fc..faea113ac5 100644
--- a/code/modules/antagonists/disease/disease_mob.dm
+++ b/code/modules/antagonists/disease/disease_mob.dm
@@ -31,7 +31,6 @@ the new instance inside the host to be updated to the template's stats.
var/browser_open = FALSE
var/mob/living/following_host
- var/datum/component/redirect/move_listener
var/list/disease_instances
var/list/hosts //this list is associative, affected_mob -> disease_instance
var/datum/disease/advance/sentient_disease/disease_template
@@ -261,16 +260,10 @@ the new instance inside the host to be updated to the template's stats.
refresh_adaptation_menu()
/mob/camera/disease/proc/set_following(mob/living/L)
+ if(following_host)
+ UnregisterSignal(following_host, COMSIG_MOVABLE_MOVED)
+ RegisterSignal(L, COMSIG_MOVABLE_MOVED, .proc/follow_mob)
following_host = L
- if(!move_listener)
- move_listener = L.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/follow_mob)))
- else
- if(L)
- L.TakeComponent(move_listener)
- if(QDELING(move_listener))
- move_listener = null
- else
- QDEL_NULL(move_listener)
follow_mob()
/mob/camera/disease/proc/follow_next(reverse = FALSE)
diff --git a/code/modules/antagonists/ert/ert.dm b/code/modules/antagonists/ert/ert.dm
index bb24af4f7a..5968c7643a 100644
--- a/code/modules/antagonists/ert/ert.dm
+++ b/code/modules/antagonists/ert/ert.dm
@@ -113,7 +113,6 @@
/datum/antagonist/ert/proc/forge_objectives()
if(ert_team)
objectives |= ert_team.objectives
- owner.objectives |= objectives
/datum/antagonist/ert/proc/equipERT()
var/mob/living/carbon/human/H = owner.current
diff --git a/code/modules/antagonists/greentext/greentext.dm b/code/modules/antagonists/greentext/greentext.dm
index ffaab71aca..13a3c2a07a 100644
--- a/code/modules/antagonists/greentext/greentext.dm
+++ b/code/modules/antagonists/greentext/greentext.dm
@@ -8,7 +8,6 @@
O.completed = TRUE //YES!
O.owner = owner
objectives += O
- owner.objectives += objectives
/datum/antagonist/greentext/on_gain()
forge_objectives()
diff --git a/code/modules/antagonists/highlander/highlander.dm b/code/modules/antagonists/highlander/highlander.dm
index 51e8d9a13b..49635356ac 100644
--- a/code/modules/antagonists/highlander/highlander.dm
+++ b/code/modules/antagonists/highlander/highlander.dm
@@ -24,8 +24,6 @@
hijack_objective.owner = owner
objectives += hijack_objective
- owner.objectives |= objectives
-
/datum/antagonist/highlander/on_gain()
forge_objectives()
owner.special_role = "highlander"
diff --git a/code/modules/antagonists/magic_servant/magic_servant.dm b/code/modules/antagonists/magic_servant/magic_servant.dm
new file mode 100644
index 0000000000..31b51f59f6
--- /dev/null
+++ b/code/modules/antagonists/magic_servant/magic_servant.dm
@@ -0,0 +1,9 @@
+/datum/antagonist/magic_servant
+ name = "Magic Servant"
+ show_in_roundend = FALSE
+ show_in_antagpanel = FALSE
+
+/datum/antagonist/magic_servant/proc/setup_master(mob/M)
+ var/datum/objective/O = new("Serve [M.real_name].")
+ O.owner = owner
+ objectives |= O
\ No newline at end of file
diff --git a/code/modules/antagonists/monkey/monkey.dm b/code/modules/antagonists/monkey/monkey.dm
index 9ce28eb60d..e480eb8674 100644
--- a/code/modules/antagonists/monkey/monkey.dm
+++ b/code/modules/antagonists/monkey/monkey.dm
@@ -63,7 +63,6 @@
/datum/antagonist/monkey/proc/forge_objectives()
objectives |= monkey_team.objectives
- owner.objectives |= objectives
/datum/antagonist/monkey/admin_remove(mob/admin)
var/mob/living/carbon/monkey/M = owner.current
diff --git a/code/modules/antagonists/ninja/ninja.dm b/code/modules/antagonists/ninja/ninja.dm
index a8bce90f1c..52e13bdc69 100644
--- a/code/modules/antagonists/ninja/ninja.dm
+++ b/code/modules/antagonists/ninja/ninja.dm
@@ -96,7 +96,6 @@
var/datum/objective/O = new /datum/objective/survive()
O.owner = owner
objectives += O
- owner.objectives |= objectives
/proc/remove_ninja(mob/living/L)
if(!L || !L.mind)
diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm
index 800448c02f..4604439fc8 100644
--- a/code/modules/antagonists/nukeop/nukeop.dm
+++ b/code/modules/antagonists/nukeop/nukeop.dm
@@ -87,7 +87,7 @@
/datum/antagonist/nukeop/proc/forge_objectives()
if(nuke_team)
- owner.objectives |= nuke_team.objectives
+ objectives |= nuke_team.objectives
/datum/antagonist/nukeop/proc/move_to_spawnpoint()
var/team_number = 1
diff --git a/code/modules/antagonists/official/official.dm b/code/modules/antagonists/official/official.dm
index 26de196cb4..9165a99d42 100644
--- a/code/modules/antagonists/official/official.dm
+++ b/code/modules/antagonists/official/official.dm
@@ -36,8 +36,6 @@
missionobj.completed = 1
mission = missionobj
objectives |= mission
- owner.objectives |= objectives
-
/datum/antagonist/official/on_gain()
forge_objectives()
diff --git a/code/modules/antagonists/overthrow/overthrow.dm b/code/modules/antagonists/overthrow/overthrow.dm
index 075b9f13bc..c8b253793e 100644
--- a/code/modules/antagonists/overthrow/overthrow.dm
+++ b/code/modules/antagonists/overthrow/overthrow.dm
@@ -26,7 +26,6 @@
// Sets objectives, equips all antags with the storage implant.
/datum/antagonist/overthrow/on_gain()
objectives += team.objectives
- owner.objectives += objectives
..()
owner.announce_objectives()
equip_overthrow()
@@ -34,7 +33,6 @@
/datum/antagonist/overthrow/on_removal()
owner.special_role = null
- owner.objectives -= objectives
..()
// Creates the overthrow team, or sets it. The objectives are static for all the team members.
diff --git a/code/modules/antagonists/overthrow/overthrow_team.dm b/code/modules/antagonists/overthrow/overthrow_team.dm
index 7f5d010013..a22f08d45c 100644
--- a/code/modules/antagonists/overthrow/overthrow_team.dm
+++ b/code/modules/antagonists/overthrow/overthrow_team.dm
@@ -35,7 +35,9 @@
objectives += heads_obj
for(var/i in members)
var/datum/mind/M = i
- M.objectives += heads_obj
+ var/datum/antagonist/overthrow/O = M.has_antag_datum(/datum/antagonist/overthrow)
+ if(O)
+ O.objectives += heads_obj
heads_obj.find_targets()
addtimer(CALLBACK(src,.proc/update_objectives),OBJECTIVE_UPDATING_TIME,TIMER_UNIQUE)
diff --git a/code/modules/antagonists/pirate/pirate.dm b/code/modules/antagonists/pirate/pirate.dm
index 96830562e9..ff33477909 100644
--- a/code/modules/antagonists/pirate/pirate.dm
+++ b/code/modules/antagonists/pirate/pirate.dm
@@ -31,12 +31,7 @@
/datum/antagonist/pirate/on_gain()
if(crew)
- owner.objectives |= crew.objectives
- . = ..()
-
-/datum/antagonist/pirate/on_removal()
- if(crew)
- owner.objectives -= crew.objectives
+ objectives |= crew.objectives
. = ..()
/datum/team/pirate
@@ -53,7 +48,9 @@
getbooty.update_explanation_text()
objectives += getbooty
for(var/datum/mind/M in members)
- M.objectives |= objectives
+ var/datum/antagonist/pirate/P = M.has_antag_datum(/datum/antagonist/pirate)
+ if(P)
+ P.objectives |= objectives
/datum/objective/loot
diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm
index f380fa68e9..b43024fb31 100644
--- a/code/modules/antagonists/revenant/revenant.dm
+++ b/code/modules/antagonists/revenant/revenant.dm
@@ -69,7 +69,7 @@
/mob/living/simple_animal/revenant/Initialize(mapload)
. = ..()
AddSpell(new /obj/effect/proc_holder/spell/targeted/night_vision/revenant(null))
- AddSpell(new /obj/effect/proc_holder/spell/targeted/revenant_transmit(null))
+ AddSpell(new /obj/effect/proc_holder/spell/targeted/telepathy/revenant(null))
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/defile(null))
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/overload(null))
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/blight(null))
diff --git a/code/modules/antagonists/revenant/revenant_abilities.dm b/code/modules/antagonists/revenant/revenant_abilities.dm
index 112a31f44d..17d200a685 100644
--- a/code/modules/antagonists/revenant/revenant_abilities.dm
+++ b/code/modules/antagonists/revenant/revenant_abilities.dm
@@ -27,6 +27,7 @@
if(prob(10))
to_chat(target, "You feel as if you are being watched.")
return
+ face_atom(target)
draining = TRUE
essence_drained += rand(15, 20)
to_chat(src, "You search for the soul of [target].")
@@ -65,7 +66,7 @@
if(target.anti_magic_check(FALSE, TRUE))
to_chat(src, "Something's wrong! [target] seems to be resisting the siphoning, leaving you vulnerable!")
target.visible_message("[target] slumps onto the ground.", \
- "Violets lights, dancing in your vision, receding--")
+ "Violet lights, dancing in your vision, receding--")
draining = FALSE
return
var/datum/beam/B = Beam(target,icon_state="drain_life",time=INFINITY)
@@ -104,36 +105,16 @@
action_background_icon_state = "bg_revenant"
//Transmit: the revemant's only direct way to communicate. Sends a single message silently to a single mob
-/obj/effect/proc_holder/spell/targeted/revenant_transmit
- name = "Transmit"
- desc = "Telepathically transmits a message to the target."
+/obj/effect/proc_holder/spell/targeted/telepathy/revenant
+ name = "Revenant Transmit"
panel = "Revenant Abilities"
- charge_max = 0
- clothes_req = 0
- range = 7
- include_user = 0
action_icon = 'icons/mob/actions/actions_revenant.dmi'
action_icon_state = "r_transmit"
action_background_icon_state = "bg_revenant"
-
-/obj/effect/proc_holder/spell/targeted/revenant_transmit/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
- for(var/mob/living/M in targets)
- var/msg = stripped_input(usr, "What do you wish to tell [M]?", null, "")
- if(!msg)
- charge_counter = charge_max
- return
- log_directed_talk(user, M, msg, LOG_SAY, "revenant whisper")
- to_chat(user, "You transmit to [M]:[msg]")
- if(!M.anti_magic_check(FALSE, TRUE)) //hear no evil
- to_chat(M, "You hear something behind you talking...[msg]")
- for(var/ded in GLOB.dead_mob_list)
- if(!isobserver(ded))
- continue
- var/follow_rev = FOLLOW_LINK(ded, user)
- var/follow_whispee = FOLLOW_LINK(ded, M)
- to_chat(ded, "[follow_rev] [user] Revenant Transmit:\"[msg]\" to [follow_whispee] [M]")
-
-
+ notice = "revennotice"
+ boldnotice = "revenboldnotice"
+ holy_check = TRUE
+ tinfoil_check = FALSE
/obj/effect/proc_holder/spell/aoe_turf/revenant
clothes_req = 0
diff --git a/code/modules/antagonists/revenant/revenant_antag.dm b/code/modules/antagonists/revenant/revenant_antag.dm
index 476db96fb8..8d99edf26e 100644
--- a/code/modules/antagonists/revenant/revenant_antag.dm
+++ b/code/modules/antagonists/revenant/revenant_antag.dm
@@ -14,8 +14,6 @@
objective2.owner = owner
objectives += objective2
- owner.objectives |= objectives
-
/datum/antagonist/revenant/on_gain()
forge_objectives()
. = ..()
diff --git a/code/modules/antagonists/revenant/revenant_blight.dm b/code/modules/antagonists/revenant/revenant_blight.dm
index 89d8de283a..235e50008c 100644
--- a/code/modules/antagonists/revenant/revenant_blight.dm
+++ b/code/modules/antagonists/revenant/revenant_blight.dm
@@ -12,8 +12,8 @@
disease_flags = CURABLE
permeability_mod = 1
severity = DISEASE_SEVERITY_DANGEROUS
- var/finalstage = 0 //Because we're spawning off the cure in the final stage, we need to check if we've done the final stage's effects.
- var/datum/mood_event/revenant_blight/depression
+ var/finalstage = FALSE //Because we're spawning off the cure in the final stage, we need to check if we've done the final stage's effects.
+ var/depression = FALSE
/datum/disease/revblight/cure()
if(affected_mob)
@@ -44,12 +44,13 @@
affected_mob.emote("pale")
if(3)
if(!depression)
- depression = SEND_SIGNAL(affected_mob, COMSIG_ADD_MOOD_EVENT, "rev_blight", /datum/mood_event/revenant_blight)
- SEND_SIGNAL(affected_mob, COMSIG_DECREASE_SANITY, 0.12, SANITY_CRAZY)
+ SEND_SIGNAL(affected_mob, COMSIG_ADD_MOOD_EVENT, "rev_blight", /datum/mood_event/revenant_blight)
+ depression = TRUE
+ SEND_SIGNAL(affected_mob, COMSIG_MODIFY_SANITY, -0.12, SANITY_CRAZY)
if(prob(10))
affected_mob.emote(pick("pale","shiver"))
if(4)
- SEND_SIGNAL(affected_mob, COMSIG_DECREASE_SANITY, 0.18, SANITY_CRAZY)
+ SEND_SIGNAL(affected_mob, COMSIG_MODIFY_SANITY, -0.18, SANITY_CRAZY)
if(prob(15))
affected_mob.emote(pick("pale","shiver","cries"))
if(5)
diff --git a/code/modules/antagonists/revolution/revolution.dm b/code/modules/antagonists/revolution/revolution.dm
index e10d83ffb7..fef7061488 100644
--- a/code/modules/antagonists/revolution/revolution.dm
+++ b/code/modules/antagonists/revolution/revolution.dm
@@ -66,10 +66,10 @@
return rev_team
/datum/antagonist/rev/proc/create_objectives()
- owner.objectives |= rev_team.objectives
+ objectives |= rev_team.objectives
/datum/antagonist/rev/proc/remove_objectives()
- owner.objectives -= rev_team.objectives
+ objectives -= rev_team.objectives
//Bump up to head_rev
/datum/antagonist/rev/proc/promote()
@@ -265,7 +265,8 @@
new_target.update_explanation_text()
objectives += new_target
for(var/datum/mind/M in members)
- M.objectives |= objectives
+ var/datum/antagonist/rev/R = M.has_antag_datum(/datum/antagonist/rev)
+ R.objectives |= objectives
addtimer(CALLBACK(src,.proc/update_objectives),HEAD_UPDATE_PERIOD,TIMER_UNIQUE)
diff --git a/code/modules/antagonists/santa/santa.dm b/code/modules/antagonists/santa/santa.dm
new file mode 100644
index 0000000000..bf42188cf6
--- /dev/null
+++ b/code/modules/antagonists/santa/santa.dm
@@ -0,0 +1,29 @@
+/datum/antagonist/santa
+ name = "Santa"
+ show_in_antagpanel = FALSE
+
+/datum/antagonist/santa/on_gain()
+ . = ..()
+ give_equipment()
+ give_objective()
+
+/datum/antagonist/santa/greet()
+ . = ..()
+ to_chat(owner, "You are Santa! Your objective is to bring joy to the people on this station. You can conjure more presents using a spell, and there are several presents in your bag.")
+
+/datum/antagonist/santa/proc/give_equipment()
+ var/mob/living/carbon/human/H = owner.current
+ if(istype(H))
+ H.equipOutfit(/datum/outfit/santa)
+
+ owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/presents)
+ var/obj/effect/proc_holder/spell/targeted/area_teleport/teleport/telespell = new
+ telespell.clothes_req = 0 //santa robes aren't actually magical.
+ owner.AddSpell(telespell) //does the station have chimneys? WHO KNOWS!
+
+/datum/antagonist/santa/proc/give_objective()
+ var/datum/objective/santa_objective = new()
+ santa_objective.explanation_text = "Bring joy and presents to the station!"
+ santa_objective.completed = 1 //lets cut our santas some slack.
+ santa_objective.owner = owner
+ objectives |= santa_objective
\ No newline at end of file
diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm
index 03a176b054..f45555a6ee 100644
--- a/code/modules/antagonists/slaughter/slaughter.dm
+++ b/code/modules/antagonists/slaughter/slaughter.dm
@@ -34,7 +34,6 @@
melee_damage_upper = 30
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
- var/boost = 0
bloodcrawl = BLOODCRAWL_EAT
var/playstyle_string = "You are a slaughter demon, a terrible creature from another realm. You have a single desire: To kill. \
You may use the \"Blood Crawl\" ability near blood pools to travel through them, appearing and disappearing from the station at will. \
@@ -54,24 +53,18 @@
if(istype(loc, /obj/effect/dummy/phased_mob/slaughter))
bloodspell.phased = TRUE
-/mob/living/simple_animal/slaughter/Life()
- ..()
- if(boost Target eliminated: [victim.name]")
LAZYINITLIST(targets_stolen)
- for(var/objective_ in victim.objectives)
+ for(var/objective_ in victim.get_all_objectives())
if(istype(objective_, /datum/objective/assassinate/internal))
var/datum/objective/assassinate/internal/objective = objective_
if(objective.target==owner)
@@ -159,7 +158,7 @@
var/status_text = objective.check_completion() ? "neutralised" : "active"
to_chat(owner.current, " New target added to database: [objective.target.name] ([status_text]) ")
last_man_standing = TRUE
- for(var/objective_ in owner.objectives)
+ for(var/objective_ in objectives)
if(!is_internal_objective(objective_))
continue
var/datum/objective/assassinate/internal/objective = objective_
@@ -175,7 +174,7 @@
/datum/antagonist/traitor/internal_affairs/proc/iaa_process()
if(owner&&owner.current&&owner.current.stat!=DEAD)
- for(var/objective_ in owner.objectives)
+ for(var/objective_ in objectives)
if(!is_internal_objective(objective_))
continue
var/datum/objective/assassinate/internal/objective = objective_
diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm
index e43c2f6254..5dfc08b6cf 100644
--- a/code/modules/antagonists/traitor/datum_traitor.dm
+++ b/code/modules/antagonists/traitor/datum_traitor.dm
@@ -55,12 +55,10 @@
owner.special_role = null
..()
-/datum/antagonist/traitor/proc/add_objective(var/datum/objective/O)
- owner.objectives += O
+/datum/antagonist/traitor/proc/add_objective(datum/objective/O)
objectives += O
-/datum/antagonist/traitor/proc/remove_objective(var/datum/objective/O)
- owner.objectives -= O
+/datum/antagonist/traitor/proc/remove_objective(datum/objective/O)
objectives -= O
/datum/antagonist/traitor/proc/forge_traitor_objectives()
@@ -89,7 +87,7 @@
forge_single_objective()
if(is_hijacker && objective_count <= toa) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
- if (!(locate(/datum/objective/hijack) in owner.objectives))
+ if (!(locate(/datum/objective/hijack) in objectives))
var/datum/objective/hijack/hijack_objective = new
hijack_objective.owner = owner
add_objective(hijack_objective)
@@ -97,7 +95,7 @@
var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead.
- for(var/datum/objective/O in owner.objectives)
+ for(var/datum/objective/O in objectives)
if(!O.martyr_compatible)
martyr_compatibility = 0
break
@@ -109,7 +107,7 @@
return
else
- if(!(locate(/datum/objective/escape) in owner.objectives))
+ if(!(locate(/datum/objective/escape) in objectives))
var/datum/objective/escape/escape_objective = new
escape_objective.owner = owner
add_objective(escape_objective)
@@ -159,7 +157,7 @@
kill_objective.find_target()
add_objective(kill_objective)
else
- if(prob(15) && !(locate(/datum/objective/download) in owner.objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
+ if(prob(15) && !(locate(/datum/objective/download) in objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
var/datum/objective/download/download_objective = new
download_objective.owner = owner
download_objective.gen_amount_goal()
diff --git a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
index ff4f7276bc..e1d607c34b 100644
--- a/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
+++ b/code/modules/antagonists/traitor/equipment/Malf_Modules.dm
@@ -304,7 +304,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
sleep(30)
if(!owner || QDELETED(owner))
return
- priority_announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", 'sound/ai/aimalf.ogg')
+ priority_announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", "aimalf")
set_security_level("delta")
var/obj/machinery/doomsday_device/DOOM = new(owner_AI)
owner_AI.nuking = TRUE
diff --git a/code/modules/antagonists/valentines/heartbreaker.dm b/code/modules/antagonists/valentines/heartbreaker.dm
index 4f228910d7..b78e8d574f 100644
--- a/code/modules/antagonists/valentines/heartbreaker.dm
+++ b/code/modules/antagonists/valentines/heartbreaker.dm
@@ -9,7 +9,6 @@
var/datum/objective/martyr/normiesgetout = new
normiesgetout.owner = owner
objectives += normiesgetout
- owner.objectives += objectives
/datum/antagonist/heartbreaker/on_gain()
forge_objectives()
diff --git a/code/modules/antagonists/valentines/valentine.dm b/code/modules/antagonists/valentines/valentine.dm
index 21e54374a4..19c08f3076 100644
--- a/code/modules/antagonists/valentines/valentine.dm
+++ b/code/modules/antagonists/valentines/valentine.dm
@@ -12,7 +12,6 @@
protect_objective.human_check = FALSE
protect_objective.explanation_text = "Protect [date.name], your date."
objectives += protect_objective
- owner.objectives += objectives
/datum/antagonist/valentine/on_gain()
forge_objectives()
@@ -34,8 +33,8 @@
//Squashed up a bit
/datum/antagonist/valentine/roundend_report()
var/objectives_complete = TRUE
- if(owner.objectives.len)
- for(var/datum/objective/objective in owner.objectives)
+ if(objectives.len)
+ for(var/datum/objective/objective in objectives)
if(!objective.check_completion())
objectives_complete = FALSE
break
@@ -51,8 +50,8 @@
/datum/antagonist/valentine/chem/roundend_report()
var/objectives_complete = TRUE
- if(owner.objectives.len)
- for(var/datum/objective/objective in owner.objectives)
+ if(objectives.len)
+ for(var/datum/objective/objective in objectives)
if(!objective.check_completion())
objectives_complete = FALSE
break
diff --git a/code/modules/antagonists/wishgranter/wishgranter.dm b/code/modules/antagonists/wishgranter/wishgranter.dm
index 318de51eb4..21cab26d1e 100644
--- a/code/modules/antagonists/wishgranter/wishgranter.dm
+++ b/code/modules/antagonists/wishgranter/wishgranter.dm
@@ -8,7 +8,6 @@
var/datum/objective/hijack/hijack = new
hijack.owner = owner
objectives += hijack
- owner.objectives |= objectives
/datum/antagonist/wishgranter/on_gain()
owner.special_role = "Avatar of the Wish Granter"
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index 57488a6722..38aa0ad7f5 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -113,7 +113,7 @@
/obj/singularity/wizard/attack_tk(mob/user)
if(iscarbon(user))
var/mob/living/carbon/C = user
- GET_COMPONENT_FROM(insaneinthemembrane, /datum/component/mood, C)
+ var/datum/component/mood/insaneinthemembrane = C.GetComponent(/datum/component/mood)
if(insaneinthemembrane.sanity < 15)
return //they've already seen it and are about to die, or are just too insane to care
to_chat(C, "OH GOD! NONE OF IT IS REAL! NONE OF IT IS REEEEEEEEEEEEEEEEEEEEEEEEAL!")
@@ -255,7 +255,7 @@
/obj/item/voodoo/attackby(obj/item/I, mob/user, params)
if(target && cooldown < world.time)
- if(I.is_hot())
+ if(I.get_temperature())
to_chat(target, "You suddenly feel very hot")
target.adjust_bodytemperature(50)
GiveHint(target)
@@ -324,14 +324,11 @@
cooldown = world.time + cooldown_time
/obj/item/voodoo/proc/update_targets()
- possible = list()
+ LAZYINITLIST(possible)
if(!voodoo_link)
return
- var/list/prints = voodoo_link.return_fingerprints()
- if(!length(prints))
- return FALSE
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
- if(prints[md5(H.dna.uni_identity)])
+ if(md5(H.dna.uni_identity) in voodoo_link.fingerprints)
possible |= H
/obj/item/voodoo/proc/GiveHint(mob/victim,force=0)
diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm
index 1df8e43316..6f4c3fca10 100644
--- a/code/modules/antagonists/wizard/equipment/soulstone.dm
+++ b/code/modules/antagonists/wizard/equipment/soulstone.dm
@@ -238,6 +238,7 @@
T.stop_sound_channel(CHANNEL_HEARTBEAT)
T.invisibility = INVISIBILITY_ABSTRACT
T.dust_animation()
+ QDEL_IN(T, 5)
var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade(src)
S.status_flags |= GODMODE //So they won't die inside the stone somehow
S.canmove = FALSE//Can't move out of the soul stone
diff --git a/code/modules/antagonists/wizard/wizard.dm b/code/modules/antagonists/wizard/wizard.dm
index 8a20a81555..89324f0691 100644
--- a/code/modules/antagonists/wizard/wizard.dm
+++ b/code/modules/antagonists/wizard/wizard.dm
@@ -57,19 +57,19 @@
if(!GLOB.wizardstart.len)
SSjob.SendToLateJoin(owner.current)
to_chat(owner, "HOT INSERTION, GO GO GO")
- owner.current.forceMove(pick(GLOB.wizardstart))
+ else
+ owner.current.forceMove(pick(GLOB.wizardstart))
/datum/antagonist/wizard/proc/create_objectives()
var/datum/objective/new_objective = new("Cause as much creative mayhem as you can aboard the station! The more outlandish your methods of achieving this, the better! Make sure there's a decent amount of crew alive to tell of your tale.")
+ new_objective.completed = TRUE //So they can greentext without admin intervention.
new_objective.owner = owner
objectives += new_objective
- var/datum/objective/escape/escape_objective = new
- escape_objective.owner = owner
- objectives += escape_objective
-
- for(var/datum/objective/O in objectives)
- owner.objectives += O
+ if (!(locate(/datum/objective/escape) in objectives))
+ var/datum/objective/escape/escape_objective = new
+ escape_objective.owner = owner
+ objectives += escape_objective
/datum/antagonist/wizard/on_removal()
unregister()
@@ -183,7 +183,6 @@
new_objective.owner = owner
new_objective.target = master
new_objective.explanation_text = "Protect [master.current.real_name], the wizard."
- owner.objectives += new_objective
objectives += new_objective
//Random event wizard
@@ -251,7 +250,6 @@
/datum/antagonist/wizard/academy/create_objectives()
var/datum/objective/new_objective = new("Protect Wizard Academy from the intruders")
new_objective.owner = owner
- owner.objectives += new_objective
objectives += new_objective
//Solo wizard report
diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm
index 186eb1b024..6b87278e00 100644
--- a/code/modules/assembly/flash.dm
+++ b/code/modules/assembly/flash.dm
@@ -201,8 +201,10 @@
/obj/item/assembly/flash/cyborg
/obj/item/assembly/flash/cyborg/attack(mob/living/M, mob/user)
- ..()
+ . = ..()
new /obj/effect/temp_visual/borgflash(get_turf(src))
+ if(. && !CONFIG_GET(flag/disable_borg_flash_knockdown) && iscarbon(M) && !M.resting && !M.get_eye_protection())
+ M.Knockdown(80)
/obj/item/assembly/flash/cyborg/attack_self(mob/user)
..()
diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm
index 07f31a6678..7405549b3d 100644
--- a/code/modules/assembly/infrared.dm
+++ b/code/modules/assembly/infrared.dm
@@ -10,7 +10,7 @@
var/maxlength = 8
var/list/obj/effect/beam/i_beam/beams
var/olddir = 0
- var/datum/component/redirect/listener
+ var/turf/listeningTo
var/hearing_range = 3
/obj/item/assembly/infra/Initialize()
@@ -33,7 +33,7 @@
/obj/item/assembly/infra/Destroy()
STOP_PROCESSING(SSobj, src)
- QDEL_NULL(listener)
+ listeningTo = null
QDEL_LIST(beams)
. = ..()
@@ -163,8 +163,12 @@
next_activate = world.time + 30
/obj/item/assembly/infra/proc/switchListener(turf/newloc)
- QDEL_NULL(listener)
- listener = newloc.AddComponent(/datum/component/redirect, list(COMSIG_ATOM_EXITED = CALLBACK(src, .proc/check_exit)))
+ if(listeningTo == newloc)
+ return
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_ATOM_EXITED)
+ RegisterSignal(newloc, COMSIG_ATOM_EXITED, .proc/check_exit)
+ listeningTo = newloc
/obj/item/assembly/infra/proc/check_exit(datum/source, atom/movable/offender)
if(QDELETED(src))
diff --git a/code/modules/atmospherics/gasmixtures/reactions.dm b/code/modules/atmospherics/gasmixtures/reactions.dm
index 8e320b2f3e..f9c831a65a 100644
--- a/code/modules/atmospherics/gasmixtures/reactions.dm
+++ b/code/modules/atmospherics/gasmixtures/reactions.dm
@@ -210,9 +210,9 @@
return cached_results["fire"] ? REACTING : NO_REACTION
-//fusion: a terrible idea that was fun but broken. Now reworked to be less broken and more interesting. Again (and again, and again)
+//fusion: a terrible idea that was fun but broken. Now reworked to be less broken and more interesting. Again (and again, and again). Again!
//Fusion Rework Counter: Please increment this if you make a major overhaul to this system again.
-//5 reworks
+//6 reworks
/datum/gas_reaction/fusion
exclude = FALSE
@@ -220,100 +220,79 @@
name = "Plasmic Fusion"
id = "fusion"
-//Since fusion isn't really intended to happen in successive chains, the requirements are very high
/datum/gas_reaction/fusion/init_reqs()
min_requirements = list(
"TEMP" = FUSION_TEMPERATURE_THRESHOLD,
- "ENER" = FUSION_ENERGY_THRESHOLD,
+ /datum/gas/tritium = FUSION_TRITIUM_MOLES_USED,
/datum/gas/plasma = FUSION_MOLE_THRESHOLD,
- /datum/gas/tritium = FUSION_MOLE_THRESHOLD
- )
+ /datum/gas/carbon_dioxide = FUSION_MOLE_THRESHOLD)
/datum/gas_reaction/fusion/react(datum/gas_mixture/air, datum/holder)
var/list/cached_gases = air.gases
- var/temperature = air.temperature
- if(!air.analyzer_results)
- air.analyzer_results = new
- var/list/cached_scan_results = air.analyzer_results
var/turf/open/location
if (istype(holder,/datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet.
var/datum/pipeline/fusion_pipenet = holder
location = get_turf(pick(fusion_pipenet.members))
else
location = get_turf(holder)
-
+ if(!air.analyzer_results)
+ air.analyzer_results = new
+ var/list/cached_scan_results = air.analyzer_results
var/old_heat_capacity = air.heat_capacity()
- var/reaction_energy = 0
-
- var/mediation = FUSION_MEDIATION_FACTOR*(air.heat_capacity()-(cached_gases[/datum/gas/plasma]*GLOB.meta_gas_specific_heats[/datum/gas/plasma]))/(air.total_moles()-cached_gases[/datum/gas/plasma]) //This is the average specific heat of the mixture,not including plasma.
-
- var/gases_fused = air.total_moles() - cached_gases[/datum/gas/plasma]
- var/plasma_differential = (cached_gases[/datum/gas/plasma] - gases_fused) / air.total_moles()
- var/reaction_efficiency = FUSION_EFFICIENCY_BASE ** -((plasma_differential ** 2) / FUSION_EFFICIENCY_DIVISOR) //https://www.desmos.com/calculator/6jjx3vdrvx
-
+ var/reaction_energy = 0 //Reaction energy can be negative or positive, for both exothermic and endothermic reactions.
+ var/initial_plasma = cached_gases[/datum/gas/plasma]
+ var/initial_carbon = cached_gases[/datum/gas/carbon_dioxide]
+ var/scale_factor = (air.volume)/(PI) //We scale it down by volume/Pi because for fusion conditions, moles roughly = 2*volume, but we want it to be based off something constant between reactions.
+ var/toroidal_size = (2*PI)+TORADIANS(arctan((air.volume-TOROID_VOLUME_BREAKEVEN)/TOROID_VOLUME_BREAKEVEN)) //The size of the phase space hypertorus
var/gas_power = 0
+ var/list/gas_fusion_powers = GLOB.meta_gas_fusions
for (var/gas_id in cached_gases)
- gas_power += reaction_efficiency * (GLOB.meta_gas_fusions[gas_id]*cached_gases[gas_id])
+ gas_power += (gas_fusion_powers[gas_id]*cached_gases[gas_id])
+ var/instability = MODULUS((gas_power*INSTABILITY_GAS_POWER_FACTOR)**2,toroidal_size) //Instability effects how chaotic the behavior of the reaction is
+ cached_scan_results[id] = instability//used for analyzer feedback
- var/power_ratio = gas_power/mediation
- cached_scan_results[id] = power_ratio //used for analyzer feedback
+ var/plasma = (initial_plasma-FUSION_MOLE_THRESHOLD)/(scale_factor) //We have to scale the amounts of carbon and plasma down a significant amount in order to show the chaotic dynamics we want
+ var/carbon = (initial_carbon-FUSION_MOLE_THRESHOLD)/(scale_factor) //We also subtract out the threshold amount to make it harder for fusion to burn itself out.
- for (var/gas_id in cached_gases) //and now we fuse
- cached_gases[gas_id] = 0
+ //The reaction is a specific form of the Kicked Rotator system, which displays chaotic behavior and can be used to model particle interactions.
+ plasma = MODULUS(plasma - (instability*sin(TODEGREES(carbon))), toroidal_size)
+ carbon = MODULUS(carbon - plasma, toroidal_size)
- var/radiation_power = (FUSION_RADIATION_FACTOR * power_ratio) / (power_ratio + FUSION_RADIATION_CONSTANT) //https://www.desmos.com/calculator/4i1f296phl
- var/zap_power = ((FUSION_ZAP_POWER_ASYMPTOTE * power_ratio) / (power_ratio + FUSION_ZAP_POWER_CONSTANT)) + FUSION_ZAP_POWER_BASE //https://www.desmos.com/calculator/n0zkdpxnrr
- var/do_explosion = FALSE
- var/zap_range //these ones are set later
- var/fusion_prepare_to_die_edition_rng
- if (power_ratio > FUSION_SUPER_TIER_THRESHOLD) //power ratio 50+: SUPER TIER. The gases become so energized that they fuse into a ton of tritium, which is pretty nice! Until you consider the fact that everything just exploded, the canister is probably going to break and you're irradiated.
- reaction_energy += gases_fused * FUSION_RELEASE_ENERGY_SUPER * (power_ratio / FUSION_ENERGY_DIVISOR_SUPER)
- cached_gases[/datum/gas/tritium] += gases_fused * FUSION_GAS_CREATION_FACTOR_TRITIUM //60% of the gas is converted to energy, 40% to trit
- fusion_prepare_to_die_edition_rng = 100 //Wait a minute..
- do_explosion = TRUE
- zap_range = FUSION_ZAP_RANGE_SUPER
+ cached_gases[/datum/gas/plasma] = plasma*scale_factor + FUSION_MOLE_THRESHOLD //Scales the gases back up
+ cached_gases[/datum/gas/carbon_dioxide] = carbon*scale_factor + FUSION_MOLE_THRESHOLD
+ var/delta_plasma = initial_plasma - cached_gases[/datum/gas/plasma]
- else if (power_ratio > FUSION_HIGH_TIER_THRESHOLD) //power ratio 20-50; High tier. The reaction is so energized that it fuses into a small amount of stimulum, and some pluoxium. Very dangerous, but super cool and super useful.
- reaction_energy += gases_fused * FUSION_RELEASE_ENERGY_HIGH * (power_ratio / FUSION_ENERGY_DIVISOR_HIGH)
- cached_gases[/datum/gas/stimulum] += gases_fused * FUSION_GAS_CREATION_FACTOR_STIM //40% of the gas is converted to energy, 60% to stim and pluox
- cached_gases[/datum/gas/pluoxium] += gases_fused * FUSION_GAS_CREATION_FACTOR_PLUOX
- fusion_prepare_to_die_edition_rng = power_ratio //Now we're getting into dangerous territory
- do_explosion = TRUE
- zap_range = FUSION_ZAP_RANGE_HIGH
-
- else if (power_ratio > FUSION_MID_TIER_THRESHOLD) //power_ratio 5 to 20; Mediation is overpowered, fusion reaction starts to break down.
- reaction_energy += gases_fused * FUSION_RELEASE_ENERGY_MID * (power_ratio / FUSION_ENERGY_DIVISOR_MID)
- cached_gases[/datum/gas/nitryl] += gases_fused * FUSION_GAS_CREATION_FACTOR_NITRYL //20% of the gas is converted to energy, 80% to nitryl and N2O
- cached_gases[/datum/gas/nitrous_oxide] += gases_fused * FUSION_GAS_CREATION_FACTOR_N2O
- fusion_prepare_to_die_edition_rng = power_ratio * FUSION_MID_TIER_RAD_PROB_FACTOR //Still unlikely, but don't stand next to the reaction unprotected
- zap_range = FUSION_ZAP_RANGE_MID
-
- else //power ratio 0 to 5; Gas power is overpowered. Fusion isn't nearly as powerful.
- reaction_energy += gases_fused * FUSION_RELEASE_ENERGY_LOW * (power_ratio / FUSION_ENERGY_DIVISOR_LOW)
- cached_gases[/datum/gas/bz] += gases_fused * FUSION_GAS_CREATION_FACTOR_BZ //10% of the gas is converted to energy, 90% to BZ and CO2
- cached_gases[/datum/gas/carbon_dioxide] += gases_fused * FUSION_GAS_CREATION_FACTOR_CO2
- fusion_prepare_to_die_edition_rng = power_ratio * FUSION_LOW_TIER_RAD_PROB_FACTOR //Low, but still something to look out for
- zap_range = FUSION_ZAP_RANGE_LOW
-
- //All the deadly consequences of fusion, consolidated for your viewing pleasure
- if (location)
- if(prob(fusion_prepare_to_die_edition_rng)) //Some.. permanent effects
- if(do_explosion)
- explosion(location, 0, 0, 5, power_ratio, TRUE, TRUE) //large shockwave, the actual radius is quite small - people will recognize that you're doing fusion
- radiation_pulse(location, radiation_power) //You mean causing a super-tier fusion reaction in the halls is a bad idea?
- SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, 30000)//The science is cool though.
- playsound(location, 'sound/effects/supermatter.ogg', 100, 0)
- else
- playsound(location, 'sound/effects/phasein.ogg', 75, 0)
- //These will always happen, so be prepared
- tesla_zap(location, zap_range, zap_power, TESLA_FUSION_FLAGS) //larpers beware
- location.fire_nuclear_particles(power_ratio) //see code/modules/projectile/energy/nuclear_particle.dm
+ reaction_energy += delta_plasma*PLASMA_BINDING_ENERGY //Energy is gained or lost corresponding to the creation or destruction of mass.
+ if(instability < FUSION_INSTABILITY_ENDOTHERMALITY)
+ reaction_energy = max(reaction_energy,0) //Stable reactions don't end up endothermic.
+ else if (reaction_energy < 0)
+ reaction_energy *= (instability-FUSION_INSTABILITY_ENDOTHERMALITY)**0.5
+ if(air.thermal_energy() + reaction_energy < 0) //No using energy that doesn't exist.
+ cached_gases[/datum/gas/plasma] = initial_plasma
+ cached_gases[/datum/gas/carbon_dioxide] = initial_carbon
+ return NO_REACTION
+ cached_gases[/datum/gas/tritium] -= FUSION_TRITIUM_MOLES_USED
+ //The decay of the tritium and the reaction's energy produces waste gases, different ones depending on whether the reaction is endo or exothermic
if(reaction_energy > 0)
+ cached_gases[/datum/gas/oxygen] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT)
+ cached_gases[/datum/gas/nitrous_oxide] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT)
+ else
+ cached_gases[/datum/gas/bz] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT)
+ cached_gases[/datum/gas/nitryl] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT)
+
+ if(reaction_energy)
+ if(location)
+ var/particle_chance = ((PARTICLE_CHANCE_CONSTANT)/(reaction_energy-PARTICLE_CHANCE_CONSTANT)) + 1//Asymptopically approaches 100% as the energy of the reaction goes up.
+ if(prob(PERCENT(particle_chance)))
+ location.fire_nuclear_particle()
+ var/rad_power = max((FUSION_RAD_COEFFICIENT/instability) + FUSION_RAD_MAX,0)
+ radiation_pulse(location,rad_power)
+
var/new_heat_capacity = air.heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
- air.temperature = max(((temperature*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB)
+ air.temperature = CLAMP(((air.temperature*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB,INFINITY)
return REACTING
/datum/gas_reaction/nitrylformation //The formation of nitryl. Endothermic. Requires N2O as a catalyst.
diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm
index 304d050630..854e94b13d 100644
--- a/code/modules/awaymissions/corpse.dm
+++ b/code/modules/awaymissions/corpse.dm
@@ -17,6 +17,7 @@
var/faction = null
var/permanent = FALSE //If true, the spawner will not disappear upon running out of uses.
var/random = FALSE //Don't set a name or gender, just go random
+ var/antagonist_type
var/objectives = null
var/uses = 1 //how many times can we spawn from it. set to -1 for infinite.
var/brute_damage = 0
@@ -110,9 +111,16 @@
if(show_flavour)
to_chat(M, "[flavour_text]")
var/datum/mind/MM = M.mind
+ var/datum/antagonist/A
+ if(antagonist_type)
+ A = MM.add_antag_datum(antagonist_type)
if(objectives)
+ if(!A)
+ A = MM.add_antag_datum(/datum/antagonist/custom)
for(var/objective in objectives)
- MM.objectives += new/datum/objective(objective)
+ var/datum/objective/O = new/datum/objective(objective)
+ O.owner = MM
+ A.objectives += O
if(assignedrole)
M.mind.assigned_role = assignedrole
special(M, name)
@@ -586,3 +594,57 @@
shoes = /obj/item/clothing/shoes/sneakers/black
suit = /obj/item/clothing/suit/armor/vest
glasses = /obj/item/clothing/glasses/sunglasses/reagent
+
+/obj/effect/mob_spawn/human/lavaknight
+ name = "odd cryogenics pod"
+ desc = "A humming cryo pod. You can barely recognise a faint glow underneath the built up ice. The machine is attempting to wake up its occupant."
+ mob_name = "a displaced knight from another dimension"
+ icon = 'icons/obj/machines/sleeper.dmi'
+ icon_state = "sleeper"
+ roundstart = FALSE
+ id_job = "Knight"
+ job_description = "Cydonian Knight"
+ death = FALSE
+ random = TRUE
+ outfit = /datum/outfit/lavaknight
+ mob_species = /datum/species/human
+ flavour_text = "You are a knight who conveniently has some form of retrograde amnesia. \
+ You cannot remember where you came from. However, a few things remain burnt into your mind, most prominently a vow to never harm another sapient being under any circumstances unless it is hellbent on ending your life. \
+ Remember: hostile creatures and such are fair game for attacking, but under no circumstances are you to attack anything capable of thought and/or speech unless it has made it its life's calling to chase you to the ends of the earth."
+ assignedrole = "Cydonian Knight"
+
+/obj/effect/mob_spawn/human/lavaknight/special(mob/living/new_spawn)
+ if(ishuman(new_spawn))
+ var/mob/living/carbon/human/H = new_spawn
+ H.dna.features["mam_ears"] = "Cat, Big" //cat people
+ H.dna.features["mcolor"] = H.hair_color
+ H.update_body()
+
+/obj/effect/mob_spawn/human/lavaknight/Destroy()
+ new/obj/structure/showcase/machinery/oldpod/used(drop_location())
+ return ..()
+
+/datum/outfit/lavaknight
+ name = "Cydonian Knight"
+ uniform = /obj/item/clothing/under/assistantformal
+ mask = /obj/item/clothing/mask/breath
+ shoes = /obj/item/clothing/shoes/sneakers/black
+ r_pocket = /obj/item/melee/transforming/energy/sword/cx
+ suit = /obj/item/clothing/suit/space/hardsuit/lavaknight
+ suit_store = /obj/item/tank/internals/oxygen
+ id = /obj/item/card/id/knight/blue
+
+/obj/effect/mob_spawn/human/lavaknight/captain
+ name = "odd gilded cryogenics pod"
+ desc = "A humming cryo pod that appears to be gilded. You can barely recognise a faint glow underneath the built up ice. The machine is attempting to wake up its occupant."
+ flavour_text = "You are a knight who conveniently has some form of retrograde amnesia. \
+ You cannot remember where you came from. However, a few things remain burnt into your mind, most prominently a vow to never harm another sapient being under any circumstances unless it is hellbent on ending your life. \
+ Remember: hostile creatures and such are fair game for attacking, but under no circumstances are you to attack anything capable of thought and/or speech unless it has made it its life's calling to chase you to the ends of the earth. \
+ You feel a natural instict to lead, and as such, you should strive to lead your comrades to safety, and hopefully home. You also feel a burning determination to uphold your vow, as well as your fellow comrade's."
+ outfit = /datum/outfit/lavaknight/captain
+ id_job = "Knight Captain"
+
+/datum/outfit/lavaknight/captain
+ name ="Cydonian Knight Captain"
+ l_pocket = /obj/item/twohanded/dualsaber/hypereutactic
+ id = /obj/item/card/id/knight/captain
diff --git a/code/modules/awaymissions/mission_code/Academy.dm b/code/modules/awaymissions/mission_code/Academy.dm
index b7b21bbb9b..77cdf8441b 100644
--- a/code/modules/awaymissions/mission_code/Academy.dm
+++ b/code/modules/awaymissions/mission_code/Academy.dm
@@ -264,8 +264,9 @@
var/mob/living/carbon/human/H = new(drop_location())
H.equipOutfit(/datum/outfit/butler)
var/datum/mind/servant_mind = new /datum/mind()
- var/datum/objective/O = new("Serve [user.real_name].")
- servant_mind.objectives += O
+ var/datum/antagonist/magic_servant/A = new
+ servant_mind.add_antag_datum(A)
+ A.setup_master(user)
servant_mind.transfer_to(H)
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [user.real_name] Servant?", ROLE_WIZARD, null, ROLE_WIZARD, 50, H)
diff --git a/code/modules/cargo/bounties/assistant.dm b/code/modules/cargo/bounties/assistant.dm
index cf4efaa8c6..4edcb04e8f 100644
--- a/code/modules/cargo/bounties/assistant.dm
+++ b/code/modules/cargo/bounties/assistant.dm
@@ -1,46 +1,46 @@
/datum/bounty/item/assistant/strange_object
name = "Strange Object"
description = "Nanotrasen has taken an interest in strange objects. Find one in maint, and ship it off to CentCom right away."
- reward = 1200
+ reward = 600
wanted_types = list(/obj/item/relic)
/datum/bounty/item/assistant/scooter
name = "Scooter"
description = "Nanotrasen has determined walking to be wasteful. Ship a scooter to CentCom to speed operations up."
- reward = 1080 // the mat hoffman
+ reward = 850 // the mat hoffman
wanted_types = list(/obj/vehicle/ridden/scooter)
include_subtypes = FALSE
/datum/bounty/item/assistant/skateboard
name = "Skateboard"
description = "Nanotrasen has determined walking to be wasteful. Ship a skateboard to CentCom to speed operations up."
- reward = 900 // the tony hawk
+ reward = 700 // the tony hawk
wanted_types = list(/obj/vehicle/ridden/scooter/skateboard)
/datum/bounty/item/assistant/stunprod
name = "Stunprod"
description = "CentCom demands a stunprod to use against dissidents. Craft one, then ship it."
- reward = 1300
+ reward = 800
wanted_types = list(/obj/item/melee/baton/cattleprod)
/datum/bounty/item/assistant/soap
name = "Soap"
description = "Soap has gone missing from CentCom's bathrooms and nobody knows who took it. Replace it and be the hero CentCom needs."
- reward = 2000
+ reward = 1000
required_count = 3
wanted_types = list(/obj/item/soap)
/datum/bounty/item/assistant/spear
name = "Spears"
description = "CentCom's security forces are going through budget cuts. You will be paid if you ship a set of spears."
- reward = 2000
+ reward = 1000
required_count = 5
wanted_types = list(/obj/item/twohanded/spear)
/datum/bounty/item/assistant/toolbox
name = "Toolboxes"
description = "There's an absence of robustness at Central Command. Hurry up and ship some toolboxes as a solution."
- reward = 2000
+ reward = 1000
required_count = 6
wanted_types = list(/obj/item/storage/toolbox)
@@ -53,81 +53,81 @@
/datum/bounty/item/assistant/clown_box
name = "Clown Box"
description = "The universe needs laughter. Stamp cardboard with a clown stamp and ship it out."
- reward = 1500
+ reward = 750
wanted_types = list(/obj/item/storage/box/clown)
/datum/bounty/item/assistant/cheesiehonkers
name = "Cheesie Honkers"
description = "Apparently the company that makes Cheesie Honkers is going out of business soon. CentCom wants to stock up before it happens!"
- reward = 1200
+ reward = 1000
required_count = 3
wanted_types = list(/obj/item/reagent_containers/food/snacks/cheesiehonkers)
/datum/bounty/item/assistant/baseball_bat
name = "Baseball Bat"
description = "Baseball fever is going on at CentCom! Be a dear and ship them some baseball bats, so that management can live out their childhood dream."
- reward = 2000
+ reward = 1000
required_count = 5
wanted_types = list(/obj/item/melee/baseball_bat)
/datum/bounty/item/assistant/extendohand
name = "Extendo-Hand"
description = "Commander Betsy is getting old, and can't bend over to get the telescreen remote anymore. Management has requested an extendo-hand to help her out."
- reward = 2500
+ reward = 1250
wanted_types = list(/obj/item/extendohand)
/datum/bounty/item/assistant/donut
name = "Donuts"
description = "CentCom's security forces are facing heavy losses against the Syndicate. Ship donuts to raise morale."
- reward = 3000
+ reward = 2000
required_count = 10
wanted_types = list(/obj/item/reagent_containers/food/snacks/donut)
/datum/bounty/item/assistant/donkpocket
name = "Donk-Pockets"
description = "Consumer safety recall: Warning. Donk-Pockets manufactured in the past year contain hazardous lizard biomatter. Return units to CentCom immediately."
- reward = 3000
+ reward = 1000
required_count = 10
wanted_types = list(/obj/item/reagent_containers/food/snacks/donkpocket)
/datum/bounty/item/assistant/briefcase
name = "Briefcase"
description = "Central Command will be holding a business convention this year. Ship a few briefcases in support."
- reward = 2500
+ reward = 1500
required_count = 5
wanted_types = list(/obj/item/storage/briefcase, /obj/item/storage/secure/briefcase)
/datum/bounty/item/assistant/sunglasses
name = "Sunglasses"
description = "A famous blues duo is passing through the sector, but they've lost their shades and they can't perform. Ship new sunglasses to CentCom to rectify this."
- reward = 3000
+ reward = 1000
required_count = 2
wanted_types = list(/obj/item/clothing/glasses/sunglasses)
/datum/bounty/item/assistant/monkey_hide
name = "Monkey Hide"
description = "One of the scientists at CentCom is interested in testing products on monkey skin. Your mission is to acquire monkey's hide and ship it."
- reward = 1500
+ reward = 500
wanted_types = list(/obj/item/stack/sheet/animalhide/monkey)
/datum/bounty/item/assistant/shard
name = "Shards"
description = "A killer clown has been stalking CentCom, and staff have been unable to catch her because she's not wearing shoes. Please ship some shards so that a booby trap can be constructed."
- reward = 1500
+ reward = 500
required_count = 15
wanted_types = list(/obj/item/shard)
/datum/bounty/item/assistant/comfy_chair
name = "Comfy Chairs"
description = "Commander Pat is unhappy with his chair. He claims it hurts his back. Ship some alternatives out to humor him."
- reward = 1500
+ reward = 900
required_count = 5
wanted_types = list(/obj/structure/chair/comfy)
/datum/bounty/item/assistant/geranium
name = "Geraniums"
description = "Commander Zot has the hots for Commander Zena. Send a shipment of geraniums - her favorite flower - and he'll happily reward you."
- reward = 4000
+ reward = 1000
required_count = 3
wanted_types = list(/obj/item/reagent_containers/food/snacks/grown/poppy/geranium)
@@ -142,7 +142,7 @@
/datum/bounty/item/assistant/shadyjims
name = "Shady Jim's"
description = "There's an irate officer at CentCom demanding that he receive a box of Shady Jim's cigarettes. Please ship one. He's starting to make threats."
- reward = 500
+ reward = 750
wanted_types = list(/obj/item/storage/fancy/cigarettes/cigpack_shadyjims)
/datum/bounty/item/assistant/potted_plants
diff --git a/code/modules/cargo/bounties/botany.dm b/code/modules/cargo/bounties/botany.dm
index 34906b321a..754de480cd 100644
--- a/code/modules/cargo/bounties/botany.dm
+++ b/code/modules/cargo/bounties/botany.dm
@@ -1,5 +1,5 @@
/datum/bounty/item/botany
- reward = 5000
+ reward = 1200
var/datum/bounty/item/botany/multiplier = 0 //adds bonus reward money; increased for higher tier or rare mutations
var/datum/bounty/item/botany/bonus_desc //for adding extra flavor text to bounty descriptions
var/datum/bounty/item/botany/foodtype = "meal" //same here
@@ -64,7 +64,7 @@
multiplier = 4 //hush money
bonus_desc = "Do not mention this shipment to security."
foodtype = "\"meal\""
-
+
/datum/bounty/item/botany/cannabis_white
name = "Lifeweed Leaves"
wanted_types = list(/obj/item/reagent_containers/food/snacks/grown/cannabis/white)
diff --git a/code/modules/cargo/bounties/chef.dm b/code/modules/cargo/bounties/chef.dm
index b9d9ebc184..719a2d10a5 100644
--- a/code/modules/cargo/bounties/chef.dm
+++ b/code/modules/cargo/bounties/chef.dm
@@ -1,34 +1,34 @@
/datum/bounty/item/chef/birthday_cake
name = "Birthday Cake"
description = "Nanotrasen's birthday is coming up! Ship them a birthday cake to celebrate!"
- reward = 4000
+ reward = 1000
wanted_types = list(/obj/item/reagent_containers/food/snacks/store/cake/birthday, /obj/item/reagent_containers/food/snacks/cakeslice/birthday)
/datum/bounty/item/chef/soup
name = "Soup"
description = "To quell the homeless uprising, Nanotrasen will be serving soup to all underpaid workers. Ship any type of soup."
- reward = 3000
+ reward = 700
required_count = 3
wanted_types = list(/obj/item/reagent_containers/food/snacks/soup)
/datum/bounty/item/chef/popcorn
name = "Popcorn Bags"
description = "Upper management wants to host a movie night. Ship bags of popcorn for the occasion."
- reward = 3000
+ reward = 800
required_count = 3
wanted_types = list(/obj/item/reagent_containers/food/snacks/popcorn)
/datum/bounty/item/chef/onionrings
name = "Onion Rings"
description = "Nanotrasen is remembering Saturn day. Ship onion rings to show the station's support."
- reward = 3000
+ reward = 800
required_count = 3
wanted_types = list(/obj/item/reagent_containers/food/snacks/onionrings)
/datum/bounty/item/chef/icecreamsandwich
name = "Ice Cream Sandwiches"
description = "Upper management has been screaming non-stop for ice cream. Please send some."
- reward = 4000
+ reward = 800
required_count = 3
wanted_types = list(/obj/item/reagent_containers/food/snacks/icecreamsandwich)
@@ -36,7 +36,7 @@
name = "Bread"
description = "Problems with central planning have led to bread prices skyrocketing. Ship some bread to ease tensions."
reward = 1000
- wanted_types = list(/obj/item/reagent_containers/food/snacks/store/bread, /obj/item/reagent_containers/food/snacks/breadslice, /obj/item/reagent_containers/food/snacks/bun, /obj/item/reagent_containers/food/snacks/pizzabread, /obj/item/reagent_containers/food/snacks/rawpastrybase)
+ wanted_types = list(/obj/item/reagent_containers/food/snacks/store/bread, /obj/item/reagent_containers/food/snacks/breadslice, /obj/item/reagent_containers/food/snacks/bun, /obj/item/reagent_containers/food/snacks/pizzabread, /obj/item/reagent_containers/food/snacks/rawpastrybase)
/datum/bounty/item/chef/pie
name = "Pie"
@@ -47,21 +47,21 @@
/datum/bounty/item/chef/salad
name = "Salad or Rice Bowls"
description = "CentCom management is going on a health binge. Your order is to ship salad or rice bowls."
- reward = 3000
+ reward = 1200
required_count = 3
wanted_types = list(/obj/item/reagent_containers/food/snacks/salad)
/datum/bounty/item/chef/carrotfries
name = "Carrot Fries"
description = "Night sight can mean life or death! A shipment of carrot fries is the order."
- reward = 3500
+ reward = 1300
required_count = 3
wanted_types = list(/obj/item/reagent_containers/food/snacks/carrotfries)
/datum/bounty/item/chef/superbite
name = "Super Bite Burger"
description = "Commander Tubbs thinks he can set a competitive eating world record. All he needs is a super bite burger shipped to him."
- reward = 12000
+ reward = 1800
wanted_types = list(/obj/item/reagent_containers/food/snacks/burger/superbite)
/datum/bounty/item/chef/poppypretzel
@@ -73,19 +73,19 @@
/datum/bounty/item/chef/cubancarp
name = "Cuban Carp"
description = "To celebrate the birth of Castro XXVII, ship one cuban carp to CentCom."
- reward = 8000
+ reward = 3000
wanted_types = list(/obj/item/reagent_containers/food/snacks/cubancarp)
/datum/bounty/item/chef/hotdog
name = "Hot Dog"
description = "Nanotrasen is conducting taste tests to determine the best hot dog recipe. Ship your station's version to participate."
- reward = 8000
+ reward = 4000
wanted_types = list(/obj/item/reagent_containers/food/snacks/hotdog)
/datum/bounty/item/chef/eggplantparm
name = "Eggplant Parmigianas"
description = "A famous singer will be arriving at CentCom, and their contract demands that they only be served Eggplant Parmigiana. Ship some, please!"
- reward = 3500
+ reward = 2500
required_count = 3
wanted_types = list(/obj/item/reagent_containers/food/snacks/eggplantparm)
@@ -99,33 +99,33 @@
/datum/bounty/item/chef/chawanmushi
name = "Chawanmushi"
description = "Nanotrasen wants to improve relations with its sister company, Japanotrasen. Ship Chawanmushi immediately."
- reward = 8000
+ reward = 5000
wanted_types = list(/obj/item/reagent_containers/food/snacks/chawanmushi)
/datum/bounty/item/chef/kebab
name = "Kebabs"
description = "Remove all kebab from station you are best food. Ship to CentCom to remove from the premises."
- reward = 3500
+ reward = 1500
required_count = 3
wanted_types = list(/obj/item/reagent_containers/food/snacks/kebab)
/datum/bounty/item/chef/soylentgreen
name = "Soylent Green"
description = "CentCom has heard wonderful things about the product 'Soylent Green', and would love to try some. If you endulge them, expect a pleasant bonus."
- reward = 5000
+ reward = 4000
wanted_types = list(/obj/item/reagent_containers/food/snacks/soylentgreen)
/datum/bounty/item/chef/pancakes
name = "Pancakes"
description = "Here at Nanotrasen we consider employees to be family. And you know what families love? Pancakes. Ship a baker's dozen."
- reward = 5000
+ reward = 4000
required_count = 13
wanted_types = list(/datum/crafting_recipe/food/pancakes)
/datum/bounty/item/chef/nuggies
name = "Chicken Nuggets"
description = "The vice president's son won't shut up about chicken nuggies. Would you mind shipping some?"
- reward = 4000
+ reward = 2500
required_count = 6
wanted_types = list(/obj/item/reagent_containers/food/snacks/nugget)
diff --git a/code/modules/cargo/bounties/engineering.dm b/code/modules/cargo/bounties/engineering.dm
index cf2cd7d93c..1f16788c4d 100644
--- a/code/modules/cargo/bounties/engineering.dm
+++ b/code/modules/cargo/bounties/engineering.dm
@@ -27,41 +27,41 @@
/datum/bounty/item/engineering/pacman
name = "P.A.C.M.A.N.-type portable generator"
description = "A neighboring station had a problem with their SMES, and now need something to power their communications console. Can you send them a P.AC.M.A.N.?"
- reward = 3500 //2500 for the cargo one
+ reward = 1500 //2500 for the cargo one
wanted_types = list(/obj/machinery/power/port_gen/pacman)
/datum/bounty/item/engineering/canisters
name = "Gas Canisters"
description = "After a recent debacle in a nearby sector, 10 gas canisters are needed for containing an experimental aerosol before it kills all the local fauna."
- reward = 5000
+ reward = 3000
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
+ reward = 1000
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
+ reward = 1500
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
+ reward = 1500
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
+ reward = 2500
required_count = 3
wanted_types = list(/obj/item/pipe_dispenser)
@@ -75,19 +75,19 @@
/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
+ reward = 1500
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
+ reward = 1500
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."
- reward = 75000 //requires 14k credits of purchases, not to mention cooperation with engineering/heads of staff to set up inside the cramped shuttle
+ reward = 50000 //requires 14k credits of purchases, not to mention cooperation with engineering/heads of staff to set up inside the cramped shuttle
wanted_types = list(/obj/singularity/energy_ball)
diff --git a/code/modules/cargo/bounties/medical.dm b/code/modules/cargo/bounties/medical.dm
index 3129051754..22964e1fb7 100644
--- a/code/modules/cargo/bounties/medical.dm
+++ b/code/modules/cargo/bounties/medical.dm
@@ -7,34 +7,34 @@
/datum/bounty/item/medical/lung
name = "Lungs"
description = "A recent explosion at Central Command has left multiple staff with punctured lungs. Ship spare lungs to be rewarded."
- reward = 10000
+ reward = 3000
required_count = 3
wanted_types = list(/obj/item/organ/lungs)
/datum/bounty/item/medical/appendix
name = "Appendix"
description = "Chef Gibb of Central Command wants to prepare a meal using a very special delicacy: an appendix. If you ship one, he'll pay."
- reward = 5000 //there are no synthetic appendixes
+ reward = 3500 //there are no synthetic appendixes
wanted_types = list(/obj/item/organ/appendix)
/datum/bounty/item/medical/ears
name = "Ears"
description = "Multiple staff at Station 12 have been left deaf due to unauthorized clowning. Ship them new ears."
- reward = 10000
+ reward = 5000
required_count = 3
wanted_types = list(/obj/item/organ/ears)
/datum/bounty/item/medical/liver
name = "Livers"
description = "Multiple high-ranking CentCom diplomats have been hospitalized with liver failure after a recent meeting with Third Soviet Union ambassadors. Help us out, will you?"
- reward = 10000
+ reward = 5500
required_count = 3
wanted_types = list(/obj/item/organ/liver)
/datum/bounty/item/medical/eye
name = "Organic Eyes"
description = "Station 5's Research Director Willem is requesting a few pairs of non-robotic eyes. Don't ask questions, just ship them."
- reward = 10000
+ reward = 3000
required_count = 3
wanted_types = list(/obj/item/organ/eyes)
exclude_types = list(/obj/item/organ/eyes/robotic)
@@ -42,7 +42,7 @@
/datum/bounty/item/medical/tongue
name = "Tongues"
description = "A recent attack by Mime extremists has left staff at Station 23 speechless. Ship some spare tongues."
- reward = 10000
+ reward = 4500
required_count = 3
wanted_types = list(/obj/item/organ/tongue)
@@ -79,7 +79,7 @@
required_count = 200
wanted_types = (L,/datum/reagent/blood)
if(istype(L,/datum/reagent/blood))
- wanted_types += L
+ wanted_types += L
/datum/bounty/item/medical/bloodu //Dosnt work do to how blood is yet*
name = "U-Type Blood"
@@ -88,40 +88,40 @@
required_count = 200
wanted_types = (U,/datum/reagent/blood)
if(istype(U,/datum/reagent/blood))
- wanted_types += U
+ wanted_types += U
*/
/datum/bounty/item/medical/surgery
name = "Surgery tool implants"
description = "Our medical interns keep dropping their Shambler's Juice while they're performing open heart surgery. One of them even had the audacity to say he only had two hands!"
- reward = 10000
+ reward = 7000
required_count = 3
wanted_types = list(/obj/item/organ/cyberimp/arm/surgery)
/datum/bounty/item/medical/chemmaker
name = "Portable Chem Dispenser"
description = "After a new chemist mixed up some water and a banana, we lost our only chem dispenser. Please send us a replacement and you will be compensated."
- reward = 7000
+ reward = 5000
wanted_types = list(/obj/machinery/chem_dispenser)
/datum/bounty/item/medical/advhealthscaner
name = "Advanced Health Analyzer"
description = "A ERT Medical unit needs the new 'advanced health analyzer', for a mission at a Station 4. Can you send some?."
- reward = 4000
+ reward = 3000
required_count = 5
wanted_types = list(/obj/item/healthanalyzer/advanced)
/datum/bounty/item/medical/wallmounts
name = "Defibrillator wall mounts"
description = "New Space OSHA regulation state that are new cloning medical wing needs a few 'Easy to access defibrillartors'. Can you send a few before we get a lawsuit?"
- reward = 5000
+ reward = 2000
required_count = 3
wanted_types = list(/obj/machinery/defibrillator_mount)
/datum/bounty/item/medical/defibrillator
name = "New defibillators"
description = "After years of storge are defibrillator units have become more liabilities then we want. Please send us some new ones to replace these old ones."
- reward = 5000
+ reward = 2250
required_count = 5
wanted_types = list(/obj/item/defibrillator)
diff --git a/code/modules/cargo/bounties/mining.dm b/code/modules/cargo/bounties/mining.dm
index 51d93f83b5..1f3266af62 100644
--- a/code/modules/cargo/bounties/mining.dm
+++ b/code/modules/cargo/bounties/mining.dm
@@ -8,58 +8,58 @@
/datum/bounty/item/mining/goliath_boat
name = "Goliath Hide Boat"
description = "Commander Menkov wants to participate in the annual Lavaland Regatta. He is asking your shipwrights to build the swiftest boat known to man."
- reward = 10000
+ reward = 5500
wanted_types = list(/obj/vehicle/ridden/lavaboat)
/datum/bounty/item/mining/bone_oar
name = "Bone Oars"
description = "Commander Menkov requires oars to participate in the annual Lavaland Regatta. Ship a pair over."
- reward = 4000
+ reward = 2000
required_count = 2
wanted_types = list(/obj/item/oar)
/datum/bounty/item/mining/bone_axe
name = "Bone Axe"
description = "Station 12 has had their fire axes stolen by marauding clowns. Ship them a bone axe as a replacement."
- reward = 7500
+ reward = 3500
wanted_types = list(/obj/item/twohanded/fireaxe/boneaxe)
/datum/bounty/item/mining/bone_armor
name = "Bone Armor"
description = "Station 14 has volunteered their lizard crew for ballistic armor testing. Ship over some bone armor."
- reward = 5000
+ reward = 2000
wanted_types = list(/obj/item/clothing/suit/armor/bone)
/datum/bounty/item/mining/skull_helmet
name = "Skull Helmet"
description = "Station 42's Head of Security has her birthday tomorrow! We want to suprise her with a fashionable skull helmet."
- reward = 4000
+ reward = 2000
wanted_types = list(/obj/item/clothing/head/helmet/skull)
/datum/bounty/item/mining/bone_talisman
name = "Bone Talismans"
description = "Station 14's Research Director claims that pagan bone talismans protect their wearer. Ship them a few so they can start testing."
- reward = 7500
+ reward = 3500
required_count = 3
wanted_types = list(/obj/item/clothing/accessory/talisman)
/datum/bounty/item/mining/bone_dagger
name = "Bone Daggers"
description = "Central Command's canteen is undergoing budget cuts. Ship over some bone daggers so our Chef can keep working."
- reward = 5000
+ reward = 1000
required_count = 3
wanted_types = list(/obj/item/kitchen/knife/combat/bone)
/datum/bounty/item/mining/basalt
name = "Artificial Basalt Tiles"
description = "Central Command's Ash Walker exhibit needs to be expanded again, we just need some more basalt flooring."
- reward = 5000
+ reward = 2200
required_count = 60
wanted_types = list(/obj/item/stack/tile/basalt)
/datum/bounty/item/mining/fruit
name = "Cactus Fruit"
description = "Central Command's Ash Walker habitat needs more fauna, send us some local fruit seeds!"
- reward = 2000
+ reward = 1000
required_count = 1
wanted_types = list(/obj/item/seeds/lavaland/cactus)
diff --git a/code/modules/cargo/bounties/reagent.dm b/code/modules/cargo/bounties/reagent.dm
index 9f1c76db3d..5137d0a6f3 100644
--- a/code/modules/cargo/bounties/reagent.dm
+++ b/code/modules/cargo/bounties/reagent.dm
@@ -116,11 +116,11 @@ datum/bounty/reagent/complex_drink/New()
wanted_reagent = new reagent_type
name = wanted_reagent.name
description = "CentCom is offering a reward for talented mixologists. Ship a container of [name] to claim the prize."
- reward += rand(0, 4) * 500
+ reward += rand(0, 4) * 300
/datum/bounty/reagent/chemical
name = "Chemical"
- reward = 4000
+ reward = 2750
required_volume = 30
datum/bounty/reagent/chemical/New()
diff --git a/code/modules/cargo/bounties/science.dm b/code/modules/cargo/bounties/science.dm
index 2ac79f6ee8..6102d8d685 100644
--- a/code/modules/cargo/bounties/science.dm
+++ b/code/modules/cargo/bounties/science.dm
@@ -1,116 +1,116 @@
/datum/bounty/item/science/boh
name = "Bag of Holding"
description = "Nanotrasen would make good use of high-capacity backpacks. If you have any, please ship them."
- reward = 10000
+ reward = 5000
wanted_types = list(/obj/item/storage/backpack/holding)
/datum/bounty/item/science/tboh
name = "Trash Bag of Holding"
description = "Nanotrasen would make good use of high-capacity trash bags. If you have any, please ship them."
- reward = 10000
+ reward = 3000
wanted_types = list(/obj/item/storage/backpack/holding)
/datum/bounty/item/science/bluespace_syringe
name = "Bluespace Syringe"
description = "Nanotrasen would make good use of high-capacity syringes. If you have any, please ship them."
- reward = 10000
+ reward = 1500
wanted_types = list(/obj/item/reagent_containers/syringe/bluespace)
/datum/bounty/item/science/bluespace_body_bag
name = "Bluespace Body Bag"
description = "Nanotrasen would make good use of high-capacity body bags. If you have any, please ship them."
- reward = 10000
+ reward = 5000
wanted_types = list(/obj/item/bodybag/bluespace)
/datum/bounty/item/science/nightvision_goggles
name = "Night Vision Goggles"
description = "An electrical storm has busted all the lights at CentCom. While management is waiting for replacements, perhaps some night vision goggles can be shipped?"
- reward = 10000
+ reward = 1000
wanted_types = list(/obj/item/clothing/glasses/night, /obj/item/clothing/glasses/meson/night, /obj/item/clothing/glasses/hud/health/night, /obj/item/clothing/glasses/hud/security/night, /obj/item/clothing/glasses/hud/diagnostic/night)
/datum/bounty/item/science/experimental_welding_tool
name = "Experimental Welding Tool"
description = "A recent accident has left most of CentCom's welding tools exploded. Ship replacements to be rewarded."
- reward = 10000
+ reward = 5000
required_count = 3
wanted_types = list(/obj/item/weldingtool/experimental)
/datum/bounty/item/science/cryostasis_beaker
name = "Cryostasis Beaker"
description = "Chemists at Central Command have discovered a new chemical that can only be held in cryostasis beakers. The only problem is they don't have any! Rectify this to receive payment."
- reward = 10000
+ reward = 2000
wanted_types = list(/obj/item/reagent_containers/glass/beaker/noreact)
/datum/bounty/item/science/diamond_drill
name = "Diamond Mining Drill"
description = "Central Command is willing to pay three months salary in exchange for one diamond mining drill."
- reward = 15000
+ reward = 5500
wanted_types = list(/obj/item/pickaxe/drill/diamonddrill, /obj/item/mecha_parts/mecha_equipment/drill/diamonddrill)
/datum/bounty/item/science/floor_buffer
name = "Floor Buffer Upgrade"
description = "One of CentCom's janitors made a small fortune betting on carp races. Now they'd like to commission an upgrade to their floor buffer."
- reward = 10000
+ reward = 3000
wanted_types = list(/obj/item/janiupgrade)
/datum/bounty/item/science/advanced_mop
name = "Advanced Mop"
description = "Excuse me. I'd like to request $17 for a push broom rebristling. Either that, or an advanced mop."
- reward = 10000
+ reward = 3000
wanted_types = list(/obj/item/mop/advanced)
/datum/bounty/item/science/advanced_egun
name = "Advanced Energy Gun"
description = "With the price of rechargers on the rise, upper management is interested in purchasing guns that are self-powered. If you ship one, they'll pay."
- reward = 10000
+ reward = 1800
wanted_types = list(/obj/item/gun/energy/e_gun/nuclear)
/datum/bounty/item/science/bscells
name = "Bluespace Power Cells"
description = "Someone in upper management keeps using the excuse that his tablet battery dies when he's in the middle of work. This will be the last time he doesn't have his presentation, I swear to -"
- reward = 7000
+ reward = 3000
required_count = 10 //Easy to make
wanted_types = list(/obj/item/stock_parts/cell/bluespace)
/datum/bounty/item/science/t4manip
name = "Femto-Manipulators"
description = "One of our Chief Engineers has OCD. Can you send us some femto-manipulators so he stops complaining that his ID doesn't fit perfectly in the PDA slot?"
- reward = 7000
+ reward = 2000
required_count = 20 //Easy to make
wanted_types = list(/obj/item/stock_parts/manipulator/femto)
/datum/bounty/item/science/t4bins
name = "Bluespace Matter Bins"
description = "The local Janitorial union has gone on strike. Can you send us some bluespace bins so we don't have to take out our own trash?"
- reward = 7000
+ reward = 2000
required_count = 20 //Easy to make
wanted_types = list(/obj/item/stock_parts/matter_bin/bluespace)
/datum/bounty/item/science/t4capacitor
name = "Quadratic Capacitor"
description = "One of our linguists doesn't understand why they're called Quadratic capacitors. Can you give him a few so he leaves us alone about it?"
- reward = 7000
+ reward = 2000
required_count = 20 //Easy to make
wanted_types = list(/obj/item/stock_parts/capacitor/quadratic)
/datum/bounty/item/science/t4triphasic
name = "Triphasic Scanning Module"
description = "One of our scientists got into the liberty caps and is demanding new scanning modules so he can talk to ghosts. At this point we just want him out of our office."
- reward = 7000
+ reward = 2000
required_count = 20 //Easy to make
wanted_types = list(/obj/item/stock_parts/scanning_module/triphasic)
/datum/bounty/item/science/t4microlaser
name = "Quad-Ultra Micro-Laser"
description = "The cats on Vega 9 are breeding out of control. We need something to corral them into one area so we can saturation bomb it."
- reward = 7000
+ reward = 2000
required_count = 20 //Easy to make
wanted_types = list(/obj/item/stock_parts/micro_laser/quadultra)
/datum/bounty/item/science/fakecrystals
name = "synthetic bluespace crystals"
description = "Don't, uh, tell anyone, but one of our BSA arrays might have had a little... accident. Send us some bluespace crystals so we can recalibrate it before anyone realizes. The whole set uses artificial bluespace crystals, so we need and not any other type of bluespace crystals..."
- reward = 10000
+ reward = 8000
required_count = 5
wanted_types = list(/obj/item/stack/ore/bluespace_crystal/artificial)
exclude_types = list(/obj/item/stack/ore/bluespace_crystal,
diff --git a/code/modules/cargo/bounties/security.dm b/code/modules/cargo/bounties/security.dm
index cae8d10c61..6ed86cd4b7 100644
--- a/code/modules/cargo/bounties/security.dm
+++ b/code/modules/cargo/bounties/security.dm
@@ -1,54 +1,54 @@
/datum/bounty/item/security/riotshotgun
name = "Riot Shotguns"
description = "Hooligans have boarded CentCom! Ship riot shotguns quick, or things are going to get dirty."
- reward = 5000
+ reward = 2500
required_count = 2
wanted_types = list(/obj/item/gun/ballistic/shotgun/riot)
/datum/bounty/item/security/recharger
name = "Rechargers"
description = "Nanotrasen military academy is conducting marksmanship exercises. They request that rechargers be shipped."
- reward = 2000
+ reward = 1700
required_count = 3
wanted_types = list(/obj/machinery/recharger)
/datum/bounty/item/security/practice
name = "Practice Laser Gun"
description = "Nanotrasen Military Academy is conducting routine marksmanship exercises. The clown hid all the practice lasers, and we're not using live weapons after last time."
- reward = 3000
+ reward = 1500
required_count = 3
wanted_types = list(/obj/item/gun/energy/laser/practice)
/datum/bounty/item/security/flashshield
name = "Strobe Shield"
description = "One of our Emergency Response Agents thinks there's vampires in a local station. Send him something to help with his fear of the dark and protect him, too."
- reward = 5000
+ reward = 3000
wanted_types = list(/obj/item/assembly/flash/shield)
/datum/bounty/item/security/sechuds
name = "Sec HUDs"
description = "Nanotrasen military academy has started to train officers how to use Sec HUDs to the fullest affect. Please send spare Sec HUDs so we can teach the men."
- reward = 3000
+ reward = 1250
required_count = 5
wanted_types = list(/obj/item/clothing/glasses/hud/security)
/datum/bounty/item/security/techslugs
name = "Tech Slugs"
description = "Nanotrasen Military Academy is conducting an ammo loading and use lessons, on the new 'Tech Slugs'. Problem is we don't have any, please fix this..."
- reward = 7500
+ reward = 3500
required_count = 15
wanted_types = list(/obj/item/ammo_casing/shotgun/techshell)
-/datum/bounty/item/security/WT550
+/datum/bounty/item/security/wt550
name = "Spare WT-550 clips"
description = "Nanotrasen Military Academy's ammunition is running low, please send in spare ammo for practice."
- reward = 7500
+ reward = 1500
required_count = 5
wanted_types = list(/obj/item/ammo_box/magazine/wt550m9)
/datum/bounty/item/security/pins
name = "Test range firing pins"
description = "Nanotrasen Military Academy just got a new set of guns, sadly they didn't come with any pins. Can you send us some Test range locked firing pins?"
- reward = 5000
+ reward = 2750
required_count = 3
wanted_types = list(/obj/item/firing_pin/test_range)
diff --git a/code/modules/cargo/bounties/slime.dm b/code/modules/cargo/bounties/slime.dm
index 4aa0797c70..f52f995a27 100644
--- a/code/modules/cargo/bounties/slime.dm
+++ b/code/modules/cargo/bounties/slime.dm
@@ -1,10 +1,10 @@
/datum/bounty/item/slime
- reward = 3000
+ reward = 1950
/datum/bounty/item/slime/New()
..()
description = "Nanotrasen's science lead is hunting for the rare and exotic [name]. A bounty has been offered for finding it."
- reward += rand(0, 4) * 500
+ reward += rand(0, 4) * 250
/datum/bounty/item/slime/green
name = "Green Slime Extract"
diff --git a/code/modules/cargo/bounties/special.dm b/code/modules/cargo/bounties/special.dm
index adffaf999a..be91b1d8aa 100644
--- a/code/modules/cargo/bounties/special.dm
+++ b/code/modules/cargo/bounties/special.dm
@@ -1,14 +1,14 @@
/datum/bounty/item/alien_organs
name = "Alien Organs"
description = "Nanotrasen is interested in studying Xenomorph biology. Ship a set of organs to be thoroughly compensated."
- reward = 25000
+ reward = 13500
required_count = 3
wanted_types = list(/obj/item/organ/brain/alien, /obj/item/organ/alien, /obj/item/organ/body_egg/alien_embryo)
/datum/bounty/item/syndicate_documents
name = "Syndicate Documents"
description = "Intel regarding the syndicate is highly prized at CentCom. If you find syndicate documents, ship them. You could save lives."
- reward = 15000
+ reward = 10000
wanted_types = list(/obj/item/documents/syndicate, /obj/item/documents/photocopy)
/datum/bounty/item/syndicate_documents/applies_to(obj/O)
@@ -22,15 +22,15 @@
/datum/bounty/item/adamantine
name = "Adamantine"
description = "Nanotrasen's anomalous materials division is in desparate need for Adamantine. Send them a large shipment and we'll make it worth your while."
- reward = 35000
+ reward = 15000
required_count = 10
wanted_types = list(/obj/item/stack/sheet/mineral/adamantine)
/datum/bounty/more_bounties
name = "More Bounties"
description = "Complete enough bounties and CentCom will issue new ones!"
- reward = 3 // number of bounties
- var/required_bounties = 5
+ reward = 8 // number of bounties
+ var/required_bounties = 3
/datum/bounty/more_bounties/can_claim()
return ..() && completed_bounty_count() >= required_bounties
diff --git a/code/modules/cargo/bounties/virus.dm b/code/modules/cargo/bounties/virus.dm
index 8f078a2668..938ac7708d 100644
--- a/code/modules/cargo/bounties/virus.dm
+++ b/code/modules/cargo/bounties/virus.dm
@@ -1,5 +1,5 @@
/datum/bounty/virus
- reward = 5000
+ reward = 3000
var/shipped = FALSE
var/stat_value = 0
var/stat_name = ""
@@ -11,7 +11,7 @@
stat_value *= -1
name = "Virus ([stat_name] of [stat_value])"
description = "Nanotrasen is interested in a virus with a [stat_name] stat of exactly [stat_value]. Central Command will pay handsomely for such a virus."
- reward += rand(0, 4) * 500
+ reward += rand(0, 4) * 400
/datum/bounty/virus/completion_string()
return shipped ? "Shipped" : "Not Shipped"
diff --git a/code/modules/cargo/exports.dm b/code/modules/cargo/exports.dm
index b7550465d9..9a99f201b3 100644
--- a/code/modules/cargo/exports.dm
+++ b/code/modules/cargo/exports.dm
@@ -1,6 +1,6 @@
/* How it works:
The shuttle arrives at CentCom dock and calls sell(), which recursively loops through all the shuttle contents that are unanchored.
-
+
Each object in the loop is checked for applies_to() of various export datums, except the invalid ones.
*/
@@ -31,7 +31,7 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they
setupExports()
var/list/contents = AM.GetAllContents()
-
+
var/datum/export_report/report = external_report
if(!report) //If we don't have any longer transaction going on
report = new
@@ -58,7 +58,7 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they
var/unit_name = "" // Unit name. Only used in "Received [total_amount] [name]s [message]." message
var/message = ""
var/cost = 100 // Cost of item, in cargo credits. Must not alow for infinite price dupes, see above.
- var/k_elasticity = 1/30 //coefficient used in marginal price calculation that roughly corresponds to the inverse of price elasticity, or "quantity elasticity"
+ var/k_elasticity = 1/20 //coefficient used in marginal price calculation that roughly corresponds to the inverse of price elasticity, or "quantity elasticity" - CIT EDIT 30 - > 20
var/list/export_types = list() // Type of the exported object. If none, the export datum is considered base type.
var/include_subtypes = TRUE // Set to FALSE to make the datum apply only to a strict type.
var/list/exclude_types = list() // Types excluded from export
@@ -125,9 +125,9 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they
if(amount <=0 || the_cost <=0)
return FALSE
-
+
report.total_value[src] += the_cost
-
+
if(istype(O, /datum/export/material))
report.total_amount[src] += amount*MINERAL_MATERIAL_AMOUNT
else
@@ -148,7 +148,7 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they
var/total_value = ex.total_value[src]
var/total_amount = ex.total_amount[src]
-
+
var/msg = "[total_value] credits: Received [total_amount] "
if(total_value > 0)
msg = "+" + msg
diff --git a/code/modules/cargo/exports/gear.dm b/code/modules/cargo/exports/gear.dm
index 125e0f708b..7ff14df04c 100644
--- a/code/modules/cargo/exports/gear.dm
+++ b/code/modules/cargo/exports/gear.dm
@@ -1,83 +1,800 @@
/datum/export/gear
+ include_subtypes = FALSE
+
+//blanket
+/datum/export/gear/hat
+ cost = 3
+ unit_name = "clothing"
+ export_types = list(/obj/item/clothing)
+ include_subtypes = TRUE
+
+//Hats
+
+//Blanket
+/datum/export/gear/hat
+ cost = 5
+ unit_name = "hat"
+ export_types = list(/obj/item/clothing/head)
+ include_subtypes = TRUE
/datum/export/gear/sec_helmet
- cost = 100
+ cost = 70
unit_name = "helmet"
export_types = list(/obj/item/clothing/head/helmet/sec)
-/datum/export/gear/sec_armor
- cost = 100
- unit_name = "armor vest"
- export_types = list(/obj/item/clothing/suit/armor/vest)
+/datum/export/gear/sec_soft
+ cost = 50
+ unit_name = "soft sec cap"
+ export_types = list(/obj/item/clothing/head/soft/sec)
-/datum/export/gear/riot_shield
- cost = 100
- unit_name = "riot shield"
- export_types = list(/obj/item/shield/riot)
+/datum/export/gear/sec_helmetalt
+ cost = 50
+ unit_name = "bullet proof helmet"
+ export_types = list(/obj/item/clothing/head/helmet/alt)
+/datum/export/gear/sec_helmetold
+ cost = 10
+ unit_name = "old helmet"
+ export_types = list(/obj/item/clothing/head/helmet/old)
+
+/datum/export/gear/sec_helmetblue
+ cost = 75
+ unit_name = "blue helmet"
+ export_types = list(/obj/item/clothing/head/helmet/blueshirt)
+
+/datum/export/gear/sec_helmetriot
+ cost = 100
+ unit_name = "riot helmet"
+ export_types = list(/obj/item/clothing/head/helmet/riot)
+
+/datum/export/gear/sec_helmet_light
+ cost = 20
+ unit_name = "justice helmet"
+ export_types = list(/obj/item/clothing/head/helmet/justice/escape)
+ include_subtypes = TRUE
+
+/datum/export/gear/syndicate_helmetswat
+ cost = 250
+ unit_name = "syndicate helmet"
+ export_types = list(/obj/item/clothing/head/helmet/swat)
+
+/datum/export/gear/sec_helmetswat
+ cost = 150
+ unit_name = "swat helmet"
+ export_types = list(/obj/item/clothing/head/helmet/swat/nanotrasen)
+
+/datum/export/gear/thunder_helmet
+ cost = 120
+ unit_name = "thunder dome helmet"
+ export_types = list(/obj/item/clothing/head/helmet/thunderdome)
+
+/datum/export/gear/roman_real
+ cost = 30
+ unit_name = "roman helmet"
+ export_types = list(/obj/item/clothing/head/helmet/roman)
+
+/datum/export/gear/roman_realalt
+ cost = 60
+ unit_name = "legionnaire helmet"
+ export_types = list(/obj/item/clothing/head/helmet/roman/legionnaire)
+
+/datum/export/gear/roman_fake
+ cost = 10
+ unit_name = "toy roman helmet"
+ export_types = list(/obj/item/clothing/head/helmet/roman/fake)
+
+/datum/export/gear/roman_fakealt
+ cost = 20
+ unit_name = "toy legionnaire helmet"
+ export_types = list(/obj/item/clothing/head/helmet/roman/legionnaire/fake)
+
+/datum/export/gear/ash_walker_helm
+ cost = 70
+ unit_name = "gladiator helmet"
+ export_types = list(/obj/item/clothing/head/helmet/gladiator)
+
+/datum/export/gear/lasertag
+ cost = 30 //Has armor
+ unit_name = "lasertag helmet"
+ export_types = list(/obj/item/clothing/head/helmet/redtaghelm)
+
+/datum/export/gear/lasertag/blue
+ export_types = list(/obj/item/clothing/head/helmet/bluetaghelm)
+
+/datum/export/gear/knight_helmet
+ cost = 200
+ k_elasticity = 1/5 //Rare, dont flood it
+ unit_name = "knight helmet"
+ export_types = list(/obj/item/clothing/head/helmet/knight, /obj/item/clothing/head/helmet/knight/blue, /obj/item/clothing/head/helmet/knight/yellow, /obj/item/clothing/head/helmet/knight/red)
+
+/datum/export/gear/skull_hat
+ cost = 70
+ k_elasticity = 1/15 //Its just a skull
+ unit_name = "skull"
+ export_types = list(/obj/item/clothing/head/helmet/skull)
+
+/datum/export/gear/durathread_helm
+ cost = 100
+ k_elasticity = 1/15
+ unit_name = "durathread hat"
+ export_types = list(/obj/item/clothing/head/helmet/durathread, /obj/item/clothing/head/beret/durathread, /obj/item/clothing/head/beanie/durathread)
+
+/datum/export/gear/hard_hats
+ cost = 50
+ unit_name = "hard hat"
+ export_types = list(/obj/item/clothing/head/hardhat, /obj/item/clothing/head/hardhat/orange, /obj/item/clothing/head/hardhat/white, /obj/item/clothing/head/hardhat/dblue)
+
+/datum/export/gear/atmos_helm
+ cost = 200 //Armored, fire proof, light, and presser proof
+ unit_name = "atmos hard hat"
+ export_types = list(/obj/item/clothing/head/hardhat/atmos)
+
+/datum/export/gear/crowns
+ cost = 350 //Armored, gold 300cr of gold to make so give them 50 more for working
+ k_elasticity = 1/5 //Anti-floods
+ unit_name = "crown"
+ export_types = list(/obj/item/clothing/head/crown, /obj/item/clothing/head/crown/fancy)
+
+/datum/export/gear/cchat
+ cost = 40
+ unit_name = "centcom hat"
+ export_types = list(/obj/item/clothing/head/centhat)
+
+/datum/export/gear/caphat
+ cost = 150
+ unit_name = "command hat"
+ export_types = list(/obj/item/clothing/head/caphat, /obj/item/clothing/head/caphat/parade, /obj/item/clothing/head/caphat/beret)
+
+/datum/export/gear/hophat
+ cost = 130
+ unit_name = "hop hat"
+ export_types = list(/obj/item/clothing/head/hopcap, /obj/item/clothing/head/hopcap/beret)
+
+/datum/export/gear/dechat
+ cost = 75
+ k_elasticity = 1/8 //Anti-floods
+ unit_name = "fedora"
+ export_types = list(/obj/item/clothing/head/fedora/det_hat, /obj/item/clothing/head/fedora/curator, /obj/item/clothing/head/fedora)
+
+/datum/export/gear/hoshat
+ cost = 140
+ unit_name = "hos hat"
+ export_types = list(/obj/item/clothing/head/HoS, /obj/item/clothing/head/HoS/beret, /obj/item/clothing/head/beret/sec/navyhos)
+
+/datum/export/gear/syndahoshat
+ cost = 300
+ unit_name = "syndicate command hat"
+ export_types = list(/obj/item/clothing/head/HoS/syndicate, /obj/item/clothing/head/HoS/beret/syndicate)
+
+/datum/export/gear/wardenhat
+ cost = 90
+ unit_name = "warden hat"
+ export_types = list(/obj/item/clothing/head/warden, /obj/item/clothing/head/warden/drill, /obj/item/clothing/head/beret/sec/navywarden)
+
+/datum/export/gear/sechats
+ cost = 60
+ unit_name = "sec beret"
+ export_types = list(/obj/item/clothing/head/beret/sec, /obj/item/clothing/head/beret/sec/navyofficer)
+
+/datum/export/gear/berets
+ cost = 30
+ unit_name = "beret"
+ export_types = list(/obj/item/clothing/head/beret/qm, /obj/item/clothing/head/beret/rd, /obj/item/clothing/head/beret/cmo, /obj/item/clothing/head/beret)
+
+/datum/export/gear/berets
+ cost = 30
+ unit_name = "beret"
+ export_types = list(/obj/item/clothing/head/beret/qm, /obj/item/clothing/head/beret/rd, /obj/item/clothing/head/beret/cmo, /obj/item/clothing/head/beret)
+
+/datum/export/gear/collectable
+ cost = 500
+ unit_name = "collectable hat"
+ k_elasticity = 1/10 //dont flood these
+ export_types = list(/obj/item/clothing/head/collectable)
+ include_subtypes = TRUE
+
+/datum/export/gear/fancyhats
+ cost = 75
+ unit_name = "fancy hat"
+ k_elasticity = 1/10 //dont flood these
+ export_types = list(/obj/item/clothing/head/that, /obj/item/clothing/head/bowler, /obj/item/clothing/head/lizard, /obj/item/clothing/head/canada)
+
+/datum/export/gear/welders
+ cost = 30
+ unit_name = "welder helm"
+ k_elasticity = 1/20 //dont flood these
+ export_types = list(/obj/item/clothing/head/welding)
+
+/datum/export/gear/magichat //Magic as is Antags-Wiz/Cults
+ cost = 450
+ unit_name = "magic hat"
+ export_types = list(/obj/item/clothing/head/wizard, /obj/item/clothing/head/culthood, /obj/item/clothing/head/magus, /obj/item/clothing/head/helmet/clockwork)
+ exclude_types = list(/obj/item/clothing/head/wizard/fake, /obj/item/clothing/head/wizard/marisa/fake)
+ include_subtypes = TRUE
+
+//Shoes
+
+//Blanket
+/datum/export/gear/shoes
+ cost = 1 //Really dont want to sell EVERY SHOE EVER - yet*
+ unit_name = "shoes"
+ export_types = list(/obj/item/clothing/shoes)
+ include_subtypes = TRUE
+
+/datum/export/gear/clown_shoesmk
+ cost = 600
+ unit_name = "mk-honk prototype shoes"
+ export_types = list(/obj/item/clothing/shoes/clown_shoes/banana_shoes)
+
+/datum/export/gear/magboots
+ cost = 50
+ unit_name = "magboots"
+ export_types = list(/obj/item/clothing/shoes/magboots, /obj/item/clothing/shoes/magboots/atmos)
+
+/datum/export/gear/nosellboots
+ cost = -5000 //We DONT want scew antags
+ unit_name = "error shipment stolen"
+ export_types = list(/obj/item/clothing/shoes/magboots/advance, /obj/item/clothing/shoes/magboots/deathsquad)
+
+/datum/export/gear/syndamagboots
+ cost = 250
+ unit_name = "blood redmagboots"
+ export_types = list(/obj/item/clothing/shoes/magboots/syndie)
+
+/datum/export/gear/combatboots
+ cost = 30
+ unit_name = "combat boots"
+ export_types = list(/obj/item/clothing/shoes/combat)
+
+/datum/export/gear/swatboots
+ cost = 45
+ unit_name = "swat boots"
+ export_types = list(/obj/item/clothing/shoes/combat/swat)
+
+/datum/export/gear/galoshes
+ cost = 50
+ unit_name = "galoshes"
+ export_types = list(/obj/item/clothing/shoes/galoshes, /obj/item/clothing/shoes/galoshes/dry)
+
+/datum/export/gear/clown
+ cost = 10
+ unit_name = "clown shoes"
+ export_types = list(/obj/item/clothing/shoes/clown_shoes, /obj/item/clothing/shoes/clown_shoes/jester)
+
+/datum/export/gear/dressshoes
+ cost = 10
+ unit_name = "dress shoes"
+ export_types = list(/obj/item/clothing/shoes/laceup, /obj/item/clothing/shoes/singerb, /obj/item/clothing/shoes/singery)
+
+/datum/export/gear/working
+ cost = 15
+ unit_name = "boots"
+ export_types = list(/obj/item/clothing/shoes/jackboots/fast, /obj/item/clothing/shoes/winterboots, /obj/item/clothing/shoes/jackboots, /obj/item/clothing/shoes/workboots, /obj/item/clothing/shoes/workboots/mining)
+
+/datum/export/gear/hopboots
+ cost = 350 //costs 1000 credits for miners to get
+ unit_name = "jump boots"
+ export_types = list(/obj/item/clothing/shoes/bhop)
+
+/datum/export/gear/magicboots //Magic as in Antag - Wiz/Cults
+ cost = 450
+ unit_name = "magic shoes"
+ export_types = list(/obj/item/clothing/shoes/sandal/marisa, /obj/item/clothing/shoes/sandal/magic, /obj/item/clothing/shoes/cult, /obj/item/clothing/shoes/clockwork, /obj/item/clothing/shoes/clown_shoes/taeclowndo, /obj/item/clothing/shoes/sandal/slippers)
+ include_subtypes = TRUE
+
+//Headsets/Ears
+
+//Blanket
+/datum/export/gear/ears
+ cost = 2 //We dont want to sell every headset ever
+ unit_name = "ear gear"
+ export_types = list(/obj/item/clothing/ears, /obj/item/radio/headset)
+ include_subtypes = TRUE
+
+//Gloves
+
+//Blanket
+/datum/export/gear/gloves
+ cost = 4 //Glove crafting can be done
+ unit_name = "gloves"
+ export_types = list(/obj/item/clothing/gloves)
+ include_subtypes = TRUE
+
+/datum/export/gear/boxing
+ cost = 10 //Padding as well as a weapon
+ unit_name = "boxing gloves"
+ export_types = list(/obj/item/clothing/gloves/boxing)
+ include_subtypes = TRUE
+
+/datum/export/gear/combatgloves
+ cost = 80
+ unit_name = "combat gloves"
+ export_types = list(/obj/item/clothing/gloves/combat, /obj/item/clothing/gloves/rapid, /obj/item/clothing/gloves/krav_maga)
+ include_subtypes = TRUE
+
+/datum/export/gear/bonegloves
+ cost = 30
+ unit_name = "bone bracers"
+ export_types = list(/obj/item/clothing/gloves/bracer)
+
+/datum/export/gear/yellowgloves
+ cost = 50
+ unit_name = "insulated gloves"
+ export_types = list(/obj/item/clothing/gloves/color/yellow, /obj/item/clothing/gloves/color/red/insulated)
+
+/datum/export/gear/leathergloves
+ cost = 20
+ unit_name = "leather gloves"
+ export_types = list(/obj/item/clothing/gloves/botanic_leather)
+
+/datum/export/gear/fancy
+ cost = 25
+ unit_name = "fancy gloves"
+ export_types = list(/obj/item/clothing/gloves/color/black, /obj/item/clothing/gloves/color/captain, /obj/item/clothing/gloves/color/white)
+
+/datum/export/gear/magicgloves//Magic as in Antag - Wiz/Cults
+ cost = 400
+ unit_name = "magic gloves"
+ export_types = list(/obj/item/clothing/gloves/clockwork)
+ include_subtypes = TRUE
+
+//Ties/neck
+
+//Blanket
+/datum/export/gear/neck
+ cost = 5 //Fancy!
+ unit_name = "neck based gear"
+ export_types = list(/obj/item/clothing/neck)
+ include_subtypes = TRUE
+
+/datum/export/gear/collar
+ cost = 7
+ unit_name = "collar"
+ export_types = list(/obj/item/clothing/neck/petcollar)
+ include_subtypes = TRUE
+
+/datum/export/gear/bling
+ cost = 15 //Needs a coin
+ unit_name = "gold plated necklace"
+ export_types = list(/obj/item/clothing/neck/necklace/dope)
+
+//masks
+
+//Blanket
+/datum/export/gear/masks
+ cost = 3 //Mostly just fake stuff and clowngear
+ unit_name = "face gear"
+ export_types = list(/obj/item/clothing/mask)
+ include_subtypes = TRUE
+
+/datum/export/gear/gasmask
+ cost = 4
+ unit_name = "gas mask"
+ export_types = list(/obj/item/clothing/mask/gas, /obj/item/clothing/mask/gas/glass)
+
+/datum/export/gear/minermask
+ cost = 10
+ unit_name = "armored mask"
+ export_types = list(/obj/item/clothing/mask/gas/welding, /obj/item/clothing/mask/gas/explorer, /obj/item/clothing/mask/gas/syndicate)
+
+/datum/export/gear/sechailer
+ cost = 6
+ unit_name = "sec hailer"
+ export_types = list(/obj/item/clothing/mask/gas/sechailer)
+ include_subtypes = TRUE
/datum/export/gear/mask/breath
cost = 2
unit_name = "breath mask"
export_types = list(/obj/item/clothing/mask/breath)
-/datum/export/gear/mask/gas
- cost = 10
- unit_name = "gas mask"
- export_types = list(/obj/item/clothing/mask/gas)
- include_subtypes = FALSE
+//Hardsuits //If you steal/fine more they are worth selling
+//Blanket
+/datum/export/gear/hardsuit
+ cost = 250 //Its just metal/plastic after all
+ unit_name = "unknown hardsuit"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit)
+ include_subtypes = TRUE
-/datum/export/gear/space/helmet
- cost = 75
+/datum/export/gear/engi_hardsuit
+ cost = 500
+ unit_name = "engine hardsuit"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit/engine)
+
+/datum/export/gear/atmos_hardsuit
+ cost = 600
+ unit_name = "atmos hardsuit"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit/engine/atmos)
+
+/datum/export/gear/engi_hardsuit
+ cost = 1000
+ unit_name = "elite engine hardsuit"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit/engine/elite)
+
+/datum/export/gear/mining_hardsuit
+ cost = 350 //common
+ unit_name = "mining hardsuit"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit/mining)
+
+/datum/export/gear/sec_hardsuit
+ cost = 750
+ unit_name = "sec hardsuit"
+ export_types = list(/obj/item/clothing/head/helmet/space/hardsuit/mining, /obj/item/clothing/head/helmet/space/hardsuit/syndi/owl)
+
+/datum/export/gear/syndi_hardsuit
+ cost = 1250
+ unit_name = "syndi hardsuit"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit/syndi)
+
+/datum/export/gear/syndi_hardsuit
+ cost = 2750
+ unit_name = "elite syndi hardsuit"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit/syndi/elite)
+
+/datum/export/gear/medical_hardsuit
+ cost = 350 //Not all that good
+ unit_name = "meidcal hardsuit"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit/medical)
+
+/datum/export/gear/rd_hardsuit
+ cost = 850 //rare
+ unit_name = "prototype hardsuit"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit/rd)
+
+/datum/export/gear/sec_hardsuit
+ cost = 750
+ unit_name = "sec hardsuit"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit/security)
+
+/datum/export/gear/command_hardsuit
+ cost = 1300
+ unit_name = "command hardsuit"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit/security/hos, /obj/item/clothing/suit/space/hardsuit/captain)
+
+/datum/export/gear/magic_hardsuit
+ cost = 3000
+ unit_name = "magic hardsuit"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit/wizard, /obj/item/clothing/suit/space/hardsuit/shielded/wizard, /obj/item/clothing/suit/space/hardsuit/cult)
+ include_subtypes = TRUE
+
+/datum/export/gear/shield_hardsuit
+ cost = 2000
+ unit_name = "shielded hardsuit"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit/shielded)
+ include_subtypes = TRUE
+
+/datum/export/gear/rigs
+ cost = 2750
+ unit_name = "RIG"
+ export_types = list(/obj/item/clothing/suit/space/hardsuit/ancient, /obj/item/clothing/suit/space/hardsuit/ancient/mason)
+
+//Soft Suits
+
+//Blanket
+datum/export/gear/space/helmet
+ cost = 55
unit_name = "space helmet"
- export_types = list(/obj/item/clothing/head/helmet/space, /obj/item/clothing/head/helmet/space/eva, /obj/item/clothing/head/helmet/space/nasavoid)
- include_subtypes = FALSE
+ export_types = list(/obj/item/clothing/head/helmet/space)
+ include_subtypes = TRUE
/datum/export/gear/space/suit
- cost = 150
+ cost = 60
unit_name = "space suit"
- export_types = list(/obj/item/clothing/suit/space, /obj/item/clothing/suit/space/eva, /obj/item/clothing/suit/space/nasavoid)
- include_subtypes = FALSE
+ export_types = list(/obj/item/clothing/suit/space)
+ include_subtypes = TRUE
+datum/export/gear/space/helmet/plasma
+ cost = 100
+ unit_name = "plasmaman space helmet"
+ export_types = list(/obj/item/clothing/suit/space/eva/plasmaman)
-/datum/export/gear/space/syndiehelmet
- cost = 150
- unit_name = "Syndicate space helmet"
+/datum/export/gear/space/suit/plasma
+ cost = 100
+ unit_name = "plasmaman space suit"
+ export_types = list(/obj/item/clothing/suit/space/eva/plasmaman)
+
+datum/export/gear/space/helmet/synda
+ cost = 150 //Flash proof
+ unit_name = "syndicate space helmet"
export_types = list(/obj/item/clothing/head/helmet/space/syndicate)
+ include_subtypes = TRUE
-/datum/export/gear/space/syndiesuit
- cost = 300
- unit_name = "Syndicate space suit"
- export_types = list(/obj/item/clothing/suit/space/syndicate)
+/datum/export/gear/space/suit/synda
+ cost = 150
+ unit_name = "syndicate space suit"
+ export_types = list(/obj/item/clothing/head/helmet/space/syndicate)
+ include_subtypes = TRUE
+//Glasses
+
+//Blanket
+datum/export/gear/glasses //glasses are not worth selling
+ cost = 3
+ unit_name = "glasses"
+ export_types = list(/obj/item/clothing/glasses)
+ include_subtypes = TRUE
+
+/datum/export/gear/mesons
+ cost = 6
+ unit_name = "mesons"
+ export_types = list(/obj/item/clothing/glasses/meson, /obj/item/clothing/glasses/material/mining)
+ include_subtypes = TRUE
+
+/datum/export/gear/scigoggles
+ cost = 8
+ unit_name = "chem giggles"
+ export_types = list(/obj/item/clothing/glasses/science)
+ include_subtypes = TRUE
+
+/datum/export/gear/nvgoggles
+ cost = 20
+ unit_name = "night vison giggles"
+ export_types = list(/obj/item/clothing/glasses/night)
+ include_subtypes = TRUE
+
+/datum/export/gear/sunglasses
+ cost = 12
+ unit_name = "sunglasses"
+ export_types = list(/obj/item/clothing/glasses/sunglasses)
+ include_subtypes = TRUE
+
+/datum/export/gear/huds
+ cost = 10
+ unit_name = "huds"
+ export_types = list(/obj/item/clothing/glasses/hud)
+ include_subtypes = TRUE
+
+/datum/export/gear/huds/glasses
+ cost = 22
+ export_types = list(/obj/item/clothing/glasses/hud/health/sunglasses, /obj/item/clothing/glasses/hud/security/sunglasses)
+
+/datum/export/gear/weldinggoggles
+ cost = 20
+ unit_name = "welding goggles"
+ export_types = list(/obj/item/clothing/glasses/welding)
+ include_subtypes = TRUE
+
+/datum/export/gear/thermals
+ cost = 30
+ unit_name = "heat seeing goggles"
+ export_types = list(/obj/item/clothing/glasses/thermal, /obj/item/clothing/glasses/hud/toggle/thermal)
+ include_subtypes = TRUE
+
+/datum/export/gear/magic_glasses
+ cost = 140
+ unit_name = "magic goggles"
+ export_types = list(/obj/item/clothing/glasses/godeye, /obj/item/clothing/glasses/hud/health/night/cultblind, /obj/item/clothing/glasses/wraith_spectacles, /obj/item/clothing/glasses/judicial_visor)
+ include_subtypes = TRUE
+
+//////////
+//UNDER///
+//////////
+
+/datum/export/gear/jumpsuit
+ cost = 3
+ unit_name = "jumpsuit"
+ k_elasticity = 1/100 //you can craft white jumpsuits, if someone does that 300 times, they deserve the 800 credits
+ export_types = list(/obj/item/clothing/under)
+ include_subtypes = TRUE
+
+/datum/export/gear/fancy_jumpsuit
+ cost = 10
+ unit_name = "fancy clothing"
+ k_elasticity = 1/90 //These will be what sells
+ export_types = list(/obj/item/clothing/under/scratch, /obj/item/clothing/under/sl_suit, /obj/item/clothing/under/rank/vice, /obj/item/clothing/under/suit_jacket, \
+ /obj/item/clothing/under/burial, /obj/item/clothing/under/skirt/black, /obj/item/clothing/under/captainparade, /obj/item/clothing/under/hosparademale, \
+ /obj/item/clothing/under/hosparadefem, /obj/item/clothing/under/assistantformal, /obj/item/clothing/under/stripeddress, /obj/item/clothing/under/redeveninggown, \
+ /obj/item/clothing/under/plaid_skirt, /obj/item/clothing/under/geisha, /obj/item/clothing/under/trek, /obj/item/clothing/under/wedding, /obj/item/clothing/under/aviatoruniform,\
+ /obj/item/clothing/under/mega, /obj/item/clothing/under/cia, /obj/item/clothing/under/casualwear, /obj/item/clothing/under/rank)
+ include_subtypes = TRUE
+
+/datum/export/gear/armored_jumpsuit
+ cost = 15
+ unit_name = "armored_jumpsuit"
+ k_elasticity = 1/90 //These will be what sells
+ export_types = list(/obj/item/clothing/under/durathread, /obj/item/clothing/under/rank/security, /obj/item/clothing/under/plasmaman, /obj/item/clothing/under/syndicate, \
+ /obj/item/clothing/under/rank/det, /obj/item/clothing/under/rank/head_of_security, /obj/item/clothing/under/rank/security/spacepol)
+ exclude_types = list(/obj/item/clothing/under/syndicate/tacticool, /obj/item/clothing/under/syndicate/tacticool/skirt)
+ include_subtypes = TRUE
+
+/datum/export/gear/jumpsuit_addon
+ cost = 12 //Few and rare as well as quick drop off of vaule
+ unit_name = "jumpsuit add on"
+ k_elasticity = 1/10
+ export_types = list(/obj/item/clothing/accessory)
+ include_subtypes = TRUE
+
+/datum/export/gear/robes_magic
+ cost = 120
+ unit_name = "magic robes"
+ export_types = list(/obj/item/clothing/suit/wizrobe, /obj/item/clothing/suit/cultrobes, /obj/item/clothing/suit/magusred, /obj/item/clothing/suit/hooded/cultrobes)
+ exclude_types = list(/obj/item/clothing/suit/wizrobe/fake)
+ include_subtypes = TRUE
+
+//Amror
+/datum/export/gear/armor
+ cost = 80
+ unit_name = "misc armor"
+ export_types = list(/obj/item/clothing/suit/armor)
+ include_subtypes = TRUE
+
+/datum/export/gear/sec_armor
+ cost = 180
+ unit_name = "sec armor"
+ export_types = list(/obj/item/clothing/suit/armor/vest/leather, /obj/item/clothing/suit/armor/bulletproof, /obj/item/clothing/suit/armor/vest/det_suit)
+ include_subtypes = TRUE
+
+/datum/export/gear/hosarmor
+ cost = 380
+ unit_name = "hos armor"
+ export_types = list(/obj/item/clothing/suit/armor/hos)
+ include_subtypes = TRUE
+
+/datum/export/gear/wardenarmor
+ cost = 280
+ unit_name = "warden armor"
+ export_types = list(/obj/item/clothing/suit/armor/vest/warden)
+ include_subtypes = TRUE
+
+/datum/export/gear/reflector
+ cost = 500
+ unit_name = "reflector armor"
+ export_types = list(/obj/item/clothing/suit/armor/laserproof)
+ include_subtypes = TRUE
+
+/datum/export/gear/heavy_armor
+ cost = 600 //REALY hard to fine/make takes lots of slimes
+ unit_name = "heavy armor"
+ export_types = list(/obj/item/clothing/suit/armor/heavy)
+ include_subtypes = TRUE
+
+/datum/export/gear/plate_armor
+ cost = 200
+ unit_name = "plate armor"
+ export_types = list(/obj/item/clothing/suit/armor/riot/knight)
+ include_subtypes = TRUE
+
+/datum/export/gear/riot_armor
+ cost = 250
+ unit_name = "riot armor"
+ export_types = list(/obj/item/clothing/suit/armor/riot)
+ include_subtypes = TRUE
+
+/datum/export/gear/bone_armor
+ cost = 50
+ unit_name = "bone armor"
+ export_types = list(/obj/item/clothing/suit/armor/bone)
+ include_subtypes = TRUE
+
+/datum/export/gear/swat_armor
+ cost = 350
+ unit_name = "swat mki armor"
+ export_types = list(/obj/item/clothing/suit/space/swat)
+ include_subtypes = TRUE
+
+/datum/export/gear/dragon_armor
+ cost = 750
+ unit_name = "drake bone armor"
+ export_types = list(/obj/item/clothing/suit/hooded/cloak/drake)
+ include_subtypes = TRUE
+
+/datum/export/gear/commandamor
+ cost = 480
+ unit_name = "command armor"
+ export_types = list(/obj/item/clothing/suit/armor/vest/capcarapace, /obj/item/clothing/suit/armor/centcom)
+ include_subtypes = TRUE
+
+/datum/export/gear/reactive_base
+ cost = 600
+ k_elasticity = 1/2 //Lets not go over board
+ unit_name = "hollow reactive armor"
+ export_types = list(/obj/item/reactive_armour_shell, /obj/item/clothing/suit/armor/reactive)
+
+/datum/export/gear/reactive_active
+ cost = 1200
+ k_elasticity = 1/3 //Lets not go over board
+ unit_name = "working reactive armor"
+ export_types = list(/obj/item/clothing/suit/armor/reactive/repulse, /obj/item/clothing/suit/armor/reactive/tesla, /obj/item/clothing/suit/armor/reactive/teleport)
+
+///////////////////////////
+//Bomb/Rad/Bio Suits/Fire//
+///////////////////////////
/datum/export/gear/radhelmet
- cost = 50
+ cost = 20
unit_name = "radsuit hood"
export_types = list(/obj/item/clothing/head/radiation)
/datum/export/gear/radsuit
- cost = 100
+ cost = 40
unit_name = "radsuit"
export_types = list(/obj/item/clothing/suit/radiation)
+/datum/export/gear/firehelmet
+ cost = 10
+ unit_name = "firesuit helmet"
+ export_types = list(/obj/item/clothing/head/hardhat/red)
+
+/datum/export/gear/fireatmos
+ cost = 120
+ unit_name = "atmos firesuit"
+ export_types = list(/obj/item/clothing/suit/fire/atmos)
+
+/datum/export/gear/firesuit
+ cost = 20
+ unit_name = "firesuit"
+ export_types = list(/obj/item/clothing/suit/fire, /obj/item/clothing/suit/fire/firefighter, /obj/item/clothing/suit/fire/heavy)
+
/datum/export/gear/biohood
- cost = 50
+ cost = 40
unit_name = "biosuit hood"
export_types = list(/obj/item/clothing/head/bio_hood)
+ include_subtypes = TRUE
/datum/export/gear/biosuit
- cost = 100
+ cost = 60
unit_name = "biosuit"
export_types = list(/obj/item/clothing/suit/bio_suit)
+ include_subtypes = TRUE
/datum/export/gear/bombhelmet
- cost = 50
+ cost = 40
unit_name = "bomb suit hood"
export_types = list(/obj/item/clothing/head/bomb_hood)
+ include_subtypes = TRUE
/datum/export/gear/bombsuit
- cost = 100
+ cost = 60
unit_name = "bomb suit"
export_types = list(/obj/item/clothing/suit/bomb_suit)
+ include_subtypes = TRUE
+
+////////////////////
+//Cloaks and Coats//
+////////////////////
+
+/datum/export/gear/cloaks
+ cost = 30
+ unit_name = "cloak"
+ export_types = list(/obj/item/clothing/neck/cloak)
+ include_subtypes = TRUE
+
+/datum/export/gear/cloaksmining
+ cost = 90
+ unit_name = "lava land cloak"
+ export_types = list(/obj/item/clothing/suit/hooded/cloak/goliath)
+ include_subtypes = TRUE
+
+/datum/export/gear/labcoats
+ cost = 15
+ unit_name = "labcoats"
+ export_types = list(/obj/item/clothing/suit/toggle/labcoat)
+ include_subtypes = TRUE
+
+/datum/export/gear/wintercoats
+ cost = 25
+ unit_name = "wintercoats"
+ export_types = list(/obj/item/clothing/suit/hooded/wintercoat)
+ include_subtypes = TRUE
+
+//////////
+//SUITS///
+//////////
+
+/datum/export/gear/suits
+ cost = 40
+ unit_name = "suit"
+ export_types = list(/obj/item/clothing/suit)
+ include_subtypes = TRUE
+
+//////////////////////
+//Chameleon Gear//////
+//////////////////////
+/datum/export/gear/chameleon //Selling a full kit is easy money for 2 tc
+ cost = 280
+ unit_name = "chameleon item"
+ export_types = list(/obj/item/clothing/head/chameleon, /obj/item/clothing/mask/chameleon, /obj/item/clothing/under/chameleon, /obj/item/clothing/suit/chameleon, /obj/item/clothing/glasses/chameleon,\
+ /obj/item/clothing/gloves/chameleon, /obj/item/clothing/head/chameleon, /obj/item/clothing/shoes/chameleon, /obj/item/storage/backpack/chameleon, \
+ /obj/item/storage/belt/chameleon, /obj/item/radio/headset/chameleon, /obj/item/pda/chameleon, /obj/item/stamp/chameleon, /obj/item/clothing/neck/cloak/chameleon)
+ include_subtypes = TRUE
\ No newline at end of file
diff --git a/code/modules/cargo/exports/large_objects.dm b/code/modules/cargo/exports/large_objects.dm
index bf77d836fb..ce4502ba99 100644
--- a/code/modules/cargo/exports/large_objects.dm
+++ b/code/modules/cargo/exports/large_objects.dm
@@ -1,3 +1,6 @@
+/datum/export/large
+ k_elasticity = 0
+
/datum/export/large/crate
cost = 500
k_elasticity = 0
@@ -21,13 +24,13 @@
export_types = list(/obj/structure/ore_box)
/datum/export/large/crate/wood
- cost = 240
+ cost = 140
unit_name = "wooden crate"
export_types = list(/obj/structure/closet/crate/wooden)
exclude_types = list()
/datum/export/large/crate/coffin
- cost = 250//50 wooden crates cost 2000 points, and you can make 10 coffins in seconds with those planks. Each coffin selling for 250 means you can make a net gain of 500 points for wasting your time making coffins.
+ cost = 150
unit_name = "coffin"
export_types = list(/obj/structure/closet/crate/coffin)
@@ -131,104 +134,219 @@
unit_name = "security barrier"
export_types = list(/obj/item/grenade/barrier, /obj/structure/barricade/security)
+/datum/export/large/frame
+ cost = 20
+ unit_name = "structure frame"
+ export_types = list(/obj/structure/frame, /obj/structure/table_frame)
+ include_subtypes = TRUE
+
+/datum/export/large/pacman
+ cost = 125
+ unit_name = "pacman"
+ export_types = list(/obj/machinery/power/port_gen/pacman)
+
+/datum/export/large/pacman
+ cost = 150
+ unit_name = "super pacman"
+ export_types = list(/obj/machinery/power/port_gen/pacman/super)
+
+/datum/export/large/pacman
+ cost = 175
+ unit_name = "mrs super pacman"
+ export_types = list(/obj/machinery/power/port_gen/pacman/mrs)
+
+/datum/export/large/hydroponics
+ cost = 120
+ unit_name = "hydroponics tray"
+ export_types = list(/obj/machinery/hydroponics)
+
+/datum/export/large/nice_chair
+ cost = 12
+ unit_name = "Padded Chair"
+ export_types = list(/obj/structure/chair/comfy)
+
/datum/export/large/gas_canister
cost = 10 //Base cost of canister. You get more for nice gases inside.
unit_name = "Gas Canister"
export_types = list(/obj/machinery/portable_atmospherics/canister)
+
/datum/export/large/gas_canister/get_cost(obj/O)
var/obj/machinery/portable_atmospherics/canister/C = O
var/worth = 10
var/gases = C.air_contents.gases
- worth += gases[/datum/gas/bz]*4
+ worth += gases[/datum/gas/bz]*4
worth += gases[/datum/gas/stimulum]*25
worth += gases[/datum/gas/hypernoblium]*1000
- worth += gases[/datum/gas/miasma]*15
+ worth += gases[/datum/gas/miasma]*4
worth += gases[/datum/gas/tritium]*7
worth += gases[/datum/gas/pluoxium]*6
worth += gases[/datum/gas/nitryl]*30
return worth
-/datum/export/large/odysseus
+
+//////////////
+//Matstatues//
+//////////////
+
+/datum/export/large/nukestatue
+ cost = 175
+ unit_name = "Nuke statue"
+ export_types = list(/obj/structure/statue/uranium/nuke)
+
+/datum/export/large/engstatue
+ cost = 175
+ unit_name = "Engine statue"
+ export_types = list(/obj/structure/statue/uranium/eng)
+
+/datum/export/large/plasmastatue
+ cost = 720
+ unit_name = "Scientist statue"
+ export_types = list(/obj/structure/statue/plasma/scientist)
+
+/datum/export/large/hosstatue
+ cost = 225
+ unit_name = "HoS statue"
+ export_types = list(/obj/structure/statue/gold/hos)
+
+/datum/export/large/rdstatue
+ cost = 225
+ unit_name = "RD statue"
+ export_types = list(/obj/structure/statue/gold/rd)
+
+/datum/export/large/hopstatue
+ cost = 225
+ unit_name = "HoP statue"
+ export_types = list(/obj/structure/statue/gold/hop)
+
+/datum/export/large/cmostatue
+ cost = 225
+ unit_name = "CMO statue"
+ export_types = list(/obj/structure/statue/gold/cmo)
+
+/datum/export/large/cestatue
+ cost = 225
+ unit_name = "CE statue"
+ export_types = list(/obj/structure/statue/gold/ce)
+
+/datum/export/large/mdstatue
+ cost = 200
+ unit_name = "MD statue"
+ export_types = list(/obj/structure/statue/silver/md)
+
+/datum/export/large/janitorstatue
+ cost = 200
+ unit_name = "Janitor statue"
+ export_types = list(/obj/structure/statue/silver/janitor)
+
+/datum/export/large/secstatue
+ cost = 200
+ unit_name = "Sec statue"
+ export_types = list(/obj/structure/statue/silver/sec)
+
+/datum/export/large/medborgstatue
+ cost = 200
+ unit_name = "Medborg statue"
+ export_types = list(/obj/structure/statue/silver/medborg)
+
+/datum/export/large/secborgstatue
+ cost = 200
+ unit_name = "Secborg statue"
+ export_types = list(/obj/structure/statue/silver/secborg)
+
+/datum/export/large/capstatue
+ cost = 1200
+ unit_name = "Captain statue"
+ export_types = list(/obj/structure/statue/diamond/captain)
+
+/datum/export/large/aistatue
+ cost = 1200
+ unit_name = "AI statue"
+ export_types = list(/obj/structure/statue/diamond/ai1, /obj/structure/statue/diamond/ai2)
+
+/datum/export/large/clownstatue
+ cost = 2750
+ unit_name = "Clown statue"
+ export_types = list(/obj/structure/statue/bananium/clown)
+
+/datum/export/large/sandstatue
+ cost = 90 //Big cash
+ unit_name = "sandstone statue"
+ export_types = list(/obj/structure/statue/sandstone/assistant)
+
+////////////
+//MECHS/////
+////////////
+
+/datum/export/large/mech
+ include_subtypes = FALSE
+
+/datum/export/large/mech/odysseus
cost = 5500
unit_name = "working odysseus"
export_types = list(/obj/mecha/medical/odysseus)
- include_subtypes = FALSE
-/datum/export/large/ripley
+/datum/export/large/mech/ripley
cost = 6500
unit_name = "working ripley"
export_types = list(/obj/mecha/working/ripley)
- include_subtypes = FALSE
-/datum/export/large/firefighter
+/datum/export/large/mech/firefighter
cost = 9000
unit_name = "working firefighter"
export_types = list(/obj/mecha/working/ripley/firefighter)
- include_subtypes = FALSE
-/datum/export/large/gygax
+/datum/export/large/mech/gygax
cost = 19000
unit_name = "working gygax"
export_types = list(/obj/mecha/combat/gygax)
- include_subtypes = FALSE
-/datum/export/large/durand
+/datum/export/large/mech/durand
cost = 10000
unit_name = "working durand"
export_types = list(/obj/mecha/combat/durand)
- include_subtypes = FALSE
-/datum/export/large/phazon
+/datum/export/large/mech/phazon
cost = 25000 //Little over half do to needing a core
unit_name = "working phazon"
export_types = list(/obj/mecha/combat/phazon)
- include_subtypes = FALSE
-/datum/export/large/marauder
+/datum/export/large/mech/marauder
cost = 15000 //Still a Combat class mech - CC tech as well! 150% "normal" boundy price.
unit_name = "working marauder"
export_types = list(/obj/mecha/combat/marauder)
- include_subtypes = FALSE
-/datum/export/large/deathripley
+/datum/export/large/mech/deathripley
cost = 8500 //Still a "Combat class" mech - Illegal tech as well! 165% "normal" boundy price.
unit_name = "working illegally modified"
export_types = list(/obj/mecha/working/ripley/deathripley)
- include_subtypes = FALSE
-/datum/export/large/gygaxdark
+/datum/export/large/mech/gygaxdark
cost = 28500 //Still a Combat class mech - Illegal tech as well! 150% "normal" boundy price.
unit_name = "working illegally modified gygax"
export_types = list(/obj/mecha/combat/gygax/dark)
- include_subtypes = FALSE
-/datum/export/large/oldripley
+/datum/export/large/mech/oldripley
cost = 6250 //old mech - Scrap metal ! 50% "normal" boundy price.
unit_name = "working miner ripley"
export_types = list(/obj/mecha/working/ripley/mining)
- include_subtypes = FALSE
-/datum/export/large/honk
+/datum/export/large/mech/honk
cost = 12000 //Still a "Combat class" mech - Comats bordem honk!
unit_name = "working honker"
export_types = list(/obj/mecha/combat/honker)
- include_subtypes = FALSE
-/datum/export/large/reticence
+/datum/export/large/mech/reticence
cost = 12000 //Still a "Combat class" mech - Has cloking and lethal weaponds.
unit_name = "working reticence"
export_types = list(/obj/mecha/combat/reticence)
- include_subtypes = FALSE
-/datum/export/large/seraph
+/datum/export/large/mech/seraph
cost = 25500 //Still a Combat class mech - CC tech as well! 150% "normal" boundy price.
unit_name = "working seraph"
export_types = list(/obj/mecha/combat/marauder/seraph)
- include_subtypes = FALSE
-/datum/export/large/mauler
+/datum/export/large/mech/mauler
cost = 12000 //Still a Combat class mech - CC lethal weaponds.
unit_name = "working legally modified marauder"
export_types = list(/obj/mecha/combat/marauder/mauler)
- include_subtypes = FALSE
diff --git a/code/modules/cargo/exports/manifest.dm b/code/modules/cargo/exports/manifest.dm
index d03f5a46ce..60515781f9 100644
--- a/code/modules/cargo/exports/manifest.dm
+++ b/code/modules/cargo/exports/manifest.dm
@@ -80,7 +80,7 @@
// Paper work done correctly
/datum/export/paperwork_correct
- cost = 150
+ cost = 120 // finicky number 20 x 120 = 2400 per crate
k_elasticity = 0
unit_name = "correct paperwork"
export_types = list(/obj/item/folder/paperwork_correct)
diff --git a/code/modules/cargo/exports/materials.dm b/code/modules/cargo/exports/materials.dm
index 04dc76fd52..cd11660ed8 100644
--- a/code/modules/cargo/exports/materials.dm
+++ b/code/modules/cargo/exports/materials.dm
@@ -1,4 +1,5 @@
/datum/export/material
+ k_elasticity = 0
cost = 5 // Cost per MINERAL_MATERIAL_AMOUNT, which is 2000cm3 as of April 2016.
message = "cm3 of developer's tears. Please, report this on github"
var/material_id = null
@@ -27,51 +28,56 @@
return round(amount/MINERAL_MATERIAL_AMOUNT)
-// Materials. Nothing but plasma is really worth selling. Better leave it all to RnD and sell some plasma instead.
+// Materials. Selling raw can lead to a big payout but takes a lot of work for miners to get a lot. Best to craft art/rnd gear
/datum/export/material/bananium
- cost = 1000
+ cost = 500
material_id = MAT_BANANIUM
message = "cm3 of bananium"
/datum/export/material/diamond
- cost = 500
+ cost = 250
material_id = MAT_DIAMOND
message = "cm3 of diamonds"
/datum/export/material/plasma
- cost = 200
+ cost = 100
k_elasticity = 0
material_id = MAT_PLASMA
message = "cm3 of plasma"
/datum/export/material/uranium
- cost = 100
+ cost = 50
material_id = MAT_URANIUM
message = "cm3 of uranium"
/datum/export/material/gold
- cost = 125
+ cost = 60
material_id = MAT_GOLD
message = "cm3 of gold"
/datum/export/material/silver
- cost = 50
+ cost = 25
material_id = MAT_SILVER
message = "cm3 of silver"
/datum/export/material/titanium
- cost = 125
+ cost = 60
material_id = MAT_TITANIUM
message = "cm3 of titanium"
/datum/export/material/plastitanium
- cost = 325 // plasma + titanium costs
+ cost = 165 // plasma + titanium costs
material_id = MAT_TITANIUM // code can only check for one material_id; plastitanium is half plasma, half titanium
message = "cm3 of plastitanium"
-/datum/export/material/metal
+/datum/export/material/plastic
cost = 5
+ material_id = MAT_PLASTIC
+ message = "cm3 of plastic"
+
+/datum/export/material/metal
+ cost = 3
message = "cm3 of metal"
material_id = MAT_METAL
export_types = list(
@@ -79,7 +85,7 @@
/obj/item/stack/rods, /obj/item/stack/ore, /obj/item/coin)
/datum/export/material/glass
- cost = 5
+ cost = 3
message = "cm3 of glass"
material_id = MAT_GLASS
export_types = list(/obj/item/stack/sheet/glass, /obj/item/stack/ore,
diff --git a/code/modules/cargo/exports/orgains_robotics.dm b/code/modules/cargo/exports/orgains_robotics.dm
new file mode 100644
index 0000000000..924d27c1d2
--- /dev/null
+++ b/code/modules/cargo/exports/orgains_robotics.dm
@@ -0,0 +1,141 @@
+// Orgains and Robotics exports. Hearts, new lims, implants, etc.
+
+/datum/export/robotics
+ include_subtypes = FALSE
+ k_elasticity = 0 //ALWAYS worth selling upgrades
+
+/datum/export/implant
+ include_subtypes = FALSE
+ k_elasticity = 0 //ALWAYS worth selling upgrades
+
+/datum/export/orgains
+ include_subtypes = TRUE
+ k_elasticity = 0 //ALWAYS worth selling orgains
+
+/datum/export/implant/autodoc
+ cost = 150
+ unit_name = "autsurgeon"
+ export_types = list(/obj/item/autosurgeon)
+ include_subtypes = TRUE
+
+/datum/export/implant/implant
+ cost = 50
+ unit_name = "implant"
+ export_types = list(/obj/item/implant)
+ include_subtypes = TRUE
+
+/datum/export/implant/cnsreboot
+ cost = 350
+ unit_name = "anti drop implant"
+ export_types = list(/obj/item/organ/cyberimp/brain/anti_drop)
+
+/datum/export/implant/antistun
+ cost = 450
+ unit_name = "rebooter implant"
+ export_types = list(/obj/item/organ/cyberimp/brain/anti_stun)
+
+/datum/export/implant/breathtube
+ cost = 150
+ unit_name = "breath implant"
+ export_types = list(/obj/item/organ/cyberimp/mouth/breathing_tube)
+
+/datum/export/implant/hungerbgone
+ cost = 200
+ unit_name = "nutriment implant"
+ export_types = list(/obj/item/organ/cyberimp/chest/nutriment)
+
+/datum/export/implant/hungerbgoneplus
+ cost = 300
+ unit_name = "upgraded nutriment implant"
+ export_types = list(/obj/item/organ/cyberimp/chest/nutriment/plus)
+
+/datum/export/implant/reviver
+ cost = 350
+ unit_name = "reviver implant"
+ export_types = list(/obj/item/organ/cyberimp/chest/reviver)
+
+/datum/export/implant/thrusters
+ cost = 150
+ unit_name = "thrusters set implant"
+ export_types = list(/obj/item/organ/cyberimp/chest/thrusters)
+
+/datum/export/implant/thrusters
+ cost = 150
+ unit_name = "thrusters set implant"
+ export_types = list(/obj/item/organ/cyberimp/chest/thrusters)
+
+/datum/export/implant/arm
+ cost = 200
+ unit_name = "arm set implant"
+ export_types = list(/obj/item/organ/cyberimp/arm/toolset, /obj/item/organ/cyberimp/arm/surgery)
+ include_subtypes = TRUE
+
+/datum/export/implant/combatarm
+ cost = 800
+ unit_name = "combat arm set implant"
+ export_types = list(/obj/item/organ/cyberimp/arm/gun/laser, /obj/item/organ/cyberimp/arm/gun/taser, /obj/item/organ/cyberimp/arm/esword, /obj/item/organ/cyberimp/arm/medibeam, /obj/item/organ/cyberimp/arm/combat, /obj/item/organ/cyberimp/arm/flash, /obj/item/organ/cyberimp/arm/baton)
+ include_subtypes = TRUE
+
+/datum/export/orgains/heart
+ cost = 250
+ unit_name = "heart"
+ export_types = list(/obj/item/organ/heart)
+ exclude_types = list(/obj/item/organ/heart/cursed, /obj/item/organ/heart/cybernetic)
+
+/datum/export/orgains/tongue
+ cost = 75
+ unit_name = "tongue"
+ export_types = list(/obj/item/organ/tongue)
+
+/datum/export/orgains/eyes
+ cost = 50 //So many things take your eyes out anyways
+ unit_name = "eyes"
+ export_types = list(/obj/item/organ/eyes)
+ exclude_types = list(/obj/item/organ/eyes/robotic)
+
+/datum/export/orgains/stomach
+ cost = 50 //can be replaced
+ unit_name = "stomach"
+ export_types = list(/obj/item/organ/stomach)
+
+/datum/export/orgains/lungs
+ cost = 150
+ unit_name = "lungs"
+ export_types = list(/obj/item/organ/lungs)
+ exclude_types = list(/obj/item/organ/lungs/cybernetic, /obj/item/organ/lungs/cybernetic/upgraded)
+
+/datum/export/orgains/liver
+ cost = 175
+ unit_name = "liver"
+ export_types = list(/obj/item/organ/liver)
+ exclude_types = list(/obj/item/organ/liver/cybernetic, /obj/item/organ/liver/cybernetic/upgraded)
+
+/datum/export/orgains/tail //Shhh
+ cost = 500
+ unit_name = "error shipment failer"
+ export_types = list(/obj/item/organ/tail)
+
+/datum/export/orgains/vocal_cords
+ cost = 500
+ unit_name = "vocal cords"
+ export_types = list(/obj/item/organ/vocal_cords) //These are gotten via different races
+
+/datum/export/robotics/lims
+ cost = 30
+ unit_name = "robotic lim replacement"
+ export_types = list(/obj/item/bodypart/l_arm/robot, /obj/item/bodypart/r_arm/robot, /obj/item/bodypart/l_leg/robot, /obj/item/bodypart/r_leg/robot, /obj/item/bodypart/chest/robot, /obj/item/bodypart/head/robot)
+
+/datum/export/robotics/surpluse
+ cost = 40
+ unit_name = "robotic lim replacement"
+ export_types = list(/obj/item/bodypart/l_arm/robot/surplus, /obj/item/bodypart/r_arm/robot/surplus, /obj/item/bodypart/l_leg/robot/surplus, /obj/item/bodypart/r_leg/robot/surplus)
+
+/datum/export/robotics/surplus_upgraded
+ cost = 50
+ unit_name = "upgraded robotic lim replacement"
+ export_types = list(/obj/item/bodypart/l_arm/robot/surplus_upgraded, /obj/item/bodypart/r_arm/robot/surplus_upgraded, /obj/item/bodypart/l_leg/robot/surplus_upgraded, /obj/item/bodypart/r_leg/robot/surplus_upgraded)
+
+/datum/export/robotics/surgery_gear_basic
+ cost = 5
+ unit_name = "surgery tool"
+ export_types = list(/obj/item/retractor, /obj/item/hemostat, /obj/item/cautery, /obj/item/surgicaldrill, /obj/item/scalpel, /obj/item/circular_saw, /obj/item/surgical_drapes)
diff --git a/code/modules/cargo/exports/parts.dm b/code/modules/cargo/exports/parts.dm
index e6fda5f6b1..b505bb5da4 100644
--- a/code/modules/cargo/exports/parts.dm
+++ b/code/modules/cargo/exports/parts.dm
@@ -6,16 +6,96 @@
export_types = list(/obj/item/solar_assembly)
/datum/export/solar/tracker_board
- cost = 100
+ cost = 30
unit_name = "solar tracker board"
export_types = list(/obj/item/electronics/tracker)
/datum/export/solar/control_board
- cost = 150
+ cost = 75
unit_name = "solar panel control board"
export_types = list(/obj/item/circuitboard/computer/solar_control)
/datum/export/swarmer
- cost = 2000
+ cost = 500
unit_name = "deactivated alien deconstruction drone"
export_types = list(/obj/item/deactivated_swarmer)
+
+//Board
+
+/datum/export/board
+ cost = 5
+ unit_name = "circuit board"
+ export_types = list(/obj/item/circuitboard)
+ include_subtypes = TRUE
+
+/datum/export/board/SMES
+ cost = 20
+ k_elasticity = 1/2 //Only a few
+ unit_name = "smes board"
+ export_types = list(/obj/item/circuitboard/machine/smes)
+
+//Stock Parts
+
+/datum/export/subspace
+ cost = 3
+ unit_name = "subspace part"
+ export_types = list(/obj/item/stock_parts/subspace)
+ include_subtypes = TRUE
+
+/datum/export/t1
+ cost = 1
+ unit_name = "basic stock part"
+ export_types = list(/obj/item/stock_parts/capacitor, /obj/item/stock_parts/scanning_module, /obj/item/stock_parts/manipulator, /obj/item/stock_parts/micro_laser, /obj/item/stock_parts/matter_bin)
+
+/datum/export/t2
+ cost = 2
+ unit_name = "upgraded stock part"
+ export_types = list(/obj/item/stock_parts/capacitor/adv, /obj/item/stock_parts/scanning_module/adv, /obj/item/stock_parts/manipulator/nano, /obj/item/stock_parts/micro_laser/high, /obj/item/stock_parts/matter_bin/adv)
+
+/datum/export/t3
+ cost = 3
+ unit_name = "advanced stock part"
+ export_types = list(/obj/item/stock_parts/capacitor/super, /obj/item/stock_parts/scanning_module/phasic, /obj/item/stock_parts/manipulator/pico, /obj/item/stock_parts/micro_laser/ultra, /obj/item/stock_parts/matter_bin/super)
+
+/datum/export/t4
+ cost = 4
+ unit_name = "blue space stock part"
+ export_types = list(/obj/item/stock_parts/capacitor/quadratic, /obj/item/stock_parts/scanning_module/triphasic, /obj/item/stock_parts/manipulator/femto, /obj/item/stock_parts/micro_laser/quadultra, /obj/item/stock_parts/matter_bin/bluespace)
+
+//Cells
+
+/datum/export/cell
+ cost = 5
+ unit_name = "power cell"
+ export_types = list(/obj/item/stock_parts/cell)
+ include_subtypes = TRUE
+
+/datum/export/cell
+ cost = 10
+ unit_name = "upgraded power cell"
+ export_types = list(/obj/item/stock_parts/cell/upgraded, /obj/item/stock_parts/cell/upgraded/plus)
+
+/datum/export/cellhigh
+ cost = 15
+ unit_name = "high power cell"
+ export_types = list(/obj/item/stock_parts/cell/high, /obj/item/stock_parts/cell/high/plus)
+
+/datum/export/cellhyper
+ cost = 20
+ unit_name = "super-capacity power cell"
+ export_types = list(/obj/item/stock_parts/cell/super, /obj/item/stock_parts/cell/hyper)
+
+/datum/export/cellbs
+ cost = 25
+ unit_name = "bluespace power cell"
+ export_types = list(/obj/item/stock_parts/cell/bluespace)
+
+/datum/export/cellyellow
+ cost = 40
+ unit_name = "slime power cell"
+ export_types = list(/obj/item/stock_parts/cell/high/slime)
+
+/datum/export/cellyellowhyper
+ cost = 120 //Takes a lot to make and is really good
+ unit_name = "hyper slime power cell"
+ export_types = list(/obj/item/stock_parts/cell/high/slime/hypercharged)
\ No newline at end of file
diff --git a/code/modules/cargo/exports/sheets.dm b/code/modules/cargo/exports/sheets.dm
index 708eb34133..8397a7dc1f 100644
--- a/code/modules/cargo/exports/sheets.dm
+++ b/code/modules/cargo/exports/sheets.dm
@@ -1,5 +1,6 @@
/datum/export/stack
unit_name = "sheet"
+ k_elasticity = 0
/datum/export/stack/get_amount(obj/O)
var/obj/item/stack/S = O
@@ -9,47 +10,52 @@
// Hides
+/datum/export/stack/leather
+ cost = 30
+ unit_name = "leather"
+ export_types = list(/obj/item/stack/sheet/leather)
+
/datum/export/stack/skin/monkey
- cost = 50
+ cost = 30
unit_name = "monkey hide"
export_types = list(/obj/item/stack/sheet/animalhide/monkey)
/datum/export/stack/skin/human
- cost = 100
+ cost = 70
export_category = EXPORT_CONTRABAND
unit_name = "piece"
message = "of human skin"
export_types = list(/obj/item/stack/sheet/animalhide/human)
/datum/export/stack/skin/goliath_hide
- cost = 200
+ cost = 160
unit_name = "goliath hide"
export_types = list(/obj/item/stack/sheet/animalhide/goliath_hide)
/datum/export/stack/skin/cat
- cost = 150
+ cost = 120
export_category = EXPORT_CONTRABAND
unit_name = "cat hide"
export_types = list(/obj/item/stack/sheet/animalhide/cat)
/datum/export/stack/skin/corgi
- cost = 200
+ cost = 140
export_category = EXPORT_CONTRABAND
unit_name = "corgi hide"
export_types = list(/obj/item/stack/sheet/animalhide/corgi)
/datum/export/stack/skin/lizard
- cost = 150
+ cost = 50
unit_name = "lizard hide"
export_types = list(/obj/item/stack/sheet/animalhide/lizard)
/datum/export/stack/skin/gondola
- cost = 5000
+ cost = 1000
unit_name = "gondola hide"
export_types = list(/obj/item/stack/sheet/animalhide/gondola)
/datum/export/stack/skin/xeno
- cost = 500
+ cost = 300
unit_name = "alien hide"
export_types = list(/obj/item/stack/sheet/animalhide/xeno)
@@ -57,23 +63,23 @@
// For base materials, see materials.dm
/datum/export/stack/plasteel
- cost = 155 // 2000u of plasma + 2000u of metal.
+ cost = 105 // 2000u of plasma + 2000u of metal.
message = "of plasteel"
export_types = list(/obj/item/stack/sheet/plasteel)
// 1 glass + 0.5 metal, cost is rounded up.
/datum/export/stack/rglass
- cost = 8
+ cost = 6
message = "of reinforced glass"
export_types = list(/obj/item/stack/sheet/rglass)
/datum/export/stack/bscrystal
- cost = 300
+ cost = 150
message = "of bluespace crystals"
export_types = list(/obj/item/stack/sheet/bluespace_crystal)
/datum/export/stack/wood
- cost = 30
+ cost = 15
unit_name = "wood plank"
export_types = list(/obj/item/stack/sheet/mineral/wood)
@@ -93,16 +99,50 @@
unit_name = "cable piece"
export_types = list(/obj/item/stack/cable_coil)
+/datum/export/stack/cloth
+ cost = 10
+ unit_name = "sheets"
+ message = "of cloth"
+ export_types = list(/obj/item/stack/sheet/cloth)
+
+/datum/export/stack/duracloth
+ cost = 40
+ unit_name = "sheets"
+ message = "of duracloth"
+ export_types = list(/obj/item/stack/sheet/durathread)
+
// Weird Stuff
/datum/export/stack/abductor
- cost = 1000
+ cost = 400
message = "of alien alloy"
export_types = list(/obj/item/stack/sheet/mineral/abductor)
/datum/export/stack/adamantine
unit_name = "bar"
- cost = 500
+ cost = 250
message = "of adamantine"
export_types = list(/obj/item/stack/sheet/mineral/adamantine)
+/datum/export/stack/bone
+ cost = 20
+ message = "of bones"
+ export_types = list(/obj/item/stack/sheet/bone)
+
+/datum/export/stack/bronze
+ unit_name = "tiles"
+ cost = 5
+ message = "of brozne"
+ export_types = list(/obj/item/stack/tile/bronze)
+
+/datum/export/stack/brass
+ unit_name = "tiles"
+ cost = 50
+ message = "of brass"
+ export_types = list(/obj/item/stack/tile/brass)
+
+/datum/export/stack/paper
+ unit_name = "sheets"
+ cost = 30
+ message = "of paperframes"
+ export_types = list(/obj/item/stack/sheet/paperframes)
\ No newline at end of file
diff --git a/code/modules/cargo/exports/tools.dm b/code/modules/cargo/exports/tools.dm
index 9e58e4ba95..4984bfe9b9 100644
--- a/code/modules/cargo/exports/tools.dm
+++ b/code/modules/cargo/exports/tools.dm
@@ -1,5 +1,5 @@
/datum/export/toolbox
- cost = 4
+ cost = 6
unit_name = "toolbox"
export_types = list(/obj/item/storage/toolbox)
@@ -8,7 +8,80 @@
// electrical toolbox: 36cr
// robust: priceless
+// Adv tools
+
+/datum/export/gear/powerdrill
+ cost = 25
+ k_elasticity = 1/40 //Market can only take so much
+ unit_name = "power tool"
+ export_types = list(/obj/item/crowbar/power, /obj/item/screwdriver/power, \
+ /obj/item/weldingtool/experimental, /obj/item/wirecutters/power, /obj/item/wrench/power)
+ include_subtypes = TRUE
+
+/datum/export/gear/advtool
+ cost = 175
+ k_elasticity = 0 //Only known to be made by 2 station, market is hungery for it
+ unit_name = "adv tool"
+ export_types = list(/obj/item/crowbar/advanced, /obj/item/crowbar/abductor, /obj/item/screwdriver/abductor, /obj/item/screwdriver/advanced, \
+ /obj/item/weldingtool/abductor, /obj/item/weldingtool/advanced, /obj/item/wirecutters/abductor, /obj/item/wirecutters/advanced, \
+ /obj/item/wrench/abductor, /obj/item/wrench/advanced)
+ include_subtypes = TRUE
+
+// Lights/Eletronic
+
+/datum/export/lights
+ cost = 10
+ unit_name = "light fixer"
+ export_types = list(/obj/item/wallframe/light_fixture)
+ include_subtypes = TRUE
+
+/datum/export/apc_board
+ cost = 5
+ unit_name = "apc electronics"
+ export_types = list(/obj/item/electronics/apc)
+ include_subtypes = TRUE
+
+/datum/export/apc_frame
+ cost = 3
+ unit_name = "apc frame"
+ export_types = list(/obj/item/wallframe/apc)
+ include_subtypes = TRUE
+
+/datum/export/floodlights
+ cost = 15
+ unit_name = "floodlight fixer"
+ export_types = list(/obj/structure/floodlight_frame)
+ include_subtypes = TRUE
+
+/datum/export/bolbstubes
+ cost = 1 //Time
+ unit_name = "light replacement"
+ export_types = list(/obj/item/light/tube, /obj/item/light/bulb)
+
+/datum/export/lightreplacer
+ cost = 20
+ unit_name = "lightreplacer"
+ export_types = list(/obj/item/lightreplacer)
+
// Basic tools
+/datum/export/basicmining
+ cost = 20
+ unit_name = "basic mining tool"
+ export_types = list(/obj/item/pickaxe, /obj/item/pickaxe/mini, /obj/item/shovel, /obj/item/resonator)
+ include_subtypes = FALSE
+
+/datum/export/upgradedmining
+ cost = 50
+ unit_name = "mining tool"
+ export_types = list(/obj/item/pickaxe/silver, /obj/item/pickaxe/drill, /obj/item/gun/energy/plasmacutter, /obj/item/resonator/upgraded)
+ include_subtypes = FALSE
+
+/datum/export/advdmining
+ cost = 150
+ unit_name = "advanced mining tool"
+ export_types = list(/obj/item/pickaxe/diamond, /obj/item/pickaxe/drill/diamonddrill, /obj/item/pickaxe/drill/jackhammer, /obj/item/gun/energy/plasmacutter/adv)
+ include_subtypes = FALSE
+
/datum/export/screwdriver
cost = 2
unit_name = "screwdriver"
@@ -31,7 +104,6 @@
message = "of wirecutters"
export_types = list(/obj/item/wirecutters)
-
/datum/export/weldingtool
cost = 5
unit_name = "welding tool"
@@ -48,9 +120,8 @@
unit_name = "industrial welding tool"
export_types = list(/obj/item/weldingtool/largetank, /obj/item/weldingtool/hugetank)
-
/datum/export/extinguisher
- cost = 15
+ cost = 10
unit_name = "fire extinguisher"
export_types = list(/obj/item/extinguisher)
include_subtypes = FALSE
@@ -60,9 +131,8 @@
unit_name = "pocket fire extinguisher"
export_types = list(/obj/item/extinguisher/mini)
-
/datum/export/flashlight
- cost = 5
+ cost = 3
unit_name = "flashlight"
export_types = list(/obj/item/flashlight)
include_subtypes = FALSE
@@ -73,11 +143,10 @@
export_types = list(/obj/item/flashlight/flare)
/datum/export/flashlight/seclite
- cost = 10
+ cost = 5
unit_name = "seclite"
export_types = list(/obj/item/flashlight/seclite)
-
/datum/export/analyzer
cost = 5
unit_name = "analyzer"
@@ -88,14 +157,12 @@
unit_name = "t-ray scanner"
export_types = list(/obj/item/t_scanner)
-
/datum/export/radio
cost = 5
unit_name = "radio"
export_types = list(/obj/item/radio)
exclude_types = list(/obj/item/radio/mech)
-
/datum/export/rcd
cost = 100
unit_name = "rapid construction device"
@@ -111,6 +178,21 @@
unit_name = "rapid piping device"
export_types = list(/obj/item/pipe_dispenser)
+/datum/export/rld
+ cost = 150
+ unit_name = "rapid light device"
+ export_types = list(/obj/item/construction/rld)
+
+/datum/export/rped
+ cost = 100
+ unit_name = "rapid part exchange device"
+ export_types = list(/obj/item/storage/part_replacer)
+
+/datum/export/bsrped
+ cost = 200
+ unit_name = "blue space part exchange device"
+ export_types = list(/obj/item/storage/part_replacer/bluespace)
+
/datum/export/singulo //failsafe in case someone decides to ship a live singularity to CentCom without the corresponding bounty
cost = 1
unit_name = "singularity"
diff --git a/code/modules/cargo/exports/weapons.dm b/code/modules/cargo/exports/weapons.dm
index bad221c3ac..97dd9c10aa 100644
--- a/code/modules/cargo/exports/weapons.dm
+++ b/code/modules/cargo/exports/weapons.dm
@@ -3,6 +3,26 @@
/datum/export/weapon
include_subtypes = FALSE
+/datum/export/weapon/makeshift_shield
+ cost = 30
+ unit_name = "unknown shield"
+ export_types = list(/obj/item/shield/riot, /obj/item/shield/riot/roman, /obj/item/shield/riot/buckler, /obj/item/shield/makeshift)
+
+/datum/export/weapon/riot_shield
+ cost = 50
+ unit_name = "riot shield"
+ export_types = list(/obj/item/shield/riot, /obj/item/shield/riot/tower)
+
+/datum/export/weapon/riot_shield
+ cost = 70
+ unit_name = "flash shield"
+ export_types = list(/obj/item/assembly/flash/shield)
+
+/datum/export/weapon/tele_shield
+ cost = 100
+ unit_name = "tele shield"
+ export_types = list(/obj/item/shield/riot/tele, /obj/item/shield/energy)
+
/datum/export/weapon/baton
cost = 100
unit_name = "stun baton"
@@ -15,7 +35,6 @@
unit_name = "combat knife"
export_types = list(/obj/item/kitchen/knife/combat)
-
/datum/export/weapon/taser
cost = 200
unit_name = "advanced taser"
@@ -27,26 +46,25 @@
export_types = list(/obj/item/gun/energy/laser)
/datum/export/weapon/disabler
- cost = 100
+ cost = 50
unit_name = "disabler"
export_types = list(/obj/item/gun/energy/disabler)
/datum/export/weapon/energy_gun
- cost = 300
+ cost = 200
unit_name = "energy gun"
export_types = list(/obj/item/gun/energy/e_gun)
/datum/export/weapon/wt550
- cost = 300
+ cost = 130
unit_name = "WT-550 automatic rifle"
export_types = list(/obj/item/gun/ballistic/automatic/wt550)
/datum/export/weapon/shotgun
- cost = 300
+ cost = 200
unit_name = "combat shotgun"
export_types = list(/obj/item/gun/ballistic/shotgun/automatic/combat)
-
/datum/export/weapon/flashbang
cost = 5
unit_name = "flashbang grenade"
@@ -57,7 +75,6 @@
unit_name = "tear gas grenade"
export_types = list(/obj/item/grenade/chem_grenade/teargas)
-
/datum/export/weapon/flash
cost = 5
unit_name = "handheld flash"
@@ -69,3 +86,271 @@
unit_name = "pair"
message = "of handcuffs"
export_types = list(/obj/item/restraints/handcuffs)
+
+//////////////
+//RND Guns////
+//////////////
+
+/datum/export/weapon/lasercarbine
+ cost = 120
+ unit_name = "laser carbine"
+ export_types = list(/obj/item/gun/energy/laser/carbine)
+ include_subtypes = TRUE
+
+/datum/export/weapon/teslagun
+ cost = 130
+ unit_name = "tesla revolver"
+ export_types = list(/obj/item/gun/energy/tesla_revolver)
+
+/datum/export/weapon/aeg
+ cost = 200 //Endless power
+ unit_name = "advance engery gun"
+ export_types = list(/obj/item/gun/energy/e_gun/nuclear)
+
+/datum/export/weapon/deconer
+ cost = 600
+ unit_name = "deconer"
+ export_types = list(/obj/item/gun/energy/decloner)
+
+/datum/export/weapon/ntsniper
+ cost = 500
+ unit_name = "beam rifle"
+ export_types = list(/obj/item/gun/energy/beam_rifle)
+
+/datum/export/weapon/needle_gun
+ cost = 50
+ unit_name = "syringe revolver"
+ export_types = list(/obj/item/gun/syringe/rapidsyringe)
+
+/datum/export/weapon/temp_gun
+ cost = 175 //Its just smaller
+ unit_name = "small temperature gun"
+ k_elasticity = 1/5 //Its just a smaller temperature gun, easy to mass make
+ export_types = list(/obj/item/gun/energy/temperature)
+
+/datum/export/weapon/flowergun
+ cost = 100
+ unit_name = "floral somatoray"
+ export_types = list(/obj/item/gun/energy/floragun)
+
+/datum/export/weapon/xraygun
+ cost = 300 //Wall hacks
+ unit_name = "x ray gun"
+ export_types = list(/obj/item/gun/energy/xray)
+
+/datum/export/weapon/ioncarbine
+ cost = 200
+ k_elasticity = 1/5 //Its just a smaller temperature gun, easy to mass make
+ unit_name = "ion carbine"
+ export_types = list(/obj/item/gun/energy/ionrifle/carbine)
+
+/datum/export/weapon/largeebow
+ cost = 500
+ unit_name = "crossbow"
+ export_types = list(/obj/item/gun/energy/kinetic_accelerator/crossbow/large)
+
+/datum/export/weapon/largebomb
+ cost = 20
+ unit_name = "large grenade"
+ export_types = list(/obj/item/grenade/chem_grenade/large)
+
+/datum/export/weapon/gravworm
+ cost = 150
+ unit_name = "bluespace weapon"
+ export_types = list(/obj/item/gun/energy/wormhole_projector, /obj/item/gun/energy/gravity_gun)
+
+/datum/export/weapon/cryopryo
+ cost = 70
+ unit_name = "heat based grenade"
+ export_types = list(/obj/item/grenade/chem_grenade/pyro, /obj/item/grenade/chem_grenade/cryo)
+
+/datum/export/weapon/advgrenade
+ cost = 80
+ unit_name = "advanced grenade"
+ export_types = list(/obj/item/grenade/chem_grenade/adv_release)
+
+/////////////////
+//Ammo and Pins//
+/////////////////
+
+/datum/export/weapon/wtammo
+ cost = 10
+ unit_name = "WT-550 automatic rifle ammo"
+ export_types = list(/obj/item/ammo_box/magazine/wt550m9, /obj/item/ammo_box/magazine/wt550m9/wtrubber)
+
+/datum/export/weapon/wtammo/advanced
+ cost = 30
+ unit_name = "advanced WT-550 automatic rifle ammo"
+ export_types = list( /obj/item/ammo_box/magazine/wt550m9/wtap, /obj/item/ammo_box/magazine/wt550m9/wttx, /obj/item/ammo_box/magazine/wt550m9/wtic)
+
+/datum/export/weapon/mindshield
+ cost = 80
+ unit_name = "mindshield locked pin"
+ export_types = list(/obj/item/firing_pin/implant/mindshield)
+
+/datum/export/weapon/testrange
+ cost = 20
+ unit_name = "test range pin"
+ export_types = list(/obj/item/firing_pin/test_range)
+
+/datum/export/weapon/techslug
+ cost = 15
+ k_elasticity = 0
+ unit_name = "advanced shotgun shell"
+ export_types = list(/obj/item/ammo_casing/shotgun/dragonsbreath, /obj/item/ammo_casing/shotgun/meteorslug, /obj/item/ammo_casing/shotgun/pulseslug, /obj/item/ammo_casing/shotgun/frag12, /obj/item/ammo_casing/shotgun/ion, /obj/item/ammo_casing/shotgun/laserslug)
+
+/////////////////////////
+//The Traitor Sell Outs//
+/////////////////////////
+
+/datum/export/weapon/pistol
+ cost = 120
+ unit_name = "illegal firearm"
+ export_types = list(/obj/item/gun/ballistic/automatic/pistol)
+
+/datum/export/weapon/revolver
+ cost = 200
+ unit_name = "large handgun"
+ export_types = list(/obj/item/gun/ballistic/revolver/syndie)
+
+/datum/export/weapon/rocketlauncher
+ cost = 1000
+ unit_name = "rocketlauncher"
+ export_types = list(/obj/item/gun/ballistic/rocketlauncher)
+
+/datum/export/weapon/antitank
+ cost = 300
+ unit_name = "hand cannon"
+ export_types = list(/obj/item/gun/ballistic/automatic/pistol/antitank/syndicate)
+
+/datum/export/weapon/clownstuff
+ cost = 500
+ unit_name = "clown war tech"
+ export_types = list(/obj/item/pneumatic_cannon/pie/selfcharge, /obj/item/shield/energy/bananium, /obj/item/melee/transforming/energy/sword/bananium, )
+
+/datum/export/weapon/bulldog
+ cost = 400
+ unit_name = "drum loaded shotgun"
+ export_types = list(/obj/item/gun/ballistic/automatic/shotgun/bulldog)
+
+/datum/export/weapon/smg
+ cost = 350
+ unit_name = "automatic c-20r"
+ export_types = list(/obj/item/gun/ballistic/automatic/c20r)
+
+/datum/export/weapon/duelsaber
+ cost = 360 //Get it?
+ unit_name = "energy saber"
+ export_types = list(/obj/item/twohanded/dualsaber)
+
+/datum/export/weapon/esword
+ cost = 130
+ unit_name = "energy sword"
+ export_types = list(/obj/item/melee/transforming/energy/sword/cx/traitor, /obj/item/melee/transforming/energy/sword/saber)
+
+/datum/export/weapon/rapier
+ cost = 150
+ unit_name = "rapier"
+ export_types = list(/obj/item/storage/belt/sabre/rapier)
+
+/datum/export/weapon/flamer
+ cost = 20 //welder + some rods cheap
+ unit_name = "flamethrower"
+ export_types = list(/obj/item/flamethrower)
+
+/datum/export/weapon/gloves
+ cost = 90
+ unit_name = "star struck gloves"
+ export_types = list(/obj/item/clothing/gloves/rapid)
+
+/datum/export/weapon/l6
+ cost = 500
+ unit_name = "law 6 saw"
+ export_types = list(/obj/item/gun/ballistic/automatic/l6_saw)
+
+/datum/export/weapon/m90
+ cost = 400
+ unit_name = "assault class weapon"
+ export_types = list(/obj/item/gun/ballistic/automatic/m90)
+
+/datum/export/weapon/powerglove
+ cost = 100
+ unit_name = "hydraulic glove"
+ export_types = list(/obj/item/melee/powerfist)
+
+/datum/export/weapon/sniper
+ cost = 750
+ unit_name = ".50 sniper"
+ export_types = list(/obj/item/gun/ballistic/automatic/sniper_rifle/syndicate)
+
+/datum/export/weapon/ebow
+ cost = 600
+ unit_name = "mini crossbow"
+ export_types = list(/obj/item/gun/energy/kinetic_accelerator/crossbow)
+
+/datum/export/weapon/m10mm
+ cost = 10
+ unit_name = "10mm magazine"
+ export_types = list(/obj/item/ammo_box/magazine/m10mm)
+ include_subtypes = TRUE
+
+/datum/export/weapon/dj_a_bomb
+ cost = 100
+ unit_name = "40mm shell"
+ export_types = list(/obj/item/ammo_casing/a40mm)
+
+/datum/export/weapon/point50mags
+ cost = 50
+ unit_name = ".50 magazine"
+ export_types = list(/obj/item/ammo_box/magazine/sniper_rounds)
+ include_subtypes = TRUE
+
+/datum/export/weapon/smg_mag
+ cost = 45
+ unit_name = "smg magazine"
+ export_types = list(/obj/item/ammo_box/magazine/smgm45, /obj/item/ammo_box/magazine/m556)
+
+/datum/export/weapon/l6sawammo
+ cost = 60
+ unit_name = "law 6 saw ammo box"
+ export_types = list(/obj/item/ammo_box/magazine/mm195x129)
+ include_subtypes = TRUE
+
+/datum/export/weapon/rocket
+ cost = 120
+ unit_name = "rocket"
+ export_types = list(/obj/item/ammo_casing/caseless/rocket)
+ include_subtypes = TRUE
+
+/datum/export/weapon/ninemmammo
+ cost = 20
+ unit_name = "9mm ammo magazine"
+ export_types = list(/obj/item/ammo_box/magazine/pistolm9mm)
+
+/datum/export/weapon/fletcher_ammo
+ cost = 60
+ unit_name = "illegal ammo magazines"
+ export_types = list(/obj/item/ammo_box/magazine/flechette)
+ include_subtypes = TRUE
+
+/datum/export/weapon/dj_a_pizzabomb
+ cost = -6000
+ unit_name = "Repair Costs"
+ export_types = list(/obj/item/pizzabox/bomb, /obj/item/sbeacondrop/bomb)
+
+/datum/export/weapon/real_toolbox
+ cost = 600
+ unit_name = "golden toolbox"
+ export_types = list(/obj/item/storage/toolbox/gold_real)
+
+/datum/export/weapon/melee
+ cost = 30
+ unit_name = "unlisted weapon"
+ export_types = list(/obj/item/melee)
+ include_subtypes = TRUE
+
+/datum/export/weapon/gun
+ cost = 30
+ unit_name = "unlisted weapon"
+ export_types = list(/obj/item/gun)
+ include_subtypes = TRUE
\ No newline at end of file
diff --git a/code/modules/cargo/packs.dm b/code/modules/cargo/packs.dm
index 8d845badd4..4c9ddfe3bc 100644
--- a/code/modules/cargo/packs.dm
+++ b/code/modules/cargo/packs.dm
@@ -1,20 +1,20 @@
/datum/supply_pack
var/name = "Crate"
var/group = ""
- var/hidden = FALSE
- var/contraband = FALSE
+ var/hidden = FALSE //Aka emag only
+ var/contraband = FALSE //Hacking the console with a multitool
var/cost = 700 // Minimum cost, or infinite points are possible.
- var/access = FALSE
- var/access_any = FALSE
- var/list/contains = null
- var/crate_name = "crate"
+ var/access = FALSE //What access does the Crate itself need?
+ var/access_any = FALSE //Do we care about access?
+ var/list/contains = null //What items are in the crate
+ var/crate_name = "crate" //The crate that comes with each order
var/desc = ""//no desc by default
- var/crate_type = /obj/structure/closet/crate
+ var/crate_type = /obj/structure/closet/crate //what kind of crate - Locked crates needed for access locked crates
var/dangerous = FALSE // Should we message admins?
var/special = FALSE //Event/Station Goals/Admin enabled packs
var/special_enabled = FALSE
- var/DropPodOnly = FALSE//only usable by the Bluespace Drop Pod via the express cargo console
- var/admin_spawned = FALSE
+ var/DropPodOnly = FALSE //only usable by the Bluespace Drop Pod via the express cargo console
+ var/admin_spawned = FALSE //Can only an admin spawn this crate?
/datum/supply_pack/proc/generate(atom/A)
var/obj/structure/closet/crate/C = new crate_type(A)
@@ -36,2844 +36,3 @@
else
for(var/item in contains)
new item(C)
-
-// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////// Emergency ///////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/emergency
- group = "Emergency"
-
-/datum/supply_pack/emergency/vehicle
- name = "Biker Gang Kit" //TUNNEL SNAKES OWN THIS TOWN
- desc = "TUNNEL SNAKES OWN THIS TOWN. Contains an unbranded All Terrain Vehicle, and a complete gang outfit -- consists of black gloves, a menacing skull bandanna, and a SWEET leather overcoat!"
- cost = 2000
- contraband = TRUE
- contains = list(/obj/vehicle/ridden/atv,
- /obj/item/key,
- /obj/item/clothing/suit/jacket/leather/overcoat,
- /obj/item/clothing/gloves/color/black,
- /obj/item/clothing/head/soft,
- /obj/item/clothing/mask/bandana/skull)//so you can properly #cargoniabikergang
- crate_name = "Biker Kit"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/emergency/equipment
- name = "Emergency Bot/Internals Crate"
- desc = "Explosions got you down? These supplies are guaranteed to patch up holes, in stations and people alike! Comes with two floorbots, two medbots, five oxygen masks and five small oxygen tanks."
- cost = 3500
- contains = list(/mob/living/simple_animal/bot/floorbot,
- /mob/living/simple_animal/bot/floorbot,
- /mob/living/simple_animal/bot/medbot,
- /mob/living/simple_animal/bot/medbot,
- /obj/item/tank/internals/air,
- /obj/item/tank/internals/air,
- /obj/item/tank/internals/air,
- /obj/item/tank/internals/air,
- /obj/item/tank/internals/air,
- /obj/item/clothing/mask/gas,
- /obj/item/clothing/mask/gas,
- /obj/item/clothing/mask/gas,
- /obj/item/clothing/mask/gas,
- /obj/item/clothing/mask/gas)
- crate_name = "emergency crate"
- crate_type = /obj/structure/closet/crate/internals
-
-/datum/supply_pack/emergency/radiatione_emergency
- name = "Emergenc Radiation Protection Crate"
- desc = "Survive the Nuclear Apocalypse and Supermatter Engine alike with two sets of Radiation suits. Each set contains a helmet, suit, and Geiger counter. We'll even throw in a few pill bottles that are able to handles radiation and the affects of the poisoning."
- cost = 2500
- contains = list(/obj/item/clothing/head/radiation,
- /obj/item/clothing/head/radiation,
- /obj/item/clothing/suit/radiation,
- /obj/item/clothing/suit/radiation,
- /obj/item/geiger_counter,
- /obj/item/geiger_counter,
- /obj/item/storage/pill_bottle/mutarad,
- /obj/item/storage/firstaid/radbgone)
- crate_name = "radiation protection crate"
- crate_type = /obj/structure/closet/crate/radiation
-
-/datum/supply_pack/emergency/rcds
- name = "Emergency RCDs"
- desc = "Bombs going off on station? SME blown and now you need to fix the hole it left behind? Well this crate has a pare of Rcds to be able to easily fix up any problem you may have!"
- cost = 1500
- contains = list(/obj/item/construction/rcd,
- /obj/item/construction/rcd)
- crate_name = "emergency rcds"
- crate_type = /obj/structure/closet/crate/internals
-
-/datum/supply_pack/emergency/soft_suit
- name = "Emergency Space Suit "
- desc = "Is there bombs going off left and right? Is there meteors shooting around the station? Well we have two fragile space suit for emergencys as well as air and masks."
- cost = 1000
- contains = list(/obj/item/tank/internals/air,
- /obj/item/tank/internals/air,
- /obj/item/clothing/mask/gas,
- /obj/item/clothing/mask/gas,
- /obj/item/clothing/suit/space/fragile,
- /obj/item/clothing/suit/space/fragile,
- /obj/item/clothing/head/helmet/space/fragile,
- /obj/item/clothing/head/helmet/space/fragile)
- crate_name = "emergency crate"
- crate_type = /obj/structure/closet/crate/internals
-
-/datum/supply_pack/emergency/firefighting
- name = "Firefighting Crate"
- desc = "Only you can prevent station fires. Partner up with two firefighter suits, gas masks, flashlights, large oxygen tanks, extinguishers, and hardhats!"
- cost = 1000
- contains = list(/obj/item/clothing/suit/fire/firefighter,
- /obj/item/clothing/suit/fire/firefighter,
- /obj/item/clothing/mask/gas,
- /obj/item/clothing/mask/gas,
- /obj/item/flashlight,
- /obj/item/flashlight,
- /obj/item/tank/internals/oxygen/red,
- /obj/item/tank/internals/oxygen/red,
- /obj/item/extinguisher/advanced,
- /obj/item/extinguisher/advanced,
- /obj/item/clothing/head/hardhat/red,
- /obj/item/clothing/head/hardhat/red)
- crate_name = "firefighting crate"
-
-/datum/supply_pack/emergency/atmostank
- name = "Firefighting Tank Backpack"
- desc = "Mow down fires with this high-capacity fire fighting tank backpack. Requires Atmospherics access to open."
- cost = 1000
- access = ACCESS_ATMOSPHERICS
- contains = list(/obj/item/watertank/atmos)
- crate_name = "firefighting backpack crate"
- crate_type = /obj/structure/closet/crate/secure
-
-/datum/supply_pack/emergency/internals
- name = "Internals Crate"
- desc = "Master your life energy and control your breathing with three breath masks, three emergency oxygen tanks and three large air tanks."//IS THAT A
- cost = 1000
- contains = list(/obj/item/clothing/mask/gas,
- /obj/item/clothing/mask/gas,
- /obj/item/clothing/mask/gas,
- /obj/item/clothing/mask/breath,
- /obj/item/clothing/mask/breath,
- /obj/item/clothing/mask/breath,
- /obj/item/tank/internals/emergency_oxygen,
- /obj/item/tank/internals/emergency_oxygen,
- /obj/item/tank/internals/emergency_oxygen,
- /obj/item/tank/internals/air,
- /obj/item/tank/internals/air,
- /obj/item/tank/internals/air)
- crate_name = "internals crate"
- crate_type = /obj/structure/closet/crate/internals
-
-/datum/supply_pack/emergency/metalfoam
- name = "Metal Foam Grenade Crate"
- desc = "Seal up those pesky hull breaches with 14 Metal Foam Grenades."
- cost = 2000
- contains = list(/obj/item/storage/box/metalfoam,
- /obj/item/storage/box/metalfoam)
- crate_name = "metal foam grenade crate"
-
-/datum/supply_pack/emergency/syndicate
- name = "NULL_ENTRY"
- desc = "(#@&^$THIS PACKAGE CONTAINS 30TC WORTH OF SOME RANDOM SYNDICATE GEAR WE HAD LYING AROUND THE WAREHOUSE. GIVE EM HELL, OPERATIVE@&!*() "
- hidden = TRUE
- cost = 20000
- contains = list()
- crate_name = "emergency crate"
- crate_type = /obj/structure/closet/crate/internals
- dangerous = TRUE
-
-/datum/supply_pack/emergency/syndicate/fill(obj/structure/closet/crate/C)
- var/crate_value = 30
- var/list/uplink_items = get_uplink_items(SSticker.mode)
- while(crate_value)
- var/category = pick(uplink_items)
- var/item = pick(uplink_items[category])
- var/datum/uplink_item/I = uplink_items[category][item]
- if(!I.surplus_nullcrates || prob(100 - I.surplus_nullcrates))
- continue
- if(crate_value < I.cost)
- continue
- crate_value -= I.cost
- new I.item(C)
-
-/datum/supply_pack/emergency/plasma_spacesuit
- name = "Plasmaman Space Envirosuits"
- desc = "Contains two space-worthy envirosuits for Plasmamen. Order now and we'll throw in two free helmets! Requires EVA access to open."
- cost = 4000
- access = ACCESS_EVA
- contains = list(/obj/item/clothing/suit/space/eva/plasmaman,
- /obj/item/clothing/suit/space/eva/plasmaman,
- /obj/item/clothing/head/helmet/space/plasmaman,
- /obj/item/clothing/head/helmet/space/plasmaman)
- crate_name = "plasmaman EVA crate"
- crate_type = /obj/structure/closet/crate/secure
-
-/datum/supply_pack/emergency/plasmaman
- name = "Plasmaman Supply Kit"
- desc = "Keep those Plasmamen alive with two sets of Plasmaman outfits. Each set contains a plasmaman jumpsuit, internals tank, and helmet."
- cost = 2000
- contains = list(/obj/item/clothing/under/plasmaman,
- /obj/item/clothing/under/plasmaman,
- /obj/item/tank/internals/plasmaman/belt/full,
- /obj/item/tank/internals/plasmaman/belt/full,
- /obj/item/clothing/head/helmet/space/plasmaman,
- /obj/item/clothing/head/helmet/space/plasmaman)
- crate_name = "plasmaman supply kit"
-
-/datum/supply_pack/emergency/radiation
- name = "Radiation Protection Crate"
- desc = "Survive the Nuclear Apocalypse and Supermatter Engine alike with two sets of Radiation suits. Each set contains a helmet, suit, and Geiger counter. We'll even throw in a bottle of vodka and some glasses too, considering the life-expectancy of people who order this."
- cost = 1000
- contains = list(/obj/item/clothing/head/radiation,
- /obj/item/clothing/head/radiation,
- /obj/item/clothing/suit/radiation,
- /obj/item/clothing/suit/radiation,
- /obj/item/geiger_counter,
- /obj/item/geiger_counter,
- /obj/item/reagent_containers/food/drinks/bottle/vodka,
- /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass,
- /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass)
- crate_name = "radiation protection crate"
- crate_type = /obj/structure/closet/crate/radiation
-
-/datum/supply_pack/emergency/spacesuit
- name = "Space Suit Crate"
- desc = "Contains two aging suits from Space-Goodwill. Requires EVA access to open."
- cost = 3000
- access = ACCESS_EVA
- contains = list(/obj/item/clothing/suit/space,
- /obj/item/clothing/suit/space,
- /obj/item/clothing/head/helmet/space,
- /obj/item/clothing/head/helmet/space,
- /obj/item/clothing/mask/breath,
- /obj/item/clothing/mask/breath)
- crate_name = "space suit crate"
- crate_type = /obj/structure/closet/crate/secure
-
-/datum/supply_pack/emergency/spacejets
- name = "Spare EVA Jetpacks"
- desc = "Contains three EVA grade jectpaks. Requires EVA access to open."
- cost = 2000
- access = ACCESS_EVA
- contains = list(/obj/item/tank/jetpack/carbondioxide/eva,
- /obj/item/tank/jetpack/carbondioxide/eva,
- /obj/item/tank/jetpack/carbondioxide/eva)
- crate_name = "eva jetpacks crate"
- crate_type = /obj/structure/closet/crate/secure
-
-/datum/supply_pack/emergency/specialops
- name = "Special Ops Supplies"
- desc = "(*!&@#TOO CHEAP FOR THAT NULL_ENTRY, HUH OPERATIVE? WELL, THIS LITTLE ORDER CAN STILL HELP YOU OUT IN A PINCH. CONTAINS A BOX OF FIVE EMP GRENADES, THREE SMOKEBOMBS, AN INCENDIARY GRENADE, AND A \"SLEEPY PEN\" FULL OF NICE TOXINS!#@*$"
- hidden = TRUE
- cost = 2000
- contains = list(/obj/item/storage/box/emps,
- /obj/item/grenade/smokebomb,
- /obj/item/grenade/smokebomb,
- /obj/item/grenade/smokebomb,
- /obj/item/pen/sleepy,
- /obj/item/grenade/chem_grenade/incendiary)
- crate_name = "emergency crate"
- crate_type = /obj/structure/closet/crate/internals
-
-/datum/supply_pack/emergency/weedcontrol
- name = "Weed Control Crate"
- desc = "Keep those invasive species OUT. Contains a scythe, gasmask, two sprays of Plant-B-Gone, and two anti-weed chemical grenades. Warranty void if used on ambrosia. Requires Hydroponics access to open."
- cost = 1500
- access = ACCESS_HYDROPONICS
- contains = list(/obj/item/scythe,
- /obj/item/clothing/mask/gas,
- /obj/item/grenade/chem_grenade/antiweed,
- /obj/item/grenade/chem_grenade/antiweed,
- /obj/item/reagent_containers/spray/plantbgone,
- /obj/item/reagent_containers/spray/plantbgone)
- crate_name = "weed control crate"
- crate_type = /obj/structure/closet/crate/secure/hydroponics
-
-/datum/supply_pack/medical/anitvirus
- name = "Virus Containment Crate"
- desc = "Viro let out a death plague Mk II again? Someone didnt wash there hands? Old plagues born anew? Well this crate is for you! Hope you cure it before it brakes out of the station... This crate needs medical access to open and has two bio suits, a box of needles and beakers, five spaceacillin needles, and a medibot."
- cost = 3000
- access = ACCESS_MEDICAL
- contains = list(/mob/living/simple_animal/bot/medbot,
- /obj/item/clothing/head/bio_hood,
- /obj/item/clothing/head/bio_hood,
- /obj/item/clothing/suit/bio_suit,
- /obj/item/clothing/suit/bio_suit,
- /obj/item/reagent_containers/syringe/antiviral,
- /obj/item/reagent_containers/syringe/antiviral,
- /obj/item/reagent_containers/syringe/antiviral,
- /obj/item/reagent_containers/syringe/antiviral,
- /obj/item/reagent_containers/syringe/antiviral,
- /obj/item/storage/box/syringes,
- /obj/item/storage/box/beakers)
- crate_name = "virus containment unit crate"
- crate_type = /obj/structure/closet/crate/secure/plasma
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////// Security ////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/security
- group = "Security"
- access = ACCESS_SECURITY
- crate_type = /obj/structure/closet/crate/secure/gear
-
-/datum/supply_pack/security/armor
- name = "Armor Crate"
- desc = "Three vests of well-rounded, decently-protective armor. Requires Security access to open."
- cost = 1000
- contains = list(/obj/item/clothing/suit/armor/vest,
- /obj/item/clothing/suit/armor/vest,
- /obj/item/clothing/suit/armor/vest)
- crate_name = "armor crate"
-
-/datum/supply_pack/security/disabler
- name = "Disabler Crate"
- desc = "Three stamina-draining disabler weapons. Requires Security access to open."
- cost = 1500
- contains = list(/obj/item/gun/energy/disabler,
- /obj/item/gun/energy/disabler,
- /obj/item/gun/energy/disabler)
- crate_name = "disabler crate"
-
-/datum/supply_pack/security/forensics
- name = "Forensics Crate"
- desc = "Stay hot on the criminal's heels with Nanotrasen's Detective Essentials(tm). Contains a forensics scanner, six evidence bags, camera, tape recorder, white crayon, and of course, a fedora. Requires Security access to open."
- cost = 2000
- contains = list(/obj/item/detective_scanner,
- /obj/item/storage/box/evidence,
- /obj/item/camera,
- /obj/item/taperecorder,
- /obj/item/toy/crayon/white,
- /obj/item/clothing/head/fedora/det_hat)
- crate_name = "forensics crate"
-
-/datum/supply_pack/security/helmets
- name = "Helmets Crate"
- desc = "Contains three standard-issue brain buckets. Requires Security access to open."
- cost = 1000
- contains = list(/obj/item/clothing/head/helmet/sec,
- /obj/item/clothing/head/helmet/sec,
- /obj/item/clothing/head/helmet/sec)
- crate_name = "helmet crate"
-
-/datum/supply_pack/security/laser
- name = "Lasers Crate"
- desc = "Contains three lethal, high-energy laser guns. Requires Security access to open."
- cost = 2000
- contains = list(/obj/item/gun/energy/laser,
- /obj/item/gun/energy/laser,
- /obj/item/gun/energy/laser)
- crate_name = "laser crate"
-
-/datum/supply_pack/security/russianclothing
- name = "Russian Surplus Clothing"
- desc = "An old russian crate full of surplus armor that they used to use! Has two sets of bulletproff armor, a few union suits and some warm hats!"
- contraband = TRUE
- cost = 5000 // Its basicly sec suits, good boots/gloves
- contains = list(/obj/item/clothing/suit/security/officer/russian,
- /obj/item/clothing/suit/security/officer/russian,
- /obj/item/clothing/shoes/combat,
- /obj/item/clothing/shoes/combat,
- /obj/item/clothing/head/ushanka,
- /obj/item/clothing/head/ushanka,
- /obj/item/clothing/suit/armor/bulletproof,
- /obj/item/clothing/suit/armor/bulletproof,
- /obj/item/clothing/head/helmet/alt,
- /obj/item/clothing/head/helmet/alt,
- /obj/item/clothing/gloves/combat,
- /obj/item/clothing/gloves/combat,
- /obj/item/clothing/mask/gas,
- /obj/item/clothing/mask/gas)
- crate_name = "surplus russian clothing"
- crate_type = /obj/structure/closet/crate/internals
-
-/datum/supply_pack/security/russianmosin
- name = "Russian Minutemen Gear"
- desc = "An old russian Minutemen crate, comes with a full russian outfit, a mosin and a stripper clip."
- contraband = TRUE
- access = FALSE
- cost = 5000 //
- contains = list(/obj/item/clothing/suit/security/officer/russian,
- /obj/item/clothing/shoes/combat,
- /obj/item/clothing/head/ushanka,
- /obj/item/clothing/suit/armor/bulletproof,
- /obj/item/clothing/head/helmet/alt,
- /obj/item/clothing/gloves/combat,
- /obj/item/clothing/mask/gas,
- /obj/item/gun/ballistic/shotgun/boltaction,
- /obj/item/ammo_box/a762)
- crate_name = "surplus russian gear"
- crate_type = /obj/structure/closet/crate/internals
-
-/datum/supply_pack/security/sechardsuit
- name = "Sec Hardsuit"
- desc = "One Sec Hardsuit with a small air tank and mask."
- cost = 3000 // half of SWAT gear for have the armor and half the gear
- contains = list(/obj/item/clothing/suit/space/hardsuit/security,
- /obj/item/tank/internals/air,
- /obj/item/clothing/mask/gas)
- crate_name = "sec hardsuit crate"
-
-/datum/supply_pack/security/securitybarriers
- name = "Security Barrier Grenades"
- desc = "Stem the tide with four Security Barrier grenades. Requires Security access to open."
- contains = list(/obj/item/grenade/barrier,
- /obj/item/grenade/barrier,
- /obj/item/grenade/barrier,
- /obj/item/grenade/barrier)
- cost = 2000
- crate_name = "security barriers crate"
-
-/datum/supply_pack/security/securityclothes
- name = "Security Clothing Crate"
- desc = "Contains appropriate outfits for the station's private security force. Contains outfits for the Warden, Head of Security, and two Security Officers. Each outfit comes with a rank-appropriate jumpsuit, suit, and beret. Requires Security access to open."
- cost = 3000
- contains = list(/obj/item/clothing/under/rank/security/navyblue,
- /obj/item/clothing/under/rank/security/navyblue,
- /obj/item/clothing/suit/security/officer,
- /obj/item/clothing/suit/security/officer,
- /obj/item/clothing/head/beret/sec/navyofficer,
- /obj/item/clothing/head/beret/sec/navyofficer,
- /obj/item/clothing/under/rank/warden/navyblue,
- /obj/item/clothing/suit/security/warden,
- /obj/item/clothing/head/beret/sec/navywarden,
- /obj/item/clothing/under/rank/head_of_security/navyblue,
- /obj/item/clothing/suit/security/hos,
- /obj/item/clothing/head/beret/sec/navyhos)
- crate_name = "security clothing crate"
-
-/datum/supply_pack/security/supplies
- name = "Security Supplies Crate"
- desc = "Contains seven flashbangs, seven teargas grenades, six flashes, and seven handcuffs. Requires Security access to open."
- cost = 1000
- contains = list(/obj/item/storage/box/flashbangs,
- /obj/item/storage/box/teargas,
- /obj/item/storage/box/flashes,
- /obj/item/storage/box/handcuffs)
- crate_name = "security supply crate"
-
-/datum/supply_pack/security/firingpins
- name = "Standard Firing Pins Crate"
- desc = "Upgrade your arsenal with 10 standard firing pins. Requires Security access to open."
- cost = 2000
- contains = list(/obj/item/storage/box/firingpins,
- /obj/item/storage/box/firingpins)
- crate_name = "firing pins crate"
-
-/datum/supply_pack/security/justiceinbound
- name = "Standard Justice Enforcer Crate"
- desc = "This is it. The Bee's Knees. The Creme of the Crop. The Pick of the Litter. The best of the best of the best. The Crown Jewel of Nanotrasen. The Alpha and the Omega of security headwear. Guaranteed to strike fear into the hearts of each and every criminal aboard the station. Also comes with a security gasmask. Requires Security access to open."
- cost = 6000 //justice comes at a price. An expensive, noisy price.
- contraband = TRUE
- contains = list(/obj/item/clothing/head/helmet/justice,
- /obj/item/clothing/mask/gas/sechailer)
- crate_name = "security clothing crate"
-
-/datum/supply_pack/security/baton
- name = "Stun Batons Crate"
- desc = "Arm the Civil Protection Forces with three stun batons. Batteries included. Requires Security access to open."
- cost = 1000
- contains = list(/obj/item/melee/baton/loaded,
- /obj/item/melee/baton/loaded,
- /obj/item/melee/baton/loaded)
- crate_name = "stun baton crate"
-
-/datum/supply_pack/security/taser
- name = "Taser Crate"
- desc = "From the depths of stunbased combat, this order rises above, supreme. Contains three hybrid tasers, capable of firing both electrodes and disabling shots. Requires Security access to open."
- cost = 3000
- contains = list(/obj/item/gun/energy/e_gun/advtaser,
- /obj/item/gun/energy/e_gun/advtaser,
- /obj/item/gun/energy/e_gun/advtaser)
- crate_name = "taser crate"
-
-/datum/supply_pack/security/wall_flash
- name = "Wall-Mounted Flash Crate"
- desc = "Contains four wall-mounted flashes. Requires Security access to open."
- cost = 1000
- contains = list(/obj/item/storage/box/wall_flash,
- /obj/item/storage/box/wall_flash,
- /obj/item/storage/box/wall_flash,
- /obj/item/storage/box/wall_flash)
- crate_name = "wall-mounted flash crate"
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////// Armory //////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/security/armory
- group = "Armory"
- access = ACCESS_ARMORY
- crate_type = /obj/structure/closet/crate/secure/weapon
-
-/datum/supply_pack/security/armory/bulletarmor
- name = "Bulletproof Armor Crate"
- desc = "Contains three sets of bulletproof armor. Guaranteed to reduce a bullet's stopping power by over half. Requires Armory access to open."
- cost = 1500
- contains = list(/obj/item/clothing/suit/armor/bulletproof,
- /obj/item/clothing/suit/armor/bulletproof,
- /obj/item/clothing/suit/armor/bulletproof)
- crate_name = "bulletproof armor crate"
-
-/datum/supply_pack/security/armory/bullethelmets
- name = "Bulletproof Helmet Crate"
- desc = "Contains three sets of bulletproof helmets. Guaranteed to reduce a bullet's stopping power by over half. Requires Armory access to open."
- cost = 1500
- contains = list(/obj/item/clothing/head/helmet/alt,
- /obj/item/clothing/head/helmet/alt,
- /obj/item/clothing/head/helmet/alt)
- crate_name = "bulletproof helmet crate"
-
-/datum/supply_pack/security/armory/chemimp
- name = "Chemical Implants Crate"
- desc = "Contains five Remote Chemical implants. Requires Armory access to open."
- cost = 2000
- contains = list(/obj/item/storage/box/chemimp)
- crate_name = "chemical implant crate"
-
-/datum/supply_pack/security/armory/combatknives
- name = "Combat Knives Crate"
- desc = "Contains three sharpened combat knives. Each knife guaranteed to fit snugly inside any Nanotrasen-standard boot. Requires Armory access to open."
- cost = 3000
- contains = list(/obj/item/kitchen/knife/combat,
- /obj/item/kitchen/knife/combat,
- /obj/item/kitchen/knife/combat)
- crate_name = "combat knife crate"
-
-/datum/supply_pack/security/armory/ballistic
- name = "Combat Shotguns Crate"
- desc = "For when the enemy absolutely needs to be replaced with lead. Contains three Aussec-designed Combat Shotguns, with three Shotgun Bandoliers, as well as seven buchshot and 12g shotgun slugs. Requires Armory access to open."
- cost = 8000
- contains = list(/obj/item/gun/ballistic/shotgun/automatic/combat,
- /obj/item/gun/ballistic/shotgun/automatic/combat,
- /obj/item/gun/ballistic/shotgun/automatic/combat,
- /obj/item/storage/belt/bandolier,
- /obj/item/storage/belt/bandolier,
- /obj/item/storage/belt/bandolier,
- /obj/item/storage/box/lethalshot,
- /obj/item/storage/box/lethalslugs)
- crate_name = "combat shotguns crate"
-
-/datum/supply_pack/security/armory/dragnetgun
- name = "DRAGnet gun Crate"
- desc = "Contains two DRAGnet gun. A Dynamic Rapid-Apprehension of the Guilty net the revolution in law enforcement technology that YOU Want! Requires Armory access to open."
- cost = 3500
- contains = list(/obj/item/gun/energy/e_gun/dragnet,
- /obj/item/gun/energy/e_gun/dragnet)
- crate_name = "anti riot net guns crate"
-
-/datum/supply_pack/security/armory/energy
- name = "Energy Guns Crate"
- desc = "Contains three Energy Guns, capable of firing both nonlethal and lethal blasts of light. Requires Armory access to open."
- cost = 3500
- contains = list(/obj/item/gun/energy/e_gun,
- /obj/item/gun/energy/e_gun,
- /obj/item/gun/energy/e_gun)
- crate_name = "energy gun crate"
- crate_type = /obj/structure/closet/crate/secure/plasma
-
-/datum/supply_pack/security/armory/exileimp // Theres boxes in 2 lockers as well as gateway never realy being used sad
- name = "Exile Implants Crate"
- desc = "Contains five Exile implants. Requires Armory access to open."
- cost = 1000
- contains = list(/obj/item/storage/box/exileimp)
- crate_name = "exile implant crate"
-
-/datum/supply_pack/security/armory/mindshield
- name = "Mindshield Implants Crate"
- desc = "Prevent against radical thoughts with three Mindshield implants. Requires Armory access to open."
- cost = 4000
- contains = list(/obj/item/storage/lockbox/loyalty)
- crate_name = "mindshield implant crate"
-
-/datum/supply_pack/security/armory/trackingimp
- name = "Tracking Implants Crate"
- desc = "Contains four tracking implants. Requires Armory access to open."
- cost = 1000
- contains = list(/obj/item/storage/box/trackimp)
- crate_name = "tracking implant crate"
-
-/datum/supply_pack/security/armory/fire
- name = "Incendiary Weapons Crate"
- desc = "Burn, baby burn. Contains three incendiary grenades, seven incendiary slugs, three plasma canisters, and a flamethrower. Requires Brige access to open."
- cost = 1500
- access = ACCESS_HEADS
- contains = list(/obj/item/flamethrower/full,
- /obj/item/tank/internals/plasma,
- /obj/item/tank/internals/plasma,
- /obj/item/tank/internals/plasma,
- /obj/item/grenade/chem_grenade/incendiary,
- /obj/item/grenade/chem_grenade/incendiary,
- /obj/item/grenade/chem_grenade/incendiary,
- /obj/item/storage/box/fireshot)
- crate_name = "incendiary weapons crate"
- crate_type = /obj/structure/closet/crate/secure/plasma
- dangerous = TRUE
-
-/datum/supply_pack/security/armory/miniguns
- name = "Personal Miniature Energy Guns"
- desc = "Contains three miniature energy guns. Each gun has a disabler and a lethal option. Requires Armory access to open."
- cost = 5000
- contains = list(/obj/item/gun/energy/e_gun/mini,
- /obj/item/gun/energy/e_gun/mini,
- /obj/item/gun/energy/e_gun/mini)
- crate_name = "personal energy guns crate"
- crate_type = /obj/structure/closet/crate/secure/plasma
-
-/datum/supply_pack/security/armory/laserarmor
- name = "Reflector Vest Crate"
- desc = "Contains two vests of highly reflective material. Each armor piece diffuses a laser's energy by over half, as well as offering a good chance to reflect the laser entirely. Requires Armory access to open."
- cost = 2000
- contains = list(/obj/item/clothing/suit/armor/laserproof,
- /obj/item/clothing/suit/armor/laserproof)
- crate_name = "reflector vest crate"
- crate_type = /obj/structure/closet/crate/secure/plasma
-
-/datum/supply_pack/security/armory/riotarmor
- name = "Riot Armor Crate"
- desc = "Contains three sets of heavy body armor. Advanced padding protects against close-ranged weaponry, making melee attacks feel only half as potent to the user. Requires Armory access to open."
- cost = 1500
- contains = list(/obj/item/clothing/suit/armor/riot,
- /obj/item/clothing/suit/armor/riot,
- /obj/item/clothing/suit/armor/riot)
- crate_name = "riot armor crate"
-
-/datum/supply_pack/security/armory/riothelmets
- name = "Riot Helmets Crate"
- desc = "Contains three riot helmets. Requires Armory access to open."
- cost = 1500
- contains = list(/obj/item/clothing/head/helmet/riot,
- /obj/item/clothing/head/helmet/riot,
- /obj/item/clothing/head/helmet/riot)
- crate_name = "riot helmets crate"
-
-/datum/supply_pack/security/armory/riotshields
- name = "Riot Shields Crate"
- desc = "For when the greytide gets really uppity. Contains three riot shields. Requires Armory access to open."
- cost = 2000
- contains = list(/obj/item/shield/riot,
- /obj/item/shield/riot,
- /obj/item/shield/riot)
- crate_name = "riot shields crate"
-
-/datum/supply_pack/security/armory/riotshotguns
- name = "Riot Shotgun Crate"
- desc = "For when the greytide gets really uppity. Contains three riot shotguns, seven rubber shot and beanbag shells. Requires Armory access to open."
- cost = 6000
- contains = list(/obj/item/gun/ballistic/shotgun/riot,
- /obj/item/gun/ballistic/shotgun/riot,
- /obj/item/gun/ballistic/shotgun/riot,
- /obj/item/storage/box/rubbershot,
- /obj/item/storage/box/beanbag)
- crate_name = "riot shotgun crate"
-
-/datum/supply_pack/security/armory/swat
- name = "SWAT Crate"
- desc = "Contains two fullbody sets of tough, fireproof, pressurized suits designed in a joint effort by IS-ERI and Nanotrasen. Each set contains a suit, helmet, mask, combat belt, and combat gloves. Requires Armory access to open."
- cost = 6000
- contains = list(/obj/item/clothing/head/helmet/swat/nanotrasen,
- /obj/item/clothing/head/helmet/swat/nanotrasen,
- /obj/item/clothing/suit/space/swat,
- /obj/item/clothing/suit/space/swat,
- /obj/item/clothing/mask/gas/sechailer/swat,
- /obj/item/clothing/mask/gas/sechailer/swat,
- /obj/item/storage/belt/military/assault,
- /obj/item/storage/belt/military/assault,
- /obj/item/clothing/gloves/combat,
- /obj/item/clothing/gloves/combat)
- crate_name = "swat crate"
-
-/datum/supply_pack/security/armory/swattasers //Lesser AEG tbh
- name = "SWAT tatical tasers Crate"
- desc = "Contains two tactical energy gun, these guns are able to tase, disable and lethal as well as hold a seclight. Requires Armory access to open."
- cost = 8000
- contains = list(/obj/item/gun/energy/e_gun/stun,
- /obj/item/gun/energy/e_gun/stun)
- crate_name = "swat taser crate"
-
-/datum/supply_pack/security/armory/woodstock
- name = "Classic WoodStock Shotguns Crate"
- desc = "Contains three rustic, pumpaction shotguns. Requires Armory access to open."
- cost = 3500
- contains = list(/obj/item/gun/ballistic/shotgun,
- /obj/item/gun/ballistic/shotgun,
- /obj/item/gun/ballistic/shotgun)
- crate_name = "woodstock shotguns crate"
-
-/datum/supply_pack/security/armory/wt550
- name = "WT-550 Semi-Auto Rifle Crate"
- desc = "Contains two high-powered, semiautomatic rifles chambered in 4.6x30mm. Requires Armory access to open."
- cost = 3500
- contains = list(/obj/item/gun/ballistic/automatic/wt550,
- /obj/item/gun/ballistic/automatic/wt550)
- crate_name = "auto rifle crate"
-
-/datum/supply_pack/security/armory/wt550ammo
- name = "WT-550 Semi-Auto SMG Ammo Crate"
- desc = "Contains four 20-round magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open."
- cost = 2500
- contains = list(/obj/item/ammo_box/magazine/wt550m9,
- /obj/item/ammo_box/magazine/wt550m9,
- /obj/item/ammo_box/magazine/wt550m9,
- /obj/item/ammo_box/magazine/wt550m9)
- crate_name = "auto rifle ammo crate"
-
-/datum/supply_pack/security/armory/wt550ammo_nonlethal // Takes around 12 shots to stun crit someone
- name = "WT-550 Semi-Auto SMG Non-Lethal Ammo Crate"
- desc = "Contains four 20-round magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open."
- cost = 1500
- contains = list(/obj/item/ammo_box/magazine/wt550m9/wtrubber,
- /obj/item/ammo_box/magazine/wt550m9/wtrubber,
- /obj/item/ammo_box/magazine/wt550m9/wtrubber,
- /obj/item/ammo_box/magazine/wt550m9/wtrubber)
- crate_name = "auto rifle ammo crate"
-
-/datum/supply_pack/security/armory/wt550ammo_special
- name = "WT-550 Semi-Auto SMG Special Ammo Crate"
- desc = "Contains 2 20-round Armour Piercing and Incendiary magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open."
- cost = 4500
- contains = list(/obj/item/ammo_box/magazine/wt550m9/wtap,
- /obj/item/ammo_box/magazine/wt550m9/wtap,
- /obj/item/ammo_box/magazine/wt550m9/wtic,
- /obj/item/ammo_box/magazine/wt550m9/wtic)
- crate_name = "auto rifle ammo crate"
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////// Engineering /////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/engineering
- group = "Engineering"
- crate_type = /obj/structure/closet/crate/engineering
-
-/datum/supply_pack/engineering/shieldgen
- name = "Anti-breach Shield Projector Crate"
- desc = "Hull breaches again? Say no more with the Nanotrasen Anti-Breach Shield Projector! Uses forcefield technology to keep the air in, and the space out. Contains two shield projectors."
- cost = 2500
- contains = list(/obj/machinery/shieldgen,
- /obj/machinery/shieldgen)
- crate_name = "anti-breach shield projector crate"
-
-/datum/supply_pack/engineering/conveyor
- name = "Conveyor Assembly Crate"
- desc = "Keep production moving along with six conveyor belts. Conveyor switch included. If you have any questions, check out the enclosed instruction book."
- cost = 750
- contains = list(/obj/item/conveyor_construct,
- /obj/item/conveyor_construct,
- /obj/item/conveyor_construct,
- /obj/item/conveyor_construct,
- /obj/item/conveyor_construct,
- /obj/item/conveyor_construct,
- /obj/item/conveyor_switch_construct,
- /obj/item/paper/guides/conveyor)
- crate_name = "conveyor assembly crate"
-
-/datum/supply_pack/engineering/engiequipment
- name = "Engineering Gear Crate"
- desc = "Gear up with three toolbelts, high-visibility vests, welding helmets, hardhats, and two pairs of meson goggles!"
- cost = 1300
- contains = list(/obj/item/storage/belt/utility,
- /obj/item/storage/belt/utility,
- /obj/item/storage/belt/utility,
- /obj/item/clothing/suit/hazardvest,
- /obj/item/clothing/suit/hazardvest,
- /obj/item/clothing/suit/hazardvest,
- /obj/item/clothing/head/welding,
- /obj/item/clothing/head/welding,
- /obj/item/clothing/head/welding,
- /obj/item/clothing/head/hardhat,
- /obj/item/clothing/head/hardhat,
- /obj/item/clothing/head/hardhat,
- /obj/item/clothing/glasses/meson/engine,
- /obj/item/clothing/glasses/meson/engine)
- crate_name = "engineering gear crate"
-
-/datum/supply_pack/engineering/engihardsuit
- name = "Engineering Hardsuit"
- desc = "Poly 'Who stole all the hardsuits!' Well now you can get more hardsuits if needed! NOTE ONE HARDSUIT IS IN THIS CRATE, as well as one air tank and mask!"
- cost = 2500
- contains = list(/obj/item/tank/internals/air,
- /obj/item/clothing/mask/gas,
- /obj/item/clothing/suit/space/hardsuit/engine)
- crate_name = "engineering hardsuit"
-
-/datum/supply_pack/engineering/atmoshardsuit
- name = "Atmospherics Hardsuit"
- desc = "Too many techs and not enough hardsuits? Time to buy some more! Comes with gas mask and air tank. Ask the CE to open."
- cost = 5000
- access = ACCESS_CE
- contains = list(/obj/item/tank/internals/air,
- /obj/item/clothing/mask/gas,
- /obj/item/clothing/suit/space/hardsuit/engine/atmos)
- crate_name = "atmospherics hardsuit"
- crate_type = /obj/structure/closet/crate/secure/engineering
-
-/datum/supply_pack/engineering/industrialrcd
- name = "Industrial RCD"
- desc = "A industrial RCD in case the station has gone through more then one meteor storm and the CE needs to bring out the somthing a bit more reliable. Dose not contain spare ammo for the industrial RCD or any other RCD modles."
- cost = 4500
- access = ACCESS_CE
- contains = list(/obj/item/construction/rcd/industrial)
- crate_name = "industrial rcd"
- crate_type = /obj/structure/closet/crate/secure/engineering
-
-/datum/supply_pack/engineering/powergamermitts
- name = "Insulated Gloves Crate"
- desc = "The backbone of modern society. Barely ever ordered for actual engineering. Contains three insulated gloves."
- cost = 2000 //Made of pure-grade bullshittinium
- contains = list(/obj/item/clothing/gloves/color/yellow,
- /obj/item/clothing/gloves/color/yellow,
- /obj/item/clothing/gloves/color/yellow)
- crate_name = "insulated gloves crate"
- crate_type = /obj/structure/closet/crate/engineering/electrical
-
-/obj/item/stock_parts/cell/inducer_supply
- maxcharge = 5000
- charge = 5000
-
-/datum/supply_pack/engineering/inducers
- name = "NT-75 Electromagnetic Power Inducers Crate"
- desc = "No rechargers? No problem, with the NT-75 EPI, you can recharge any standard cell-based equipment anytime, anywhere. Contains two Inducers."
- cost = 2000
- contains = list(/obj/item/inducer/sci {cell_type = /obj/item/stock_parts/cell/inducer_supply; opened = 0}, /obj/item/inducer/sci {cell_type = /obj/item/stock_parts/cell/inducer_supply; opened = 0}) //FALSE doesn't work in modified type paths apparently.
- crate_name = "inducer crate"
- crate_type = /obj/structure/closet/crate/engineering/electrical
-
-/datum/supply_pack/engineering/pacman
- name = "P.A.C.M.A.N Generator Crate"
- desc = "Engineers can't set up the engine? Not an issue for you, once you get your hands on this P.A.C.M.A.N. Generator! Takes in plasma and spits out sweet sweet energy."
- cost = 2500
- contains = list(/obj/machinery/power/port_gen/pacman)
- crate_name = "PACMAN generator crate"
- crate_type = /obj/structure/closet/crate/engineering/electrical
-
-/datum/supply_pack/engineering/power
- name = "Power Cell Crate"
- desc = "Looking for power overwhelming? Look no further. Contains three high-voltage power cells."
- cost = 1000
- contains = list(/obj/item/stock_parts/cell/high,
- /obj/item/stock_parts/cell/high,
- /obj/item/stock_parts/cell/high)
- crate_name = "power cell crate"
- crate_type = /obj/structure/closet/crate/engineering/electrical
-
-/datum/supply_pack/engineering/shuttle_engine
- name = "Shuttle Engine Crate"
- desc = "Through advanced bluespace-shenanigans, our engineers have managed to fit an entire shuttle engine into one tiny little crate. Requires CE access to open."
- cost = 5000
- access = ACCESS_CE
- contains = list(/obj/structure/shuttle/engine/propulsion/burst/cargo)
- crate_name = "shuttle engine crate"
- crate_type = /obj/structure/closet/crate/secure/engineering
- special = TRUE
-
-/datum/supply_pack/engineering/tools
- name = "Toolbox Crate"
- desc = "Any robust spaceman is never far from their trusty toolbox. Contains three electrical toolboxes and three mechanical toolboxes."
- contains = list(/obj/item/storage/toolbox/electrical,
- /obj/item/storage/toolbox/electrical,
- /obj/item/storage/toolbox/electrical,
- /obj/item/storage/toolbox/mechanical,
- /obj/item/storage/toolbox/mechanical,
- /obj/item/storage/toolbox/mechanical)
- cost = 1000
- crate_name = "toolbox crate"
-
-/datum/supply_pack/engineering/bsa
- name = "Bluespace Artillery Parts"
- desc = "The pride of Nanotrasen Naval Command. The legendary Bluespace Artillery Cannon is a devastating feat of human engineering and testament to wartime determination. Highly advanced research is required for proper construction. "
- cost = 15000
- special = TRUE
- contains = list(/obj/item/circuitboard/machine/bsa/front,
- /obj/item/circuitboard/machine/bsa/middle,
- /obj/item/circuitboard/machine/bsa/back,
- /obj/item/circuitboard/computer/bsa_control
- )
- crate_name= "bluespace artillery parts crate"
-
-/datum/supply_pack/engineering/dna_vault
- name = "DNA Vault Parts"
- desc = "Secure the longevity of the current state of humanity within this massive library of scientific knowledge, capable of granting superhuman powers and abilities. Highly advanced research is required for proper construction. Also contains five DNA probes."
- cost = 12000
- special = TRUE
- contains = list(
- /obj/item/circuitboard/machine/dna_vault,
- /obj/item/dna_probe,
- /obj/item/dna_probe,
- /obj/item/dna_probe,
- /obj/item/dna_probe,
- /obj/item/dna_probe
- )
- crate_name= "dna vault parts crate"
-
-/datum/supply_pack/engineering/dna_probes
- name = "DNA Vault Samplers"
- desc = "Contains five DNA probes for use in the DNA vault."
- cost = 3000
- special = TRUE
- contains = list(/obj/item/dna_probe,
- /obj/item/dna_probe,
- /obj/item/dna_probe,
- /obj/item/dna_probe,
- /obj/item/dna_probe
- )
- crate_name= "dna samplers crate"
-
-
-/datum/supply_pack/engineering/shield_sat
- name = "Shield Generator Satellite"
- desc = "Protect the very existence of this station with these Anti-Meteor defenses. Contains three Shield Generator Satellites."
- cost = 4000
- contains = list(
- /obj/machinery/satellite/meteor_shield,
- /obj/machinery/satellite/meteor_shield,
- /obj/machinery/satellite/meteor_shield
- )
- crate_name= "shield sat crate"
-
-/datum/supply_pack/engineering/shield_sat_control
- name = "Shield System Control Board"
- desc = "A control system for the Shield Generator Satellite system."
- cost = 4000
- contains = list(/obj/item/circuitboard/computer/sat_control)
- crate_name= "shield control board crate"
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////// Engine Construction /////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/engine
- group = "Engine Construction"
- crate_type = /obj/structure/closet/crate/engineering
-
-/datum/supply_pack/engine/am_jar
- name = "Antimatter Containment Jar Crate"
- desc = "Two Antimatter containment jars stuffed into a single crate."
- cost = 2000
- contains = list(/obj/item/am_containment,
- /obj/item/am_containment)
- crate_name = "antimatter jar crate"
-
-/datum/supply_pack/engine/am_core
- name = "Antimatter Control Crate"
- desc = "The brains of the Antimatter engine, this device is sure to teach the station's powergrid the true meaning of real power."
- cost = 5000
- contains = list(/obj/machinery/power/am_control_unit)
- crate_name = "antimatter control crate"
-
-/datum/supply_pack/engine/am_shielding
- name = "Antimatter Shielding Crate"
- desc = "Contains ten Antimatter shields, somehow crammed into a crate."
- cost = 2000
- contains = list(/obj/item/am_shielding_container,
- /obj/item/am_shielding_container,
- /obj/item/am_shielding_container,
- /obj/item/am_shielding_container,
- /obj/item/am_shielding_container,
- /obj/item/am_shielding_container,
- /obj/item/am_shielding_container,
- /obj/item/am_shielding_container,
- /obj/item/am_shielding_container,
- /obj/item/am_shielding_container) //10 shields: 3x3 containment and a core
- crate_name = "antimatter shielding crate"
-
-/datum/supply_pack/engine/emitter
- name = "Emitter Crate"
- desc = "Useful for powering forcefield generators while destroying locked crates and intruders alike. Contains two high-powered energy emitters. Requires CE access to open."
- cost = 1500
- access = ACCESS_CE
- contains = list(/obj/machinery/power/emitter,
- /obj/machinery/power/emitter)
- crate_name = "emitter crate"
- crate_type = /obj/structure/closet/crate/secure/engineering
- dangerous = TRUE
-
-/datum/supply_pack/engine/field_gen
- name = "Field Generator Crate"
- desc = "Typically the only thing standing between the station and a messy death. Powered by emitters. Contains two field generators."
- cost = 1500
- contains = list(/obj/machinery/field/generator,
- /obj/machinery/field/generator)
- crate_name = "field generator crate"
-
-/datum/supply_pack/engine/grounding_rods
- name = "Grounding Rod Crate"
- desc = "Four grounding rods guaranteed to keep any uppity tesla's lightning under control."
- cost = 1700
- contains = list(/obj/machinery/power/grounding_rod,
- /obj/machinery/power/grounding_rod,
- /obj/machinery/power/grounding_rod,
- /obj/machinery/power/grounding_rod)
- crate_name = "grounding rod crate"
- crate_type = /obj/structure/closet/crate/engineering/electrical
-
-/datum/supply_pack/engine/mason
- name = "M.A.S.O.N RIG Crate"
- desc = "The rare M.A.S.O.N RIG. Requires CE access to open."
- cost = 15000
- access = ACCESS_CE
- contains = list(/obj/item/clothing/suit/space/hardsuit/ancient/mason)
- crate_name = "M.A.S.O.N Rig"
- crate_type = /obj/structure/closet/crate/secure/engineering
-
-/datum/supply_pack/engine/PA
- name = "Particle Accelerator Crate"
- desc = "A supermassive black hole or hyper-powered teslaball are the perfect way to spice up any party! This \"My First Apocalypse\" kit contains everything you need to build your own Particle Accelerator! Ages 10 and up."
- cost = 3000
- contains = list(/obj/structure/particle_accelerator/fuel_chamber,
- /obj/machinery/particle_accelerator/control_box,
- /obj/structure/particle_accelerator/particle_emitter/center,
- /obj/structure/particle_accelerator/particle_emitter/left,
- /obj/structure/particle_accelerator/particle_emitter/right,
- /obj/structure/particle_accelerator/power_box,
- /obj/structure/particle_accelerator/end_cap)
- crate_name = "particle accelerator crate"
-
-/datum/supply_pack/engine/collector
- name = "Radiation Collector Crate"
- desc = "Contains three radiation collectors. Useful for collecting energy off nearby Supermatter Crystals, Singularities or Teslas!"
- cost = 2500
- contains = list(/obj/machinery/power/rad_collector,
- /obj/machinery/power/rad_collector,
- /obj/machinery/power/rad_collector)
- crate_name = "collector crate"
-
-/datum/supply_pack/engine/sing_gen
- name = "Singularity Generator Crate"
- desc = "The key to unlocking the power of Lord Singuloth. Particle Accelerator not included."
- cost = 5000
- contains = list(/obj/machinery/the_singularitygen)
- crate_name = "singularity generator crate"
-
-/datum/supply_pack/engine/solar
- name = "Solar Panel Crate"
- desc = "Go green with this DIY advanced solar array. Contains twenty one solar assemblies, a solar-control circuit board, and tracker. If you have any questions, please check out the enclosed instruction book."
- cost = 2000
- contains = list(/obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/solar_assembly,
- /obj/item/circuitboard/computer/solar_control,
- /obj/item/electronics/tracker,
- /obj/item/paper/guides/jobs/engi/solars)
- crate_name = "solar panel crate"
- crate_type = /obj/structure/closet/crate/engineering/electrical
-
-/datum/supply_pack/engine/supermatter_shard
- name = "Supermatter Shard Crate"
- desc = "The power of the heavens condensed into a single crystal. Requires CE access to open."
- cost = 10000
- access = ACCESS_CE
- contains = list(/obj/machinery/power/supermatter_crystal/shard)
- crate_name = "supermatter shard crate"
- crate_type = /obj/structure/closet/crate/secure/engineering
- dangerous = TRUE
-
-/datum/supply_pack/engine/tesla_coils
- name = "Tesla Coil Crate"
- desc = "Whether it's high-voltage executions, creating research points, or just plain old power generation: This pack of four Tesla coils can do it all!"
- cost = 2500
- contains = list(/obj/machinery/power/tesla_coil,
- /obj/machinery/power/tesla_coil,
- /obj/machinery/power/tesla_coil,
- /obj/machinery/power/tesla_coil)
- crate_name = "tesla coil crate"
- crate_type = /obj/structure/closet/crate/engineering/electrical
-
-/datum/supply_pack/engine/tesla_gen
- name = "Tesla Generator Crate"
- desc = "The key to unlocking the power of the Tesla energy ball. Particle Accelerator not included."
- cost = 5000
- contains = list(/obj/machinery/the_singularitygen/tesla)
- crate_name = "tesla generator crate"
-
-//////////////////////////////////////////////////////////////////////////////
-/////////////////////// Canisters & Materials ////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/materials
- group = "Canisters & Materials"
-
-/datum/supply_pack/materials/cardboard50
- name = "50 Cardboard Sheets"
- desc = "Create a bunch of boxes."
- cost = 1000
- contains = list(/obj/item/stack/sheet/cardboard/fifty)
- crate_name = "cardboard sheets crate"
-
-/datum/supply_pack/materials/glass50
- name = "50 Glass Sheets"
- desc = "Let some nice light in with fifty glass sheets!"
- cost = 1000
- contains = list(/obj/item/stack/sheet/glass/fifty)
- crate_name = "glass sheets crate"
-
-/datum/supply_pack/materials/metal50
- name = "50 Metal Sheets"
- desc = "Any construction project begins with a good stack of fifty metal sheets!"
- cost = 1000
- contains = list(/obj/item/stack/sheet/metal/fifty)
- crate_name = "metal sheets crate"
-
-/datum/supply_pack/materials/plasteel20
- name = "20 Plasteel Sheets"
- desc = "Reinforce the station's integrity with twenty plasteel sheets!"
- cost = 7500
- contains = list(/obj/item/stack/sheet/plasteel/twenty)
- crate_name = "plasteel sheets crate"
-
-/datum/supply_pack/materials/plasteel50
- name = "50 Plasteel Sheets"
- desc = "For when you REALLY have to reinforce something."
- cost = 16500
- contains = list(/obj/item/stack/sheet/plasteel/fifty)
- crate_name = "plasteel sheets crate"
-
-/datum/supply_pack/materials/plastic50
- name = "50 Plastic Sheets"
- desc = "Build a limitless amount of toys with fifty plastic sheets!"
- cost = 1000
- contains = list(/obj/item/stack/sheet/plastic/fifty)
- crate_name = "plastic sheets crate"
-
-/datum/supply_pack/materials/sandstone30
- name = "30 Sandstone Blocks"
- desc = "Neither sandy nor stoney, these thirty blocks will still get the job done."
- cost = 1000
- contains = list(/obj/item/stack/sheet/mineral/sandstone/thirty)
- crate_name = "sandstone blocks crate"
-
-/datum/supply_pack/materials/wood50
- name = "50 Wood Planks"
- desc = "Turn cargo's boring metal groundwork into beautiful panelled flooring and much more with fifty wooden planks!"
- cost = 2000
- contains = list(/obj/item/stack/sheet/mineral/wood/fifty)
- crate_name = "wood planks crate"
-
-/datum/supply_pack/materials/rcdammo
- name = "Spare RDC ammo"
- desc = "This crate contains sixteen RCD ammo packs, to help with any holes or projects people mite be working on."
- cost = 3750
- contains = list(/obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo,
- /obj/item/rcd_ammo)
- crate_name = "rcd ammo"
-
-/datum/supply_pack/materials/bz
- name = "BZ Canister Crate"
- desc = "Contains a canister of BZ. Requires Toxins access to open."
- cost = 7500 // Costs 3 credits more than what you can get for selling it.
- access = ACCESS_TOX_STORAGE
- contains = list(/obj/machinery/portable_atmospherics/canister/bz)
- crate_name = "BZ canister crate"
- crate_type = /obj/structure/closet/crate/secure/science
-
-/datum/supply_pack/materials/carbon_dio
- name = "Carbon Dioxide Canister"
- desc = "Contains a canister of Carbon Dioxide."
- cost = 3000
- contains = list(/obj/machinery/portable_atmospherics/canister/carbon_dioxide)
- crate_name = "carbon dioxide canister crate"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/materials/nitrogen
- name = "Nitrogen Canister"
- desc = "Contains a canister of Nitrogen."
- cost = 2000
- contains = list(/obj/machinery/portable_atmospherics/canister/nitrogen)
- crate_name = "nitrogen canister crate"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/materials/nitrous_oxide_canister
- name = "Nitrous Oxide Canister"
- desc = "Contains a canister of Nitrous Oxide. Requires Atmospherics access to open."
- cost = 3000
- access = ACCESS_ATMOSPHERICS
- contains = list(/obj/machinery/portable_atmospherics/canister/nitrous_oxide)
- crate_name = "nitrous oxide canister crate"
- crate_type = /obj/structure/closet/crate/secure
-
-/datum/supply_pack/materials/oxygen
- name = "Oxygen Canister"
- desc = "Contains a canister of Oxygen. Canned in Druidia."
- cost = 1500
- contains = list(/obj/machinery/portable_atmospherics/canister/oxygen)
- crate_name = "oxygen canister crate"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/materials/water_vapor
- name = "Water Vapor Canister"
- desc = "Contains a canister of Water Vapor. I swear to god if you open this in the halls..."
- cost = 2500
- contains = list(/obj/machinery/portable_atmospherics/canister/water_vapor)
- crate_name = "water vapor canister crate"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/materials/fueltank
- name = "Fuel Tank Crate"
- desc = "Contains a welding fuel tank. Caution, highly flammable."
- cost = 800
- contains = list(/obj/structure/reagent_dispensers/fueltank)
- crate_name = "fuel tank crate"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/materials/watertank
- name = "Water Tank Crate"
- desc = "Contains a tank of dihydrogen monoxide... sounds dangerous."
- cost = 600
- contains = list(/obj/structure/reagent_dispensers/watertank)
- crate_name = "water tank crate"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/materials/foamtank
- name = "Firefighting Foam Tank Crate"
- desc = "Contains a tank of firefighting foam. Also known as \"plasmaman's bane\"."
- cost = 1500
- contains = list(/obj/structure/reagent_dispensers/foamtank)
- crate_name = "foam tank crate"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/materials/hightank
- name = "Large Water Tank Crate"
- desc = "Contains a high-capacity water tank. Useful for botany or other service jobs."
- cost = 1200
- contains = list(/obj/structure/reagent_dispensers/watertank/high)
- crate_name = "high-capacity water tank crate"
- crate_type = /obj/structure/closet/crate/large
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////// Medical /////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/medical
- group = "Medical"
- crate_type = /obj/structure/closet/crate/medical
-
-/datum/supply_pack/medical/firstaidbruises
- name = "Bruise Treatment Kit Crate"
- desc = "Contains three first aid kits focused on healing bruises and broken bones."
- cost = 1000
- contains = list(/obj/item/storage/firstaid/brute,
- /obj/item/storage/firstaid/brute,
- /obj/item/storage/firstaid/brute)
- crate_name = "brute treatment kit crate"
-
-/datum/supply_pack/medical/firstaidburns
- name = "Burn Treatment Kit Crate"
- desc = "Contains three first aid kits focused on healing severe burns."
- cost = 1000
- contains = list(/obj/item/storage/firstaid/fire,
- /obj/item/storage/firstaid/fire,
- /obj/item/storage/firstaid/fire)
- crate_name = "burn treatment kit crate"
-
-/datum/supply_pack/medical/bloodpacks
- name = "Blood Pack Variety Crate"
- desc = "Contains eight different blood packs for reintroducing blood to patients."
- cost = 3000
- contains = list(/obj/item/reagent_containers/blood,
- /obj/item/reagent_containers/blood,
- /obj/item/reagent_containers/blood/APlus,
- /obj/item/reagent_containers/blood/AMinus,
- /obj/item/reagent_containers/blood/BPlus,
- /obj/item/reagent_containers/blood/BMinus,
- /obj/item/reagent_containers/blood/OPlus,
- /obj/item/reagent_containers/blood/OMinus,
- /obj/item/reagent_containers/blood/lizard)
- crate_name = "blood freezer"
- crate_type = /obj/structure/closet/crate/freezer
-
-/datum/supply_pack/medical/defibs
- name = "Defibrillator Crate"
- desc = "Contains two defibrillators for bringing the recently deceased back to life."
- cost = 2500
- contains = list(/obj/item/defibrillator/loaded,
- /obj/item/defibrillator/loaded)
- crate_name = "defibrillator crate"
-
-/datum/supply_pack/medical/firstaid
- name = "First Aid Kit Crate"
- desc = "Contains four first aid kits for healing most types of wounds."
- cost = 1000
- contains = list(/obj/item/storage/firstaid/regular,
- /obj/item/storage/firstaid/regular,
- /obj/item/storage/firstaid/regular,
- /obj/item/storage/firstaid/regular)
- crate_name = "first aid kit crate"
-
-/datum/supply_pack/medical/iv_drip
- name = "IV Drip Crate"
- desc = "Contains a single IV drip stand for intravenous delivery."
- cost = 700
- contains = list(/obj/machinery/iv_drip)
- crate_name = "iv drip crate"
-
-/datum/supply_pack/science/adv_surgery_tools
- name = "Med-Co Advanced surgery tools"
- desc = "A full set of Med-Co advanced surgery tools, this crate also comes with a spay of synth flesh as well as a can of . Requires Surgery access to open."
- cost = 5000
- access = ACCESS_SURGERY
- contains = list(/obj/item/storage/belt/medical/surgery_belt_adv,
- /obj/item/reagent_containers/medspray/synthflesh,
- /obj/item/reagent_containers/medspray/sterilizine)
- crate_name = "medco newest surgery tools"
- crate_type = /obj/structure/closet/crate/medical
-
-/datum/supply_pack/medical/medicalhardsuit
- name = "Medical Hardsuit"
- desc = "Got people being spaced left and right? Hole in the same room as the dead body of Hos or cap? Fear not, now you can buy one medical hardsuit with a mask and air tank to save your fellow crewmembers."
- cost = 2500
- contains = list(/obj/item/tank/internals/air,
- /obj/item/clothing/mask/gas,
- /obj/item/clothing/suit/space/hardsuit/medical)
- crate_name = "medical hardsuit"
-
-/datum/supply_pack/medical/supplies
- name = "Medical Supplies Crate"
- desc = "Contains seven beakers, syringes, and bodybags. Three morphine bottles, four insulin pills. Two charcoal bottles, epinephrine bottles, antitoxin bottles, and large beakers. Finally, a single roll of medical gauze, as well as a bottle of stimulant pills for long, hard work days. German doctor not included."
- cost = 2500
- contains = list(/obj/item/reagent_containers/glass/bottle/charcoal,
- /obj/item/reagent_containers/glass/bottle/charcoal,
- /obj/item/reagent_containers/glass/bottle/epinephrine,
- /obj/item/reagent_containers/glass/bottle/epinephrine,
- /obj/item/reagent_containers/glass/bottle/morphine,
- /obj/item/reagent_containers/glass/bottle/morphine,
- /obj/item/reagent_containers/glass/bottle/morphine,
- /obj/item/reagent_containers/glass/bottle/toxin,
- /obj/item/reagent_containers/glass/bottle/toxin,
- /obj/item/reagent_containers/glass/beaker/large,
- /obj/item/reagent_containers/glass/beaker/large,
- /obj/item/reagent_containers/pill/insulin,
- /obj/item/reagent_containers/pill/insulin,
- /obj/item/reagent_containers/pill/insulin,
- /obj/item/reagent_containers/pill/insulin,
- /obj/item/stack/medical/gauze,
- /obj/item/storage/box/beakers,
- /obj/item/storage/box/medsprays,
- /obj/item/storage/box/syringes,
- /obj/item/storage/box/bodybags,
- /obj/item/storage/pill_bottle/stimulant)
- crate_name = "medical supplies crate"
-
-/datum/supply_pack/medical/vending
- name = "Medical Vending Crate"
- desc = "Contains refills for medical vending machines."
- cost = 2000
- contains = list(/obj/item/vending_refill/medical,
- /obj/item/vending_refill/wallmed)
- crate_name = "medical vending crate"
-
-/datum/supply_pack/medical/sprays
- name = "Medical Sprays"
- desc = "Contains two cans of Styptic Spray, Silver Sulfadiazine Spray, Synthflesh Spray and Sterilizer Compound Spray."
- cost = 2500
- contains = list(/obj/item/reagent_containers/medspray/styptic,
- /obj/item/reagent_containers/medspray/styptic,
- /obj/item/reagent_containers/medspray/silver_sulf,
- /obj/item/reagent_containers/medspray/silver_sulf,
- /obj/item/reagent_containers/medspray/synthflesh,
- /obj/item/reagent_containers/medspray/synthflesh,
- /obj/item/reagent_containers/medspray/sterilizine,
- /obj/item/reagent_containers/medspray/sterilizine)
- crate_name = "medical supplies crate"
-
-/datum/supply_pack/medical/firstaidmixed
- name = "Mixed Medical Kits"
- desc = "Contains one of each medical kits for dealing with a variety of injured crewmembers."
- cost = 1500
- contains = list(/obj/item/storage/firstaid/toxin,
- /obj/item/storage/firstaid/o2,
- /obj/item/storage/firstaid/brute,
- /obj/item/storage/firstaid/fire,
- /obj/item/storage/firstaid/regular)
- crate_name = "medical supplies crate"
-
-/datum/supply_pack/medical/firstaidoxygen
- name = "Oxygen Deprivation Kit Crate"
- desc = "Contains three first aid kits focused on helping oxygen deprivation victims."
- cost = 1000
- contains = list(/obj/item/storage/firstaid/o2,
- /obj/item/storage/firstaid/o2,
- /obj/item/storage/firstaid/o2)
- crate_name = "oxygen deprivation kit crate"
-
-/datum/supply_pack/medical/advrad
- name = "Radiation Treatment Crate Deluxe"
- desc = "A crate for when radiation is out of hand... Contains two rad-b-gone kits, one bottle of anti radiation deluxe pill bottle, as well as a radiation treatment deluxe pill bottle!"
- cost = 3500
- contains = list(/obj/item/storage/pill_bottle/antirad_plus,
- /obj/item/storage/pill_bottle/mutarad,
- /obj/item/storage/firstaid/radbgone,
- /obj/item/storage/firstaid/radbgone,
- /obj/item/geiger_counter,
- /obj/item/geiger_counter)
- crate_name = "radiation protection crate"
- crate_type = /obj/structure/closet/crate/radiation
-
-/datum/supply_pack/medical/surgery
- name = "Surgical Supplies Crate"
- desc = "Do you want to perform surgery, but don't have one of those fancy shmancy degrees? Just get started with this crate containing a medical duffelbag, Sterilizine spray and collapsible roller bed."
- cost = 1000
- contains = list(/obj/item/storage/backpack/duffelbag/med/surgery,
- /obj/item/reagent_containers/medspray/sterilizine,
- /obj/item/roller)
- crate_name = "surgical supplies crate"
-
-/datum/supply_pack/medical/firstaidtoxins
- name = "Toxin Treatment Kit Crate"
- desc = "Contains three first aid kits focused on healing damage dealt by heavy toxins."
- cost = 1000
- contains = list(/obj/item/storage/firstaid/toxin,
- /obj/item/storage/firstaid/toxin,
- /obj/item/storage/firstaid/toxin)
- crate_name = "toxin treatment kit crate"
-
-/datum/supply_pack/medical/virus
- name = "Virus Crate"
- desc = "Contains twelve different bottles, containing several viral samples for virology research. Also includes seven beakers and syringes. Balled-up jeans not included. Requires CMO access to open."
- cost = 2500
- access = ACCESS_CMO
- contains = list(/obj/item/reagent_containers/glass/bottle/flu_virion,
- /obj/item/reagent_containers/glass/bottle/cold,
- /obj/item/reagent_containers/glass/bottle/random_virus,
- /obj/item/reagent_containers/glass/bottle/random_virus,
- /obj/item/reagent_containers/glass/bottle/random_virus,
- /obj/item/reagent_containers/glass/bottle/random_virus,
- /obj/item/reagent_containers/glass/bottle/fake_gbs,
- /obj/item/reagent_containers/glass/bottle/magnitis,
- /obj/item/reagent_containers/glass/bottle/pierrot_throat,
- /obj/item/reagent_containers/glass/bottle/brainrot,
- /obj/item/reagent_containers/glass/bottle/anxiety,
- /obj/item/reagent_containers/glass/bottle/beesease,
- /obj/item/storage/box/syringes,
- /obj/item/storage/box/beakers,
- /obj/item/reagent_containers/glass/bottle/mutagen)
- crate_name = "virus crate"
- crate_type = /obj/structure/closet/crate/secure/plasma
- dangerous = TRUE
-
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////// Science /////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/science
- group = "Science"
- crate_type = /obj/structure/closet/crate/science
-
-/datum/supply_pack/science/robotics/mecha_odysseus
- name = "Circuit Crate (Odysseus)"
- desc = "Ever wanted to build your own giant medical robot? Well, now you can! Contains the Odysseus main control board and Odysseus peripherals board. Requires Robotics access to open."
- cost = 2500
- access = ACCESS_ROBOTICS
- contains = list(/obj/item/circuitboard/mecha/odysseus/peripherals,
- /obj/item/circuitboard/mecha/odysseus/main)
- crate_name = "\improper Odysseus circuit crate"
- crate_type = /obj/structure/closet/crate/secure/science
-
-/datum/supply_pack/science/robotics/mecha_ripley
- name = "Circuit Crate (Ripley APLU)"
- desc = "Rip apart rocks and xenomorphs alike with the Ripley APLU. Contains the Main Ripley control board, as well as the Ripley Peripherals board. Requires Robotics access to open."
- cost = 3000
- access = ACCESS_ROBOTICS
- contains = list(/obj/item/book/manual/ripley_build_and_repair,
- /obj/item/circuitboard/mecha/ripley/main,
- /obj/item/circuitboard/mecha/ripley/peripherals)
- crate_name = "\improper APLU Ripley circuit crate"
- crate_type = /obj/structure/closet/crate/secure/science
-
-/datum/supply_pack/science/circuitry
- name = "Circuitry Starter Pack Crate"
- desc = "Journey into the mysterious world of Circuitry with this starter pack. Contains a circuit printer, analyzer, debugger and wirer. Power cells not included."
- cost = 1000
- contains = list(/obj/item/integrated_electronics/analyzer,
- /obj/item/integrated_circuit_printer,
- /obj/item/integrated_electronics/debugger,
- /obj/item/integrated_electronics/wirer)
- crate_name = "circuitry starter pack crate"
-
-/datum/supply_pack/science/plasma
- name = "Plasma Assembly Crate"
- desc = "Everything you need to burn something to the ground, this contains three plasma assembly sets. Each set contains a plasma tank, igniter, proximity sensor, and timer! Warranty void if exposed to high temperatures. Requires Toxins access to open."
- cost = 1000
- access = ACCESS_TOX_STORAGE
- contains = list(/obj/item/tank/internals/plasma,
- /obj/item/tank/internals/plasma,
- /obj/item/tank/internals/plasma,
- /obj/item/assembly/igniter,
- /obj/item/assembly/igniter,
- /obj/item/assembly/igniter,
- /obj/item/assembly/prox_sensor,
- /obj/item/assembly/prox_sensor,
- /obj/item/assembly/prox_sensor,
- /obj/item/assembly/timer,
- /obj/item/assembly/timer,
- /obj/item/assembly/timer)
- crate_name = "plasma assembly crate"
- crate_type = /obj/structure/closet/crate/secure/plasma
-
-/datum/supply_pack/science/robotics
- name = "Robotics Assembly Crate"
- desc = "The tools you need to replace those finicky humans with a loyal robot army! Contains three proximity sensors, two high-powered cells, six flashes, and an electrical toolbox. Requires Robotics access to open."
- cost = 1000
- access = ACCESS_ROBOTICS
- contains = list(/obj/item/assembly/prox_sensor,
- /obj/item/assembly/prox_sensor,
- /obj/item/assembly/prox_sensor,
- /obj/item/storage/toolbox/electrical,
- /obj/item/storage/box/flashes,
- /obj/item/stock_parts/cell/high,
- /obj/item/stock_parts/cell/high)
- crate_name = "robotics assembly crate"
- crate_type = /obj/structure/closet/crate/secure/science
-
-/datum/supply_pack/science/shieldwalls
- name = "Shield Generator Crate"
- desc = "These high powered Shield Wall Generators are guaranteed to keep any unwanted lifeforms on the outside, where they belong! Contains four shield wall generators. Requires Teleporter access to open."
- cost = 2000
- access = ACCESS_TELEPORTER
- contains = list(/obj/machinery/shieldwallgen,
- /obj/machinery/shieldwallgen,
- /obj/machinery/shieldwallgen,
- /obj/machinery/shieldwallgen)
- crate_name = "shield generators crate"
- crate_type = /obj/structure/closet/crate/secure/science
-
-/datum/supply_pack/science/tablets
- name = "Tablet Crate"
- desc = "What's a computer? Contains five cargo tablets."
- cost = 5000
- contains = list(/obj/item/modular_computer/tablet/preset/cargo,
- /obj/item/modular_computer/tablet/preset/cargo,
- /obj/item/modular_computer/tablet/preset/cargo,
- /obj/item/modular_computer/tablet/preset/cargo,
- /obj/item/modular_computer/tablet/preset/cargo)
- crate_name = "tablet crate"
-
-/datum/supply_pack/science/transfer_valves
- name = "Tank Transfer Valves Crate"
- desc = "The key ingredient for making a lot of people very angry very fast. Contains two tank transfer valves. Requires RD access to open."
- cost = 6000
- access = ACCESS_RD
- contains = list(/obj/item/transfer_valve,
- /obj/item/transfer_valve)
- crate_name = "tank transfer valves crate"
- crate_type = /obj/structure/closet/crate/secure/science
- dangerous = TRUE
-
-/datum/supply_pack/science/tech_slugs
- name = "Tech Slug Ammo Shells"
- desc = "A new type of shell that is able to be made into a few different dangerous types. Contains two boxes of tech slugs, 14 shells in all."
- cost = 1000
- contains = list(/obj/item/storage/box/techsslug,
- /obj/item/storage/box/techsslug)
- crate_name = "tech slug crate"
-
-
-//////////////////////////////////////////////////////////////////////////////
-/////////////////////////////// Service //////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/service
- group = "Service"
-
-/datum/supply_pack/service/advlighting
- name = "Advanced Lighting crate"
- desc = "Thanks to advanced lighting tech we here at the Lamp Factory have be able to produce more lamps and lamp items! This crate has three lamps, a box of lights and a state of the art rapid-light-device!"
- cost = 2500 //Fair
- contains = list(/obj/item/construction/rld,
- /obj/item/flashlight/lamp,
- /obj/item/flashlight/lamp,
- /obj/item/flashlight/lamp/green,
- /obj/item/storage/box/lights/mixed)
- crate_name = "advanced lighting crate"
- crate_type = /obj/structure/closet/crate/secure
-
-/datum/supply_pack/service/cargo_supples
- name = "Cargo Supplies Crate"
- desc = "Sold everything that wasn't bolted down? You can get right back to work with this crate containing stamps, an export scanner, destination tagger, hand labeler and some package wrapping."
- cost = 1000
- contains = list(/obj/item/stamp,
- /obj/item/stamp/denied,
- /obj/item/export_scanner,
- /obj/item/destTagger,
- /obj/item/hand_labeler,
- /obj/item/stack/packageWrap)
- crate_name = "cargo supplies crate"
-
-/datum/supply_pack/service/food_cart
- name = "Food Cart Crate"
- desc = "Want to sell food on the go? Cook lost their cart? Well we just so happen to have a few carts to spare!"
- cost = 1000
- contains = list(/obj/machinery/food_cart)
- crate_name = "food cart crate"
- crate_type = /obj/structure/closet/crate
-
-/datum/supply_pack/service/noslipfloor
- name = "High-traction Floor Tiles"
- desc = "Make slipping a thing of the past with sixty industrial-grade anti-slip floortiles!"
- cost = 2000
- contains = list(/obj/item/stack/tile/noslip/thirty,
- /obj/item/stack/tile/noslip/thirty)
- crate_name = "high-traction floor tiles crate"
-
-/datum/supply_pack/service/icecream_cart
- name = "Ice Cream Cart Crate"
- desc = "Plasma fire a to hot for you, want a nice treat after a hard days work? Well now we have the cart for you! This Ice Cream Vat has everthing you need to make you and your friends so ice cream treats! This cart comes stocked with some ingredients for each type of scoopable icecream."
- cost = 2750 //Comes prestocked with basic ingredients
- contains = list(/obj/machinery/icecream_vat)
- crate_name = "ice cream vat crate"
- crate_type = /obj/structure/closet/crate
-
-/datum/supply_pack/service/janitor
- name = "Janitorial Supplies Crate"
- desc = "Fight back against dirt and grime with Nanotrasen's Janitorial Essentials(tm)! Contains three buckets, caution signs, and cleaner grenades. Also has a single mop, spray cleaner, rag, NT soap and a trash bag."
- cost = 1000
- contains = list(/obj/item/reagent_containers/glass/bucket,
- /obj/item/reagent_containers/glass/bucket,
- /obj/item/reagent_containers/glass/bucket,
- /obj/item/mop,
- /obj/item/caution,
- /obj/item/caution,
- /obj/item/caution,
- /obj/item/storage/bag/trash,
- /obj/item/reagent_containers/spray/cleaner,
- /obj/item/reagent_containers/rag,
- /obj/item/grenade/chem_grenade/cleaner,
- /obj/item/grenade/chem_grenade/cleaner,
- /obj/item/grenade/chem_grenade/cleaner,
- /obj/item/soap/nanotrasen)
- crate_name = "janitorial supplies crate"
-
-/datum/supply_pack/service/janitor/janicart
- name = "Janitorial Cart and Galoshes Crate"
- desc = "The keystone to any successful janitor. As long as you have feet, this pair of galoshes will keep them firmly planted on the ground. Also contains a janitorial cart."
- cost = 2000
- contains = list(/obj/structure/janitorialcart,
- /obj/item/clothing/shoes/galoshes)
- crate_name = "janitorial cart crate"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/service/janitor/janitank
- name = "Janitor Backpack Crate"
- desc = "Call forth divine judgement upon dirt and grime with this high capacity janitor backpack. Contains 500 units of station-cleansing cleaner. Requires janitor access to open."
- cost = 1000
- access = ACCESS_JANITOR
- contains = list(/obj/item/watertank/janitor)
- crate_name = "janitor backpack crate"
- crate_type = /obj/structure/closet/crate/secure
-
-/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 = 1750
- access = ACCESS_JANITOR
- contains = list(/obj/item/caution,
- /obj/item/caution,
- /obj/item/caution,
- /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!"
- cost = 2000
- contains = list(/mob/living/simple_animal/bot/mulebot)
- crate_name = "\improper MULEbot Crate"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/service/party
- name = "Party Equipment"
- desc = "Celebrate both life and death on the station with Nanotrasen's Party Essentials(tm)! Contains seven colored glowsticks, four beers, two ales, and a bottle of patron, goldschlager, and shaker!"
- cost = 2000
- contains = list(/obj/item/storage/box/drinkingglasses,
- /obj/item/reagent_containers/food/drinks/shaker,
- /obj/item/reagent_containers/food/drinks/bottle/patron,
- /obj/item/reagent_containers/food/drinks/bottle/goldschlager,
- /obj/item/reagent_containers/food/drinks/ale,
- /obj/item/reagent_containers/food/drinks/ale,
- /obj/item/reagent_containers/food/drinks/beer,
- /obj/item/reagent_containers/food/drinks/beer,
- /obj/item/reagent_containers/food/drinks/beer,
- /obj/item/reagent_containers/food/drinks/beer,
- /obj/item/flashlight/glowstick,
- /obj/item/flashlight/glowstick/red,
- /obj/item/flashlight/glowstick/blue,
- /obj/item/flashlight/glowstick/cyan,
- /obj/item/flashlight/glowstick/orange,
- /obj/item/flashlight/glowstick/yellow,
- /obj/item/flashlight/glowstick/pink)
- crate_name = "party equipment crate"
-
-/datum/supply_pack/service/carpet
- name = "Premium Carpet Crate"
- desc = "Plasteel floor tiles getting on your nerves? These stacks of extra soft carpet will tie any room together. Contains the classics."
- cost = 1000
- contains = list(/obj/item/stack/tile/carpet/fifty,
- /obj/item/stack/tile/carpet/fifty,
- /obj/item/stack/tile/carpet/black/fifty,
- /obj/item/stack/tile/carpet/black/fifty)
- crate_name = "premium carpet crate"
-
-/datum/supply_pack/service/carpet_exotic
- name = "Exotic Carpet Crate"
- desc = "Exotic carpets straight from Space Russia, for all your decorating needs. Contains 100 tiles each of 10 different flooring patterns."
- cost = 4000
- contains = list(/obj/item/stack/tile/carpet/blue/fifty,
- /obj/item/stack/tile/carpet/blue/fifty,
- /obj/item/stack/tile/carpet/cyan/fifty,
- /obj/item/stack/tile/carpet/cyan/fifty,
- /obj/item/stack/tile/carpet/green/fifty,
- /obj/item/stack/tile/carpet/green/fifty,
- /obj/item/stack/tile/carpet/orange/fifty,
- /obj/item/stack/tile/carpet/orange/fifty,
- /obj/item/stack/tile/carpet/purple/fifty,
- /obj/item/stack/tile/carpet/purple/fifty,
- /obj/item/stack/tile/carpet/red/fifty,
- /obj/item/stack/tile/carpet/red/fifty,
- /obj/item/stack/tile/carpet/royalblue/fifty,
- /obj/item/stack/tile/carpet/royalblue/fifty,
- /obj/item/stack/tile/carpet/royalblack/fifty,
- /obj/item/stack/tile/carpet/royalblack/fifty,
- /obj/item/stack/tile/carpet/blackred/fifty,
- /obj/item/stack/tile/carpet/blackred/fifty,
- /obj/item/stack/tile/carpet/monochrome/fifty,
- /obj/item/stack/tile/carpet/monochrome/fifty)
- crate_name = "exotic carpet crate"
-
-/datum/supply_pack/service/lightbulbs
- name = "Replacement Lights"
- desc = "May the light of Aether shine upon this station! Or at least, the light of forty two light tubes and twenty one light bulbs as well as a light replacer."
- cost = 1200
- contains = list(/obj/item/storage/box/lights/mixed,
- /obj/item/storage/box/lights/mixed,
- /obj/item/storage/box/lights/mixed,
- /obj/item/lightreplacer)
- crate_name = "replacement lights"
-
-/datum/supply_pack/service/minerkit
- name = "Shaft Miner Starter Kit"
- desc = "All the miners died too fast? Assistant wants to get a taste of life off-station? Either way, this kit is the best way to turn a regular crewman into an ore-producing, monster-slaying machine. Contains meson goggles, a pickaxe, advanced mining scanner, cargo headset, ore bag, gasmask, and explorer suit. Requires QM access to open."
- cost = 2500
- access = ACCESS_QM
- contains = list(/obj/item/pickaxe/mini,
- /obj/item/clothing/glasses/meson,
- /obj/item/t_scanner/adv_mining_scanner/lesser,
- /obj/item/radio/headset/headset_cargo/mining,
- /obj/item/storage/bag/ore,
- /obj/item/clothing/suit/hooded/explorer/standard,
- /obj/item/clothing/mask/gas/explorer)
- crate_name = "shaft miner starter kit"
- crate_type = /obj/structure/closet/crate/secure
-
-//////////////////////////////////////////////////////////////////////////////
-/////////////////////////// Vending Restocks /////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/service/vending/bartending
- name = "Bartending Supply Crate"
- desc = "Bring on the booze with vending machine refills, as well as a free book containing the well-kept secrets to the bartending trade!"
- cost = 2000
- contains = list(/obj/item/vending_refill/boozeomat,
- /obj/item/vending_refill/coffee,
- /obj/item/book/granter/action/drink_fling)
- crate_name = "bartending supply crate"
-
-/datum/supply_pack/service/vending/cigarette
- name = "Cigarette Supply Crate"
- desc = "Don't believe the reports - smoke today! Contains a cigarette vending machine refill."
- cost = 1500
- contains = list(/obj/item/vending_refill/cigarette)
- crate_name = "cigarette supply crate"
- crate_type = /obj/structure/closet/crate
-
-/datum/supply_pack/service/vending/games
- name = "Games Supply Crate"
- desc = "Get your game on with this game vending machine refill."
- cost = 1000
- contains = list(/obj/item/vending_refill/games)
- crate_name = "games supply crate"
- crate_type = /obj/structure/closet/crate
-
-/datum/supply_pack/service/vending/snack
- name = "Snack Supply Crate"
- desc = "One vending machine refill of cavity-bringin' goodness! The number one dentist recommended order!"
- cost = 1500
- contains = list(/obj/item/vending_refill/snack)
- crate_name = "snacks supply crate"
-
-/datum/supply_pack/service/vending/cola
- name = "Softdrinks Supply Crate"
- desc = "Got whacked by a toolbox, but you still have those pesky teeth? Get rid of those pearly whites with this soda machine refill, today!"
- cost = 1500
- contains = list(/obj/item/vending_refill/cola)
- crate_name = "soft drinks supply crate"
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////// Organic /////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/organic
- group = "Food & Hydroponics"
- crate_type = /obj/structure/closet/crate/freezer
-
-/datum/supply_pack/organic/hydroponics/beekeeping_suits
- name = "Beekeeper Suit Crate"
- desc = "Bee business booming? Better be benevolent and boost botany by bestowing bi-Beekeeper-suits! Contains two beekeeper suits and matching headwear."
- cost = 1000
- contains = list(/obj/item/clothing/head/beekeeper_head,
- /obj/item/clothing/suit/beekeeper_suit,
- /obj/item/clothing/head/beekeeper_head,
- /obj/item/clothing/suit/beekeeper_suit)
- crate_name = "beekeeper suits"
- crate_type = /obj/structure/closet/crate/hydroponics
-
-/datum/supply_pack/organic/hydroponics/beekeeping_fullkit
- name = "Beekeeping Starter Crate"
- desc = "BEES BEES BEES. Contains three honey frames, a beekeeper suit and helmet, flyswatter, bee house, and, of course, a pure-bred Nanotrasen-Standardized Queen Bee!"
- cost = 1500
- contains = list(/obj/structure/beebox/unwrenched,
- /obj/item/honey_frame,
- /obj/item/honey_frame,
- /obj/item/honey_frame,
- /obj/item/queen_bee/bought,
- /obj/item/clothing/head/beekeeper_head,
- /obj/item/clothing/suit/beekeeper_suit,
- /obj/item/melee/flyswatter)
- crate_name = "beekeeping starter crate"
- crate_type = /obj/structure/closet/crate/hydroponics
-
-/datum/supply_pack/organic/candy
- name = "Candy Crate"
- desc = "For people that have a insatiable sweet tooth! Has ten candies to be eaten up.."
- cost = 2500
- var/num_contained = 10 //number of items picked to be contained in a randomised crate
- contains = list(/obj/item/reagent_containers/food/snacks/candy,
- /obj/item/reagent_containers/food/snacks/lollipop,
- /obj/item/reagent_containers/food/snacks/gumball,
- /obj/item/reagent_containers/food/snacks/chocolateegg,
- /obj/item/reagent_containers/food/snacks/donut,
- /obj/item/reagent_containers/food/snacks/cookie,
- /obj/item/reagent_containers/food/snacks/sugarcookie,
- /obj/item/reagent_containers/food/snacks/chococornet,
- /obj/item/reagent_containers/food/snacks/mint,
- /obj/item/reagent_containers/food/snacks/spiderlollipop,
- /obj/item/reagent_containers/food/snacks/chococoin,
- /obj/item/reagent_containers/food/snacks/fudgedice,
- /obj/item/reagent_containers/food/snacks/chocoorange,
- /obj/item/reagent_containers/food/snacks/honeybar,
- /obj/item/reagent_containers/food/snacks/tinychocolate,
- /obj/item/reagent_containers/food/snacks/spacetwinkie,
- /obj/item/reagent_containers/food/snacks/syndicake,
- /obj/item/reagent_containers/food/snacks/cheesiehonkers,
- /obj/item/reagent_containers/food/snacks/sugarcookie/spookyskull,
- /obj/item/reagent_containers/food/snacks/sugarcookie/spookycoffin,
- /obj/item/reagent_containers/food/snacks/candy_corn,
- /obj/item/reagent_containers/food/snacks/candiedapple,
- /obj/item/reagent_containers/food/snacks/chocolatebar,
- /obj/item/reagent_containers/food/snacks/candyheart,
- /obj/item/storage/fancy/heart_box,
- /obj/item/storage/fancy/donut_box)
- crate_name = "candy crate"
-
-/datum/supply_pack/organic/cutlery
- name = "Kitchen Cutlery Deluxe Set"
- desc = "Need to slice and dice away those ''Tomatos'' well we got what you need! From a nice set of knifes, forks, plates, glasses, and a whetstone for when you got some grizzle that is a bit harder to slice then normal."
- cost = 10000
- contraband = TRUE
- contains = list(/obj/item/sharpener,
- /obj/item/kitchen/fork,
- /obj/item/kitchen/fork,
- /obj/item/kitchen/knife,
- /obj/item/kitchen/knife,
- /obj/item/kitchen/knife,
- /obj/item/kitchen/knife,
- /obj/item/kitchen/knife/butcher,
- /obj/item/kitchen/knife/butcher,
- /obj/item/kitchen/rollingpin, //Deluxe for a reason
- /obj/item/trash/plate,
- /obj/item/trash/plate,
- /obj/item/trash/plate,
- /obj/item/trash/plate,
- /obj/item/reagent_containers/food/drinks/drinkingglass,
- /obj/item/reagent_containers/food/drinks/drinkingglass,
- /obj/item/reagent_containers/food/drinks/drinkingglass,
- /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass,
- /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass)
- crate_name = "kitchen cutlery deluxe set"
-
-/datum/supply_pack/organic/food
- name = "Food Crate"
- desc = "Get things cooking with this crate full of useful ingredients! Contains a two dozen eggs, three bananas, and two bags of flour and rice, two cartons of milk, soymilk, as well as salt and pepper shakers, a enzyme and sugar bottle, and three slabs of monkeymeat."
- cost = 1000
- contains = list(/obj/item/reagent_containers/food/condiment/flour,
- /obj/item/reagent_containers/food/condiment/flour,
- /obj/item/reagent_containers/food/condiment/rice,
- /obj/item/reagent_containers/food/condiment/rice,
- /obj/item/reagent_containers/food/condiment/milk,
- /obj/item/reagent_containers/food/condiment/milk,
- /obj/item/reagent_containers/food/condiment/soymilk,
- /obj/item/reagent_containers/food/condiment/saltshaker,
- /obj/item/reagent_containers/food/condiment/peppermill,
- /obj/item/storage/fancy/egg_box,
- /obj/item/storage/fancy/egg_box,
- /obj/item/reagent_containers/food/condiment/enzyme,
- /obj/item/reagent_containers/food/condiment/sugar,
- /obj/item/reagent_containers/food/snacks/meat/slab/monkey,
- /obj/item/reagent_containers/food/snacks/meat/slab/monkey,
- /obj/item/reagent_containers/food/snacks/meat/slab/monkey,
- /obj/item/reagent_containers/food/snacks/grown/banana,
- /obj/item/reagent_containers/food/snacks/grown/banana,
- /obj/item/reagent_containers/food/snacks/grown/banana)
- crate_name = "food crate"
-
-/datum/supply_pack/organic/cream_piee
- name = "High-yield Clown-grade Cream Pie Crate"
- desc = "Designed by Aussec's Advanced Warfare Research Division, these high-yield, Clown-grade cream pies are powered by a synergy of performance and efficiency. Guaranteed to provide maximum results."
- cost = 6000
- contains = list(/obj/item/storage/backpack/duffelbag/clown/cream_pie)
- crate_name = "party equipment crate"
- contraband = TRUE
- access = ACCESS_THEATRE
- crate_type = /obj/structure/closet/crate/secure
-
-/datum/supply_pack/organic/hunting
- name = "Huntting gear"
- desc = "Even in space, we can fine prey to hunt, this crate contains everthing a fine hunter needs to have a sporting time. This crate needs armory access to open. A true huntter only needs a fine bottle of cognac, a nice coat, some good o' cigars, and of cource a huntting shotgun. "
- cost = 3500
- contraband = TRUE
- contains = list(/obj/item/clothing/head/flatcap,
- /obj/item/clothing/suit/hooded/wintercoat/captain,
- /obj/item/reagent_containers/food/drinks/bottle/cognac,
- /obj/item/storage/fancy/cigarettes/cigars/havana,
- /obj/item/clothing/gloves/color/white,
- /obj/item/clothing/under/rank/curator,
- /obj/item/gun/ballistic/shotgun/lethal)
- access = ACCESS_ARMORY
- crate_name = "sporting crate"
- crate_type = /obj/structure/closet/crate/secure // Would have liked a wooden crate but access >:(
-
-/datum/supply_pack/organic/hydroponics
- name = "Hydroponics Crate"
- desc = "Supplies for growing a great garden! Contains two bottles of ammonia, two Plant-B-Gone spray bottles, a hatchet, cultivator, plant analyzer, as well as a pair of leather gloves and a botanist's apron."
- cost = 1500
- contains = list(/obj/item/reagent_containers/spray/plantbgone,
- /obj/item/reagent_containers/spray/plantbgone,
- /obj/item/reagent_containers/glass/bottle/ammonia,
- /obj/item/reagent_containers/glass/bottle/ammonia,
- /obj/item/hatchet,
- /obj/item/cultivator,
- /obj/item/plant_analyzer,
- /obj/item/clothing/gloves/botanic_leather,
- /obj/item/clothing/suit/apron)
- crate_name = "hydroponics crate"
- crate_type = /obj/structure/closet/crate/hydroponics
-
-/datum/supply_pack/organic/hydroponics/hydrotank
- name = "Hydroponics Backpack Crate"
- desc = "Bring on the flood with this high-capacity backpack crate. Contains 500 units of life-giving H2O. Requires hydroponics access to open."
- cost = 1000
- access = ACCESS_HYDROPONICS
- contains = list(/obj/item/watertank)
- crate_name = "hydroponics backpack crate"
- crate_type = /obj/structure/closet/crate/secure
-
-/datum/supply_pack/organic/mre
- name = "MRE supply kit (emergency rations)"
- desc = "The lights are out. Oxygen's running low. You've run out of food except space weevils. Don't let this be you! Order our NT branded MRE kits today! This pack contains 5 MRE packs with a randomized menu and an oxygen tank."
- cost = 2000
- contains = list(/obj/item/storage/box/mre/menu1/safe,
- /obj/item/storage/box/mre/menu1/safe,
- /obj/item/storage/box/mre/menu2/safe,
- /obj/item/storage/box/mre/menu2/safe,
- /obj/item/storage/box/mre/menu3,
- /obj/item/storage/box/mre/menu4/safe)
- crate_name = "MRE crate (emergency rations)"
-
-/datum/supply_pack/organic/pizza
- name = "Pizza Crate"
- desc = "Best prices on this side of the galaxy. All deliveries are guaranteed to be 99% anomaly-free!"
- cost = 6000 // Best prices this side of the galaxy.
- contains = list(/obj/item/pizzabox/margherita,
- /obj/item/pizzabox/mushroom,
- /obj/item/pizzabox/meat,
- /obj/item/pizzabox/vegetable,
- /obj/item/pizzabox/pineapple)
- crate_name = "pizza crate"
- var/static/anomalous_box_provided = FALSE
-
-/datum/supply_pack/organic/pizza/fill(obj/structure/closet/crate/C)
- . = ..()
- if(!anomalous_box_provided)
- for(var/obj/item/pizzabox/P in C)
- if(prob(1)) //1% chance for each box, so 4% total chance per order
- var/obj/item/pizzabox/infinite/fourfiveeight = new(C)
- fourfiveeight.boxtag = P.boxtag
- qdel(P)
- anomalous_box_provided = TRUE
- log_game("An anomalous pizza box was provided in a pizza crate at during cargo delivery")
- if(prob(50))
- addtimer(CALLBACK(src, .proc/anomalous_pizza_report), rand(300, 1800))
- else
- message_admins("An anomalous pizza box was silently created with no command report in a pizza crate delivery.")
- break
-
-/datum/supply_pack/organic/pizza/proc/anomalous_pizza_report()
- print_command_report("[station_name()], our anomalous materials divison has reported a missing object that is highly likely to have been sent to your station during a routine cargo \
- delivery. Please search all crates and manifests provided with the delivery and return the object if is located. The object resembles a standard \[DATA EXPUNGED\] and is to be \
- considered \[REDACTED\] and returned at your leisure. Note that objects the anomaly produces are specifically attuned exactly to the individual opening the anomaly; regardless \
- of species, the individual will find the object edible and it will taste great according to their personal definitions, which vary significantly based on person and species.")
-
-/datum/supply_pack/organic/potted_plants
- name = "Potted Plants Crate"
- desc = "Spruce up the station with these lovely plants! Contains a random assortment of five potted plants from Nanotrasen's potted plant research division. Warranty void if thrown."
- cost = 700
- contains = list(/obj/item/twohanded/required/kirbyplants/random,
- /obj/item/twohanded/required/kirbyplants/random,
- /obj/item/twohanded/required/kirbyplants/random,
- /obj/item/twohanded/required/kirbyplants/random,
- /obj/item/twohanded/required/kirbyplants/random)
- crate_name = "potted plants crate"
- crate_type = /obj/structure/closet/crate/hydroponics
-
-/datum/supply_pack/organic/seeds
- name = "Seeds Crate"
- desc = "Big things have small beginnings. Contains thirteen different seeds."
- cost = 1000
- contains = list(/obj/item/seeds/chili,
- /obj/item/seeds/berry,
- /obj/item/seeds/corn,
- /obj/item/seeds/eggplant,
- /obj/item/seeds/tomato,
- /obj/item/seeds/soya,
- /obj/item/seeds/wheat,
- /obj/item/seeds/wheat/rice,
- /obj/item/seeds/carrot,
- /obj/item/seeds/sunflower,
- /obj/item/seeds/chanter,
- /obj/item/seeds/potato,
- /obj/item/seeds/sugarcane)
- crate_name = "seeds crate"
- crate_type = /obj/structure/closet/crate/hydroponics
-
-/datum/supply_pack/organic/vday
- name = "Surplus Valentine Crate"
- desc = "Turns out we got warehouses of this love-y dove-y crap. Were sending out small barged buddle of Valentine gear. This crate has two boxes of chocolate, three poppy flowers, five candy hearts, and three cards."
- cost = 3000
- contraband = TRUE
- contains = list(/obj/item/storage/fancy/heart_box,
- /obj/item/storage/fancy/heart_box,
- /obj/item/reagent_containers/food/snacks/grown/poppy,
- /obj/item/reagent_containers/food/snacks/grown/poppy,
- /obj/item/reagent_containers/food/snacks/grown/poppy,
- /obj/item/reagent_containers/food/snacks/candyheart,
- /obj/item/reagent_containers/food/snacks/candyheart,
- /obj/item/reagent_containers/food/snacks/candyheart,
- /obj/item/reagent_containers/food/snacks/candyheart,
- /obj/item/reagent_containers/food/snacks/candyheart,
- /obj/item/valentine,
- /obj/item/valentine,
- /obj/item/valentine)
- crate_name = "valentine crate"
- crate_type = /obj/structure/closet/crate/secure
-
-/datum/supply_pack/organic/exoticseeds
- name = "Exotic Seeds Crate"
- desc = "Any entrepreneuring botanist's dream. Contains twelve different seeds, including three replica-pod seeds and two mystery seeds!"
- cost = 1500
- contains = list(/obj/item/seeds/nettle,
- /obj/item/seeds/replicapod,
- /obj/item/seeds/replicapod,
- /obj/item/seeds/replicapod,
- /obj/item/seeds/plump,
- /obj/item/seeds/liberty,
- /obj/item/seeds/amanita,
- /obj/item/seeds/reishi,
- /obj/item/seeds/banana,
- /obj/item/seeds/eggplant/eggy,
- /obj/item/seeds/random,
- /obj/item/seeds/random)
- crate_name = "exotic seeds crate"
- crate_type = /obj/structure/closet/crate/hydroponics
-
-//////////////////////////////////////////////////////////////////////////////
-////////////////////////////// Livestock /////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/critter
- group = "Livestock"
- crate_type = /obj/structure/closet/crate/critter
-
-/datum/supply_pack/critter/butterfly
- name = "Butterflies Crate"
- desc = "Not a very dangerous insect, but they do give off a better image than, say, flies or cockroaches."//is that a motherfucking worm reference
- contraband = TRUE
- cost = 5000
- contains = list(/mob/living/simple_animal/butterfly)
- crate_name = "entomology samples crate"
-
-/datum/supply_pack/critter/butterfly/generate()
- . = ..()
- for(var/i in 1 to 49)
- new /mob/living/simple_animal/butterfly(.)
-
-/datum/supply_pack/critter/cat
- name = "Cat Crate"
- desc = "The cat goes meow! Comes with a collar and a nice cat toy! Cheeseburger not included."//i can't believe im making this reference
- cost = 5000 //Cats are worth as much as corgis.
- contains = list(/mob/living/simple_animal/pet/cat,
- /obj/item/clothing/neck/petcollar,
- /obj/item/toy/cattoy)
- crate_name = "cat crate"
-
-/datum/supply_pack/critter/cat/generate()
- . = ..()
- if(prob(50))
- var/mob/living/simple_animal/pet/cat/C = locate() in .
- qdel(C)
- new /mob/living/simple_animal/pet/cat/Proc(.)
-
-/datum/supply_pack/critter/chick
- name = "Chicken Crate"
- desc = "The chicken goes bwaak!"
- cost = 2000
- contains = list( /mob/living/simple_animal/chick)
- crate_name = "chicken crate"
-
-/datum/supply_pack/critter/crab
- name = "Crab Rocket"
- desc = "CRAAAAAAB ROCKET. CRAB ROCKET. CRAB ROCKET. CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB ROCKET. CRAFT. ROCKET. BUY. CRAFT ROCKET. CRAB ROOOCKET. CRAB ROOOOCKET. CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB ROOOOOOOOOOOOOOOOOOOOOOCK EEEEEEEEEEEEEEEEEEEEEEEEE EEEETTTTTTTTTTTTAAAAAAAAA AAAHHHHHHHHHHHHH. CRAB ROCKET. CRAAAB ROCKEEEEEEEEEGGGGHHHHTT CRAB CRAB CRAABROCKET CRAB ROCKEEEET."//fun fact: i actually spent like 10 minutes and transcribed the entire video.
- cost = 5000
- contains = list(/mob/living/simple_animal/crab)
- crate_name = "look sir free crabs"
- DropPodOnly = TRUE
-
-/datum/supply_pack/critter/crab/generate()
- . = ..()
- for(var/i in 1 to 49)
- new /mob/living/simple_animal/crab(.)
-
-/datum/supply_pack/critter/corgi
- name = "Corgi Crate"
- desc = "Considered the optimal dog breed by thousands of research scientists, this Corgi is but one dog from the millions of Ian's noble bloodline. Comes with a cute collar!"
- cost = 5000
- contains = list(/mob/living/simple_animal/pet/dog/corgi,
- /obj/item/clothing/neck/petcollar)
- crate_name = "corgi crate"
-
-/datum/supply_pack/critter/corgi/generate()
- . = ..()
- if(prob(50))
- var/mob/living/simple_animal/pet/dog/corgi/D = locate() in .
- if(D.gender == FEMALE)
- qdel(D)
- new /mob/living/simple_animal/pet/dog/corgi/Lisa(.)
-
-/datum/supply_pack/critter/corgis/exotic
- name = "Exotic Corgi Crate"
- desc = "Corgis fit for a king, these corgis come in a unique color to signify their superiority. Comes with a cute collar!"
- cost = 5500
- contains = list(/mob/living/simple_animal/pet/dog/corgi/exoticcorgi,
- /obj/item/clothing/neck/petcollar)
- crate_name = "exotic corgi crate"
-
-/datum/supply_pack/critter/cow
- name = "Cow Crate"
- desc = "The cow goes moo!"
- cost = 3000
- contains = list(/mob/living/simple_animal/cow)
- crate_name = "cow crate"
-
-/datum/supply_pack/critter/fox
- name = "Fox Crate"
- desc = "The fox goes...? Comes with a collar!"//what does the fox say
- cost = 5000
- contains = list(/mob/living/simple_animal/pet/fox,
- /obj/item/clothing/neck/petcollar)
- crate_name = "fox crate"
-
-/datum/supply_pack/critter/goat
- name = "Goat Crate"
- desc = "The goat goes baa! Warranty void if used as a replacement for Pete."
- cost = 2500
- contains = list(/mob/living/simple_animal/hostile/retaliate/goat)
- crate_name = "goat crate"
-
-/datum/supply_pack/critter/goose
- name = "Goose Crate"
- desc = "Angry and violent birds. Evil, evil creatures."
- cost = 2500
- contains = list(/mob/living/simple_animal/hostile/retaliate/goose)
- crate_name = "goose crate"
-
-/datum/supply_pack/critter/monkey
- name = "Monkey Cube Crate"
- desc = "Stop monkeying around! Contains seven monkey cubes. Just add water!"
- cost = 2000
- contains = list (/obj/item/storage/box/monkeycubes)
- crate_name = "monkey cube crate"
-
-/datum/supply_pack/critter/pug
- name = "Pug Crate"
- desc = "Like a normal dog, but... squished. Comes with a nice collar!"
- cost = 5000
- contains = list(/mob/living/simple_animal/pet/dog/pug,
- /obj/item/clothing/neck/petcollar)
- crate_name = "pug crate"
-
-/datum/supply_pack/organic/critter/kiwi
- name = "Space kiwi Crate"
- cost = 2000
- contains = list( /mob/living/simple_animal/kiwi)
- crate_name = "space kiwi crate"
-
-/datum/supply_pack/critter/snake
- name = "Snake Crate"
- desc = "Tired of these MOTHER FUCKING snakes on this MOTHER FUCKING space station? Then this isn't the crate for you. Contains three poisonous snakes."
- cost = 3000
- contains = list(/mob/living/simple_animal/hostile/retaliate/poison/snake,
- /mob/living/simple_animal/hostile/retaliate/poison/snake,
- /mob/living/simple_animal/hostile/retaliate/poison/snake)
- crate_name = "snake crate"
-
-/datum/supply_pack/critter/secbat
- name = "Security Bat Crate"
- desc = "Contains five security bats, perfect to Bat-up any security officer."
- cost = 2500
- contains = list(/mob/living/simple_animal/hostile/retaliate/bat/secbat,
- /mob/living/simple_animal/hostile/retaliate/bat/secbat,
- /mob/living/simple_animal/hostile/retaliate/bat/secbat,
- /mob/living/simple_animal/hostile/retaliate/bat/secbat,
- /mob/living/simple_animal/hostile/retaliate/bat/secbat)
- crate_name = "security bat crate"
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////// Costumes & Toys /////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/costumes_toys
- group = "Costumes & Toys"
-
-/datum/supply_pack/costumes_toys/randomised
- name = "Collectable Hats Crate"
- desc = "Flaunt your status with three unique, highly-collectable hats!"
- cost = 20000
- var/num_contained = 3 //number of items picked to be contained in a randomised crate
- contains = list(/obj/item/clothing/head/collectable/chef,
- /obj/item/clothing/head/collectable/paper,
- /obj/item/clothing/head/collectable/tophat,
- /obj/item/clothing/head/collectable/captain,
- /obj/item/clothing/head/collectable/beret,
- /obj/item/clothing/head/collectable/welding,
- /obj/item/clothing/head/collectable/flatcap,
- /obj/item/clothing/head/collectable/pirate,
- /obj/item/clothing/head/collectable/kitty,
- /obj/item/clothing/head/collectable/rabbitears,
- /obj/item/clothing/head/collectable/wizard,
- /obj/item/clothing/head/collectable/hardhat,
- /obj/item/clothing/head/collectable/HoS,
- /obj/item/clothing/head/collectable/HoP,
- /obj/item/clothing/head/collectable/thunderdome,
- /obj/item/clothing/head/collectable/swat,
- /obj/item/clothing/head/collectable/slime,
- /obj/item/clothing/head/collectable/police,
- /obj/item/clothing/head/collectable/slime,
- /obj/item/clothing/head/collectable/xenom,
- /obj/item/clothing/head/collectable/petehat)
- crate_name = "collectable hats crate"
- crate_type = /obj/structure/closet/crate/wooden
-
-/datum/supply_pack/costumes_toys/randomised/contraband
- name = "Contraband Crate"
- desc = "Psst.. bud... want some contraband? I can get you a poster, some nice cigs, dank, even some sponsored items...you know, the good stuff. Just keep it away from the cops, kay?"
- contraband = TRUE
- cost = 3000
- num_contained = 5 //SOME
- contains = list(/obj/item/poster/random_contraband,
- /obj/item/poster/random_contraband,
- /obj/item/reagent_containers/food/snacks/grown/cannabis,
- /obj/item/reagent_containers/food/snacks/grown/cannabis/rainbow,
- /obj/item/reagent_containers/food/snacks/grown/cannabis/white,
- /obj/item/storage/pill_bottle/zoom,
- /obj/item/storage/pill_bottle/happy,
- /obj/item/storage/pill_bottle/lsd,
- /obj/item/storage/pill_bottle/aranesp,
- /obj/item/storage/pill_bottle/stimulant,
- /obj/item/toy/cards/deck/syndicate,
- /obj/item/reagent_containers/food/drinks/bottle/absinthe,
- /obj/item/clothing/under/syndicate/tacticool,
- /obj/item/storage/fancy/cigarettes/cigpack_syndicate,
- /obj/item/storage/fancy/cigarettes/cigpack_shadyjims,
- /obj/item/clothing/mask/gas/syndicate,
- /obj/item/clothing/neck/necklace/dope,
- /obj/item/vending_refill/donksoft,
- /obj/item/circuitboard/computer/arcade/amputation)
- crate_name = "crate"
-
-/datum/supply_pack/costumes_toys/foamforce
- name = "Foam Force Crate"
- desc = "Break out the big guns with eight Foam Force shotguns!"
- cost = 1000
- contains = list(/obj/item/gun/ballistic/shotgun/toy,
- /obj/item/gun/ballistic/shotgun/toy,
- /obj/item/gun/ballistic/shotgun/toy,
- /obj/item/gun/ballistic/shotgun/toy,
- /obj/item/gun/ballistic/shotgun/toy,
- /obj/item/gun/ballistic/shotgun/toy,
- /obj/item/gun/ballistic/shotgun/toy,
- /obj/item/gun/ballistic/shotgun/toy)
- crate_name = "foam force crate"
-
-/datum/supply_pack/costumes_toys/foamforce/bonus
- name = "Foam Force Pistols Crate"
- desc = "Psst.. hey bud... remember those old foam force pistols that got discontinued for being too cool? Well I got two of those right here with your name on em. I'll even throw in a spare mag for each, waddya say?"
- contraband = TRUE
- cost = 4000
- contains = list(/obj/item/gun/ballistic/automatic/toy/pistol,
- /obj/item/gun/ballistic/automatic/toy/pistol,
- /obj/item/ammo_box/magazine/toy/pistol,
- /obj/item/ammo_box/magazine/toy/pistol)
- crate_name = "foam force crate"
-
-/datum/supply_pack/costumes_toys/formalwear
- name = "Formalwear Crate"
- desc = "You're gonna like the way you look, I guaranteed it. Contains an asston of fancy clothing."
- cost = 3000 //Lots of very expensive items. You gotta pay up to look good!
- contains = list(/obj/item/clothing/under/blacktango,
- /obj/item/clothing/under/assistantformal,
- /obj/item/clothing/under/assistantformal,
- /obj/item/clothing/under/lawyer/bluesuit,
- /obj/item/clothing/suit/toggle/lawyer,
- /obj/item/clothing/under/lawyer/purpsuit,
- /obj/item/clothing/suit/toggle/lawyer/purple,
- /obj/item/clothing/under/lawyer/blacksuit,
- /obj/item/clothing/suit/toggle/lawyer/black,
- /obj/item/clothing/accessory/waistcoat,
- /obj/item/clothing/neck/tie/blue,
- /obj/item/clothing/neck/tie/red,
- /obj/item/clothing/neck/tie/black,
- /obj/item/clothing/head/bowler,
- /obj/item/clothing/head/fedora,
- /obj/item/clothing/head/flatcap,
- /obj/item/clothing/head/beret,
- /obj/item/clothing/head/that,
- /obj/item/clothing/shoes/laceup,
- /obj/item/clothing/shoes/laceup,
- /obj/item/clothing/shoes/laceup,
- /obj/item/clothing/under/suit_jacket/charcoal,
- /obj/item/clothing/under/suit_jacket/navy,
- /obj/item/clothing/under/suit_jacket/burgundy,
- /obj/item/clothing/under/suit_jacket/checkered,
- /obj/item/clothing/under/suit_jacket/tan,
- /obj/item/lipstick/random)
- crate_name = "formalwear crate"
- crate_type = /obj/structure/closet/crate/wooden
-
-/datum/supply_pack/costumes_toys/clownpin
- name = "Hilarious Firing Pin Crate"
- desc = "I uh... I'm not really sure what this does. Wanna buy it?"
- cost = 5000
- contraband = TRUE
- contains = list(/obj/item/firing_pin/clown)
- crate_name = "toy crate" // It's /technically/ a toy. For the clown, at least.
- crate_type = /obj/structure/closet/crate/wooden
-
-/datum/supply_pack/costumes_toys/lasertag
- name = "Laser Tag Crate"
- desc = "Foam Force is for boys. Laser Tag is for men. Contains three sets of red suits, blue suits, matching helmets, and matching laser tag guns."
- cost = 1500
- contains = list(/obj/item/gun/energy/laser/redtag,
- /obj/item/gun/energy/laser/redtag,
- /obj/item/gun/energy/laser/redtag,
- /obj/item/gun/energy/laser/bluetag,
- /obj/item/gun/energy/laser/bluetag,
- /obj/item/gun/energy/laser/bluetag,
- /obj/item/clothing/suit/redtag,
- /obj/item/clothing/suit/redtag,
- /obj/item/clothing/suit/redtag,
- /obj/item/clothing/suit/bluetag,
- /obj/item/clothing/suit/bluetag,
- /obj/item/clothing/suit/bluetag,
- /obj/item/clothing/head/helmet/redtaghelm,
- /obj/item/clothing/head/helmet/redtaghelm,
- /obj/item/clothing/head/helmet/redtaghelm,
- /obj/item/clothing/head/helmet/bluetaghelm,
- /obj/item/clothing/head/helmet/bluetaghelm,
- /obj/item/clothing/head/helmet/bluetaghelm)
- crate_name = "laser tag crate"
-
-/datum/supply_pack/costumes_toys/lasertag/pins
- name = "Laser Tag Firing Pins Crate"
- desc = "Three laser tag firing pins used in laser-tag units to ensure users are wearing their vests."
- cost = 3000
- contraband = TRUE
- contains = list(/obj/item/storage/box/lasertagpins)
- crate_name = "laser tag crate"
-
-/datum/supply_pack/costumes_toys/costume_original
- name = "Original Costume Crate"
- desc = "Reenact Shakespearean plays with this assortment of outfits. Contains eight different costumes!"
- cost = 1000
- contains = list(/obj/item/clothing/head/snowman,
- /obj/item/clothing/suit/snowman,
- /obj/item/clothing/head/chicken,
- /obj/item/clothing/suit/chickensuit,
- /obj/item/clothing/mask/gas/monkeymask,
- /obj/item/clothing/suit/monkeysuit,
- /obj/item/clothing/head/cardborg,
- /obj/item/clothing/suit/cardborg,
- /obj/item/clothing/head/xenos,
- /obj/item/clothing/suit/xenos,
- /obj/item/clothing/suit/hooded/ian_costume,
- /obj/item/clothing/suit/hooded/carp_costume,
- /obj/item/clothing/suit/hooded/bee_costume)
- crate_name = "original costume crate"
- crate_type = /obj/structure/closet/crate/wooden
-
-/datum/supply_pack/costumes_toys/costume
- name = "Standard Costume Crate"
- desc = "Supply the station's entertainers with the equipment of their trade with these Nanotrasen-approved costumes! Contains a full clown and mime outfit, along with a bike horn and a bottle of nothing."
- cost = 1000
- access = ACCESS_THEATRE
- contains = list(/obj/item/storage/backpack/clown,
- /obj/item/clothing/shoes/clown_shoes,
- /obj/item/clothing/mask/gas/clown_hat,
- /obj/item/clothing/under/rank/clown,
- /obj/item/bikehorn,
- /obj/item/clothing/under/rank/mime,
- /obj/item/clothing/shoes/sneakers/black,
- /obj/item/clothing/gloves/color/white,
- /obj/item/clothing/mask/gas/mime,
- /obj/item/clothing/head/beret,
- /obj/item/clothing/suit/suspenders,
- /obj/item/reagent_containers/food/drinks/bottle/bottleofnothing,
- /obj/item/storage/backpack/mime)
- crate_name = "standard costume crate"
- crate_type = /obj/structure/closet/crate/wooden
-
-/datum/supply_pack/costumes_toys/randomised/toys
- name = "Toy Crate"
- desc = "Who cares about pride and accomplishment? Skip the gaming and get straight to the sweet rewards with this product! Contains five random toys. Warranty void if used to prank research directors."
- cost = 1500 // or play the arcade machines ya lazy bum
- num_contained = 5
- contains = list(/obj/item/storage/box/snappops,
- /obj/item/toy/talking/AI,
- /obj/item/toy/talking/codex_gigas,
- /obj/item/clothing/under/syndicate/tacticool,
- /obj/item/toy/sword ,
- /obj/item/toy/gun,
- /obj/item/gun/ballistic/shotgun/toy/crossbow,
- /obj/item/storage/box/fakesyndiesuit,
- /obj/item/storage/crayons,
- /obj/item/toy/spinningtoy,
- /obj/item/toy/prize/ripley,
- /obj/item/toy/prize/fireripley,
- /obj/item/toy/prize/deathripley,
- /obj/item/toy/prize/gygax,
- /obj/item/toy/prize/durand,
- /obj/item/toy/prize/honk,
- /obj/item/toy/prize/marauder,
- /obj/item/toy/prize/seraph,
- /obj/item/toy/prize/mauler,
- /obj/item/toy/prize/odysseus,
- /obj/item/toy/prize/phazon,
- /obj/item/toy/prize/reticence,
- /obj/item/toy/cards/deck,
- /obj/item/toy/nuke,
- /obj/item/toy/minimeteor,
- /obj/item/toy/redbutton,
- /obj/item/toy/talking/owl,
- /obj/item/toy/talking/griffin,
- /obj/item/coin/antagtoken,
- /obj/item/stack/tile/fakespace/loaded,
- /obj/item/stack/tile/fakepit/loaded,
- /obj/item/toy/toy_xeno,
- /obj/item/storage/box/actionfigure,
- /obj/item/restraints/handcuffs/fake,
- /obj/item/grenade/chem_grenade/glitter/pink,
- /obj/item/grenade/chem_grenade/glitter/blue,
- /obj/item/grenade/chem_grenade/glitter/white,
- /obj/item/toy/eightball,
- /obj/item/toy/windupToolbox,
- /obj/item/toy/clockwork_watch,
- /obj/item/toy/toy_dagger,
- /obj/item/extendohand/acme,
- /obj/item/hot_potato/harmless/toy,
- /obj/item/card/emagfake,
- /obj/item/clothing/shoes/wheelys,
- /obj/item/clothing/shoes/kindleKicks,
- /obj/item/storage/belt/military/snack,
- /obj/item/toy/eightball,
- /obj/item/vending_refill/donksoft)
- crate_name = "toy crate"
- crate_type = /obj/structure/closet/crate/wooden
-
-/datum/supply_pack/costumes_toys/randomised/plush
- name = "Plush Crate"
- desc = "Plush tide station wide. Contains 5 random plushies for you to love. Warranty void if your love violates the terms of use."
- cost = 1500 // or play the arcade machines ya lazy bum
- num_contained = 5
- contains = list(/obj/item/toy/plush/random,
- /obj/item/toy/plush/random,
- /obj/item/toy/plush/random,
- /obj/item/toy/plush/random,
- /obj/item/toy/plush/random) //I'm lazy
- crate_name = "plushie crate"
- crate_type = /obj/structure/closet/crate/wooden
-
-/datum/supply_pack/costumes_toys/wizard
- name = "Wizard Costume Crate"
- desc = "Pretend to join the Wizard Federation with this full wizard outfit! Nanotrasen would like to remind its employees that actually joining the Wizard Federation is subject to termination of job and life."
- cost = 2000
- contains = list(/obj/item/staff,
- /obj/item/clothing/suit/wizrobe/fake,
- /obj/item/clothing/shoes/sandal,
- /obj/item/clothing/head/wizard/fake)
- crate_name = "wizard costume crate"
- crate_type = /obj/structure/closet/crate/wooden
-
-/datum/supply_pack/costumes_toys/randomised/fill(obj/structure/closet/crate/C)
- var/list/L = contains.Copy()
- for(var/i in 1 to num_contained)
- var/item = pick_n_take(L)
- new item(C)
-
-/datum/supply_pack/costumes_toys/wardrobes/autodrobe
- name = "Autodrobe Supply Crate"
- desc = "Autodrobe missing your favorite dress? Solve that issue today with this autodrobe refill."
- cost = 1500
- contains = list(/obj/item/vending_refill/autodrobe)
- crate_name = "autodrobe supply crate"
-
-/datum/supply_pack/costumes_toys/wardrobes/cargo
- name = "Cargo Wardrobe Supply Crate"
- desc = "This crate contains a refill for the CargoDrobe."
- cost = 750
- contains = list(/obj/item/vending_refill/wardrobe/cargo_wardrobe)
- crate_name = "cargo department supply crate"
-
-/datum/supply_pack/costumes_toys/wardrobes/engineering
- name = "Engineering Wardrobe Supply Crate"
- desc = "This crate contains refills for the EngiDrobe and AtmosDrobe."
- cost = 1500
- contains = list(/obj/item/vending_refill/wardrobe/engi_wardrobe,
- /obj/item/vending_refill/wardrobe/atmos_wardrobe)
- crate_name = "engineering department wardrobe supply crate"
-
-/datum/supply_pack/costumes_toys/wardrobes/general
- name = "General Wardrobes Supply Crate"
- desc = "This crate contains refills for the CuraDrobe, BarDrobe, ChefDrobe, JaniDrobe, ChapDrobe."
- cost = 3750
- contains = list(/obj/item/vending_refill/wardrobe/curator_wardrobe,
- /obj/item/vending_refill/wardrobe/bar_wardrobe,
- /obj/item/vending_refill/wardrobe/chef_wardrobe,
- /obj/item/vending_refill/wardrobe/jani_wardrobe,
- /obj/item/vending_refill/wardrobe/chap_wardrobe)
- crate_name = "general wardrobes vendor refills"
-
-/datum/supply_pack/costumes_toys/wardrobes/hydroponics
- name = "Hydrobe Supply Crate"
- desc = "This crate contains a refill for the Hydrobe."
- cost = 750
- contains = list(/obj/item/vending_refill/wardrobe/hydro_wardrobe)
- crate_name = "hydrobe supply crate"
-
-/datum/supply_pack/costumes_toys/wardrobes/medical
- name = "Medical Wardrobe Supply Crate"
- desc = "This crate contains refills for the MediDrobe, ChemDrobe, GeneDrobe, and ViroDrobe."
- cost = 3000
- contains = list(/obj/item/vending_refill/wardrobe/medi_wardrobe,
- /obj/item/vending_refill/wardrobe/chem_wardrobe,
- /obj/item/vending_refill/wardrobe/gene_wardrobe,
- /obj/item/vending_refill/wardrobe/viro_wardrobe)
- crate_name = "medical department wardrobe supply crate"
-
-/datum/supply_pack/costumes_toys/wardrobes/science
- name = "Science Wardrobe Supply Crate"
- desc = "This crate contains refills for the SciDrobe and RoboDrobe."
- cost = 1500
- contains = list(/obj/item/vending_refill/wardrobe/robo_wardrobe,
- /obj/item/vending_refill/wardrobe/science_wardrobe)
- crate_name = "science department wardrobe supply crate"
-
-/datum/supply_pack/costumes_toys/wardrobes/security
- name = "Security Wardrobe Supply Crate"
- desc = "This crate contains refills for the SecDrobe and LawDrobe."
- cost = 1500
- contains = list(/obj/item/vending_refill/wardrobe/sec_wardrobe,
- /obj/item/vending_refill/wardrobe/law_wardrobe)
- crate_name = "security department supply crate"
-
-/datum/supply_pack/costumes_toys/kinkmate
- name = "Kinkmate construction kit"
- cost = 2000
- contraband = TRUE
- contains = list(/obj/item/vending_refill/kink, /obj/item/circuitboard/machine/kinkmate)
- crate_name = "Kinkmate construction kit"
-
-//////////////////////////////////////////////////////////////////////////////
-//////////////////////////// Miscellaneous ///////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////
-
-/datum/supply_pack/misc
- group = "Miscellaneous Supplies"
-
-/datum/supply_pack/misc/artsupply
- name = "Art Supplies"
- desc = "Make some happy little accidents with six canvasses, two easels, two boxes of crayons, and a rainbow crayon!"
- cost = 800
- contains = list(/obj/structure/easel,
- /obj/structure/easel,
- /obj/item/canvas/nineteenXnineteen,
- /obj/item/canvas/nineteenXnineteen,
- /obj/item/canvas/twentythreeXnineteen,
- /obj/item/canvas/twentythreeXnineteen,
- /obj/item/canvas/twentythreeXtwentythree,
- /obj/item/canvas/twentythreeXtwentythree,
- /obj/item/storage/crayons,
- /obj/item/storage/crayons,
- /obj/item/toy/crayon/rainbow,
- /obj/item/toy/crayon/white,
- /obj/item/toy/crayon/white)
- crate_name = "art supply crate"
- crate_type = /obj/structure/closet/crate/wooden
-
-/datum/supply_pack/misc/captain_pen
- name = "Captain Pen"
- desc = "A spare Captain fountain pen."
- access = ACCESS_CAPTAIN
- cost = 10000
- contains = list(/obj/item/pen/fountain/captain)
- crate_name = "captain pen"
- crate_type = /obj/structure/closet/crate/secure/weapon //It is a combat pen
-
-/datum/supply_pack/misc/bicycle
- name = "Bicycle"
- desc = "Nanotrasen reminds all employees to never toy with powers outside their control."
- cost = 1000000
- contains = list(/obj/vehicle/ridden/bicycle)
- crate_name = "Bicycle Crate"
- crate_type = /obj/structure/closet/crate/large
-
-/datum/supply_pack/misc/bigband
- name = "Big Band Instrument Collection"
- desc = "Get your sad station movin' and groovin' with this fine collection! Contains nine different instruments!"
- cost = 5000
- crate_name = "Big band musical instruments collection"
- contains = list(/obj/item/instrument/violin,
- /obj/item/instrument/guitar,
- /obj/item/instrument/glockenspiel,
- /obj/item/instrument/accordion,
- /obj/item/instrument/saxophone,
- /obj/item/instrument/trombone,
- /obj/item/instrument/recorder,
- /obj/item/instrument/harmonica,
- /obj/structure/piano/unanchored)
- crate_type = /obj/structure/closet/crate/wooden
-
-/datum/supply_pack/misc/book_crate
- name = "Book Crate"
- desc = "Surplus from the Nanotrasen Archives, these five books are sure to be good reads."
- cost = 1500
- contains = list(/obj/item/book/codex_gigas,
- /obj/item/book/manual/random/,
- /obj/item/book/manual/random/,
- /obj/item/book/manual/random/,
- /obj/item/book/random/triple)
- crate_type = /obj/structure/closet/crate/wooden
-
-/datum/supply_pack/misc/paper
- name = "Bureaucracy Crate"
- desc = "High stacks of papers on your desk Are a big problem - make it Pea-sized with these bureaucratic supplies! Contains five pens, some camera film, hand labeler supplies, a paper bin, three folders, two clipboards and two stamps as well as a briefcase."//that was too forced
- cost = 1500
- contains = list(/obj/structure/filingcabinet/chestdrawer/wheeled,
- /obj/item/camera_film,
- /obj/item/hand_labeler,
- /obj/item/hand_labeler_refill,
- /obj/item/hand_labeler_refill,
- /obj/item/paper_bin,
- /obj/item/pen/fourcolor,
- /obj/item/pen/fourcolor,
- /obj/item/pen,
- /obj/item/pen/blue,
- /obj/item/pen/red,
- /obj/item/folder/blue,
- /obj/item/folder/red,
- /obj/item/folder/yellow,
- /obj/item/clipboard,
- /obj/item/clipboard,
- /obj/item/stamp,
- /obj/item/stamp/denied,
- /obj/item/storage/briefcase)
- crate_name = "bureaucracy crate"
-
-/datum/supply_pack/misc/fountainpens
- name = "Calligraphy Crate"
- desc = "Sign death warrants in style with these seven executive fountain pens."
- cost = 700
- contains = list(/obj/item/storage/box/fountainpens,
- /obj/item/paper_bin)
- crate_type = /obj/structure/closet/crate/wooden
- crate_name = "calligraphy crate"
-
-/datum/supply_pack/misc/wrapping_paper
- name = "Festive Wrapping Paper Crate"
- desc = "Want to mail your loved ones gift-wrapped chocolates, stuffed animals, the Clown's severed head? You can do all that, with this crate full of wrapping paper."
- cost = 1000
- contains = list(/obj/item/stack/wrapping_paper)
- crate_type = /obj/structure/closet/crate/wooden
- crate_name = "festive wrapping paper crate"
-
-/datum/supply_pack/misc/paper_work
- name = "Freelance Paper work"
- desc = "The Nanotrasen Primary Bureaucratic Database Intelligence (PDBI) reports that the station has not completed its funding and grant paperwork this solar cycle. In order to gain further funding, your station is required to fill out (10) ten of these forms or no additional capital will be disbursed. We have sent you ten copies of the following form and we expect every one to be up to Nanotrasen Standards." // Disbursement. It's not a typo, look it up.
- cost = 700 // Net of 0 credits
- contains = list(/obj/item/folder/paperwork,
- /obj/item/folder/paperwork,
- /obj/item/folder/paperwork,
- /obj/item/folder/paperwork,
- /obj/item/folder/paperwork,
- /obj/item/folder/paperwork,
- /obj/item/folder/paperwork,
- /obj/item/folder/paperwork,
- /obj/item/folder/paperwork,
- /obj/item/folder/paperwork,
- /obj/item/pen/fountain,
- /obj/item/pen/fountain,
- /obj/item/pen/fountain,
- /obj/item/pen/fountain,
- /obj/item/pen/fountain)
- crate_name = "Paperwork"
-
-/datum/supply_pack/misc/funeral
- name = "Funeral Supply crate"
- desc = "At the end of the day, someone's gonna want someone dead. Give them a proper send-off with these funeral supplies! Contains a coffin with burial garmets and flowers."
- cost = 600
- contains = list(/obj/item/clothing/under/burial,
- /obj/item/reagent_containers/food/snacks/grown/harebell,
- /obj/item/reagent_containers/food/snacks/grown/poppy/geranium
- )
- crate_name = "coffin"
- crate_type = /obj/structure/closet/crate/coffin
-
-/datum/supply_pack/misc/jukebox
- name = "Jukebox"
- cost = 35000
- contains = list(/obj/machinery/jukebox)
- crate_name = "Jukebox"
-
-/datum/supply_pack/misc/lewd
- name = "Lewd Crate" // OwO
- desc = "Psss want to have a good time with your sluts? Well I got what you want maid clothing, dildos, collars and more!"
- cost = 5000
- contraband = TRUE
- contains = list(/obj/item/dildo/custom,
- /obj/item/dildo/custom,
- /obj/item/vending_refill/kink,
- /obj/item/vending_refill/kink,
- /obj/item/clothing/under/maid,
- /obj/item/clothing/under/maid,
- /obj/item/electropack/shockcollar,
- /obj/item/electropack/shockcollar,
- /obj/item/restraints/handcuffs/fake/kinky,
- /obj/item/restraints/handcuffs/fake/kinky,
- /obj/item/clothing/head/kitty/genuine, // Why its illegal
- /obj/item/clothing/head/kitty/genuine,
- /obj/item/storage/pill_bottle/penis_enlargement,
- /obj/structure/reagent_dispensers/keg/aphro)
- crate_name = "lewd kit"
- crate_type = /obj/structure/closet/crate
-
-/datum/supply_pack/misc/lewdkeg
- name = "Lewd Deluxe Keg"
- desc = "That other stuff not getting you ready? Well I have a Chemslut making tons of the good stuff."
- cost = 7000 //It can be a weapon
- contraband = TRUE
- contains = list(/obj/structure/reagent_dispensers/keg/aphro/strong)
- crate_name = "deluxe keg"
- crate_type = /obj/structure/closet/crate
-
-/datum/supply_pack/misc/religious_supplies
- name = "Religious Supplies Crate"
- desc = "Keep your local chaplain happy and well-supplied, lest they call down judgement upon your cargo bay. Contains two bottles of holywater, bibles, chaplain robes, and burial garmets."
- cost = 4000 // it costs so much because the Space Church is ran by Space Jews
- contains = list(/obj/item/reagent_containers/food/drinks/bottle/holywater,
- /obj/item/reagent_containers/food/drinks/bottle/holywater,
- /obj/item/storage/book/bible/booze,
- /obj/item/storage/book/bible/booze,
- /obj/item/clothing/suit/hooded/chaplain_hoodie,
- /obj/item/clothing/suit/hooded/chaplain_hoodie
- )
- crate_name = "religious supplies crate"
-
-/datum/supply_pack/misc/randomised/promiscuous
- name = "Promiscuous Organs"
- desc = "Do YOU want to have more genital? Well we have just the thing for you~. This crate has two autosurgeon, that will let you have a new sex, organ to impress that hot stud and or chick."
- cost = 4000 //Only get 2!
- contraband = TRUE
- var/num_contained = 2
- contains = list(/obj/item/autosurgeon/penis,
- /obj/item/autosurgeon/testicles,
- /obj/item/autosurgeon/vagina,
- /obj/item/autosurgeon/breasts,
- /obj/item/autosurgeon/womb)
- crate_name = "promiscuous organs"
-
-/datum/supply_pack/misc/toner
- name = "Toner Crate"
- desc = "Spent too much ink printing butt pictures? Fret not, with these six toner refills, you'll be printing butts 'till the cows come home!'"
- cost = 1000
- contains = list(/obj/item/toner,
- /obj/item/toner,
- /obj/item/toner,
- /obj/item/toner,
- /obj/item/toner,
- /obj/item/toner)
- crate_name = "toner crate"
diff --git a/code/modules/cargo/packs/armory.dm b/code/modules/cargo/packs/armory.dm
new file mode 100644
index 0000000000..ee983784fe
--- /dev/null
+++ b/code/modules/cargo/packs/armory.dm
@@ -0,0 +1,244 @@
+
+//Reminders-
+// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
+// cost = 700- Minimum cost, or infinite points are possible.
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////// Armory //////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/security/armory
+ group = "Armory"
+ access = ACCESS_ARMORY
+ crate_type = /obj/structure/closet/crate/secure/weapon
+
+/datum/supply_pack/security/armory/bulletarmor
+ name = "Bulletproof Armor Crate"
+ desc = "Contains three sets of bulletproof armor. Guaranteed to reduce a bullet's stopping power by over half. Requires Armory access to open."
+ cost = 1250
+ contains = list(/obj/item/clothing/suit/armor/bulletproof,
+ /obj/item/clothing/suit/armor/bulletproof,
+ /obj/item/clothing/suit/armor/bulletproof)
+ crate_name = "bulletproof armor crate"
+
+/datum/supply_pack/security/armory/bullethelmets
+ name = "Bulletproof Helmet Crate"
+ desc = "Contains three sets of bulletproof helmets. Guaranteed to reduce a bullet's stopping power by over half. Requires Armory access to open."
+ cost = 1250
+ contains = list(/obj/item/clothing/head/helmet/alt,
+ /obj/item/clothing/head/helmet/alt,
+ /obj/item/clothing/head/helmet/alt)
+ crate_name = "bulletproof helmet crate"
+
+/datum/supply_pack/security/armory/chemimp
+ name = "Chemical Implants Crate"
+ desc = "Contains five Remote Chemical implants. Requires Armory access to open."
+ cost = 1700
+ contains = list(/obj/item/storage/box/chemimp)
+ crate_name = "chemical implant crate"
+
+/datum/supply_pack/security/armory/combatknives
+ name = "Combat Knives Crate"
+ desc = "Contains three sharpened combat knives. Each knife guaranteed to fit snugly inside any Nanotrasen-standard boot. Requires Armory access to open."
+ cost = 3200
+ contains = list(/obj/item/kitchen/knife/combat,
+ /obj/item/kitchen/knife/combat,
+ /obj/item/kitchen/knife/combat)
+ crate_name = "combat knife crate"
+
+/datum/supply_pack/security/armory/ballistic
+ name = "Combat Shotguns Crate"
+ desc = "For when the enemy absolutely needs to be replaced with lead. Contains three Aussec-designed Combat Shotguns, with three Shotgun Bandoliers, as well as seven buchshot and 12g shotgun slugs. Requires Armory access to open."
+ cost = 8000
+ contains = list(/obj/item/gun/ballistic/shotgun/automatic/combat,
+ /obj/item/gun/ballistic/shotgun/automatic/combat,
+ /obj/item/gun/ballistic/shotgun/automatic/combat,
+ /obj/item/storage/belt/bandolier,
+ /obj/item/storage/belt/bandolier,
+ /obj/item/storage/belt/bandolier,
+ /obj/item/storage/box/lethalshot,
+ /obj/item/storage/box/lethalslugs)
+ crate_name = "combat shotguns crate"
+
+/datum/supply_pack/security/armory/dragnetgun
+ name = "DRAGnet gun Crate"
+ desc = "Contains two DRAGnet gun. A Dynamic Rapid-Apprehension of the Guilty net the revolution in law enforcement technology that YOU Want! Requires Armory access to open."
+ cost = 3250
+ contains = list(/obj/item/gun/energy/e_gun/dragnet,
+ /obj/item/gun/energy/e_gun/dragnet)
+ crate_name = "anti riot net guns crate"
+
+/datum/supply_pack/security/armory/energy
+ name = "Energy Guns Crate"
+ desc = "Contains three Energy Guns, capable of firing both nonlethal and lethal blasts of light. Requires Armory access to open."
+ cost = 3250
+ contains = list(/obj/item/gun/energy/e_gun,
+ /obj/item/gun/energy/e_gun,
+ /obj/item/gun/energy/e_gun)
+ crate_name = "energy gun crate"
+ crate_type = /obj/structure/closet/crate/secure/plasma
+
+/datum/supply_pack/security/armory/exileimp // Theres boxes in 2 lockers as well as gateway never realy being used sad
+ name = "Exile Implants Crate"
+ desc = "Contains five Exile implants. Requires Armory access to open."
+ cost = 1050 //stops endless points
+ contains = list(/obj/item/storage/box/exileimp)
+ crate_name = "exile implant crate"
+
+/datum/supply_pack/security/armory/mindshield
+ name = "Mindshield Implants Crate"
+ desc = "Prevent against radical thoughts with three Mindshield implants. Requires Armory access to open."
+ cost = 4000
+ contains = list(/obj/item/storage/lockbox/loyalty)
+ crate_name = "mindshield implant crate"
+
+/datum/supply_pack/security/armory/trackingimp
+ name = "Tracking Implants Crate"
+ desc = "Contains four tracking implants. Requires Armory access to open."
+ cost = 1050
+ contains = list(/obj/item/storage/box/trackimp)
+ crate_name = "tracking implant crate"
+
+/datum/supply_pack/security/armory/fire
+ name = "Incendiary Weapons Crate"
+ desc = "Burn, baby burn. Contains three incendiary grenades, seven incendiary slugs, three plasma canisters, and a flamethrower. Requires Brige access to open."
+ cost = 1750
+ access = ACCESS_HEADS
+ contains = list(/obj/item/flamethrower/full,
+ /obj/item/tank/internals/plasma,
+ /obj/item/tank/internals/plasma,
+ /obj/item/tank/internals/plasma,
+ /obj/item/grenade/chem_grenade/incendiary,
+ /obj/item/grenade/chem_grenade/incendiary,
+ /obj/item/grenade/chem_grenade/incendiary,
+ /obj/item/storage/box/fireshot)
+ crate_name = "incendiary weapons crate"
+ crate_type = /obj/structure/closet/crate/secure/plasma
+ dangerous = TRUE
+
+/datum/supply_pack/security/armory/miniguns
+ name = "Personal Miniature Energy Guns"
+ desc = "Contains three miniature energy guns. Each gun has a disabler and a lethal option. Requires Armory access to open."
+ cost = 3000
+ contains = list(/obj/item/gun/energy/e_gun/mini,
+ /obj/item/gun/energy/e_gun/mini,
+ /obj/item/gun/energy/e_gun/mini)
+ crate_name = "personal energy guns crate"
+ crate_type = /obj/structure/closet/crate/secure/plasma
+
+/datum/supply_pack/security/armory/laserarmor
+ name = "Reflector Vest Crate"
+ desc = "Contains two vests of highly reflective material. Each armor piece diffuses a laser's energy by over half, as well as offering a good chance to reflect the laser entirely. Requires Armory access to open."
+ cost = 2000
+ contains = list(/obj/item/clothing/suit/armor/laserproof,
+ /obj/item/clothing/suit/armor/laserproof)
+ crate_name = "reflector vest crate"
+ crate_type = /obj/structure/closet/crate/secure/plasma
+
+/datum/supply_pack/security/armory/riotarmor
+ name = "Riot Armor Crate"
+ desc = "Contains three sets of heavy body armor. Advanced padding protects against close-ranged weaponry, making melee attacks feel only half as potent to the user. Requires Armory access to open."
+ cost = 1750
+ contains = list(/obj/item/clothing/suit/armor/riot,
+ /obj/item/clothing/suit/armor/riot,
+ /obj/item/clothing/suit/armor/riot)
+ crate_name = "riot armor crate"
+
+/datum/supply_pack/security/armory/riothelmets
+ name = "Riot Helmets Crate"
+ desc = "Contains three riot helmets. Requires Armory access to open."
+ cost = 1750
+ contains = list(/obj/item/clothing/head/helmet/riot,
+ /obj/item/clothing/head/helmet/riot,
+ /obj/item/clothing/head/helmet/riot)
+ crate_name = "riot helmets crate"
+
+/datum/supply_pack/security/armory/riotshields
+ name = "Riot Shields Crate"
+ desc = "For when the greytide gets really uppity. Contains three riot shields. Requires Armory access to open."
+ cost = 2200
+ contains = list(/obj/item/shield/riot,
+ /obj/item/shield/riot,
+ /obj/item/shield/riot)
+ crate_name = "riot shields crate"
+
+/datum/supply_pack/security/armory/riotshotguns
+ name = "Riot Shotgun Crate"
+ desc = "For when the greytide gets really uppity. Contains three riot shotguns, seven rubber shot and beanbag shells. Requires Armory access to open."
+ cost = 6500
+ contains = list(/obj/item/gun/ballistic/shotgun/riot,
+ /obj/item/gun/ballistic/shotgun/riot,
+ /obj/item/gun/ballistic/shotgun/riot,
+ /obj/item/storage/box/rubbershot,
+ /obj/item/storage/box/beanbag)
+ crate_name = "riot shotgun crate"
+
+/datum/supply_pack/security/armory/swat
+ name = "SWAT Crate"
+ desc = "Contains two fullbody sets of tough, fireproof, pressurized suits designed in a joint effort by IS-ERI and Nanotrasen. Each set contains a suit, helmet, mask, combat belt, and combat gloves. Requires Armory access to open."
+ cost = 6000
+ contains = list(/obj/item/clothing/head/helmet/swat/nanotrasen,
+ /obj/item/clothing/head/helmet/swat/nanotrasen,
+ /obj/item/clothing/suit/space/swat,
+ /obj/item/clothing/suit/space/swat,
+ /obj/item/clothing/mask/gas/sechailer/swat,
+ /obj/item/clothing/mask/gas/sechailer/swat,
+ /obj/item/storage/belt/military/assault,
+ /obj/item/storage/belt/military/assault,
+ /obj/item/clothing/gloves/combat,
+ /obj/item/clothing/gloves/combat)
+ crate_name = "swat crate"
+
+/datum/supply_pack/security/armory/swattasers //Lesser AEG tbh
+ name = "SWAT tatical tasers Crate"
+ desc = "Contains two tactical energy gun, these guns are able to tase, disable and lethal as well as hold a seclight. Requires Armory access to open."
+ cost = 7000
+ contains = list(/obj/item/gun/energy/e_gun/stun,
+ /obj/item/gun/energy/e_gun/stun)
+ crate_name = "swat taser crate"
+
+/datum/supply_pack/security/armory/woodstock
+ name = "Classic WoodStock Shotguns Crate"
+ desc = "Contains three rustic, pumpaction shotguns. Requires Armory access to open."
+ cost = 3000
+ contains = list(/obj/item/gun/ballistic/shotgun,
+ /obj/item/gun/ballistic/shotgun,
+ /obj/item/gun/ballistic/shotgun)
+ crate_name = "woodstock shotguns crate"
+
+/datum/supply_pack/security/armory/wt550
+ name = "WT-550 Semi-Auto Rifle Crate"
+ desc = "Contains two high-powered, semiautomatic rifles chambered in 4.6x30mm. Requires Armory access to open."
+ cost = 2550
+ contains = list(/obj/item/gun/ballistic/automatic/wt550,
+ /obj/item/gun/ballistic/automatic/wt550)
+ crate_name = "auto rifle crate"
+
+/datum/supply_pack/security/armory/wt550ammo
+ name = "WT-550 Semi-Auto SMG Ammo Crate"
+ desc = "Contains four 20-round magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open."
+ cost = 1750
+ contains = list(/obj/item/ammo_box/magazine/wt550m9,
+ /obj/item/ammo_box/magazine/wt550m9,
+ /obj/item/ammo_box/magazine/wt550m9,
+ /obj/item/ammo_box/magazine/wt550m9)
+ crate_name = "auto rifle ammo crate"
+
+/datum/supply_pack/security/armory/wt550ammo_nonlethal // Takes around 12 shots to stun crit someone
+ name = "WT-550 Semi-Auto SMG Non-Lethal Ammo Crate"
+ desc = "Contains four 20-round magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open."
+ cost = 1000
+ contains = list(/obj/item/ammo_box/magazine/wt550m9/wtrubber,
+ /obj/item/ammo_box/magazine/wt550m9/wtrubber,
+ /obj/item/ammo_box/magazine/wt550m9/wtrubber,
+ /obj/item/ammo_box/magazine/wt550m9/wtrubber)
+ crate_name = "auto rifle ammo crate"
+
+/datum/supply_pack/security/armory/wt550ammo_special
+ name = "WT-550 Semi-Auto SMG Special Ammo Crate"
+ desc = "Contains 2 20-round Armour Piercing and Incendiary magazines for the WT-550 Semi-Auto SMG. Each magazine is designed to facilitate rapid tactical reloads. Requires Armory access to open."
+ cost = 3000
+ contains = list(/obj/item/ammo_box/magazine/wt550m9/wtap,
+ /obj/item/ammo_box/magazine/wt550m9/wtap,
+ /obj/item/ammo_box/magazine/wt550m9/wtic,
+ /obj/item/ammo_box/magazine/wt550m9/wtic)
+ crate_name = "auto rifle ammo crate"
diff --git a/code/modules/cargo/packs/costumes_toys.dm b/code/modules/cargo/packs/costumes_toys.dm
new file mode 100644
index 0000000000..40d21e4505
--- /dev/null
+++ b/code/modules/cargo/packs/costumes_toys.dm
@@ -0,0 +1,369 @@
+
+//Reminders-
+// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
+// cost = 700- Minimum cost, or infinite points are possible.
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////// Costumes & Toys /////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/costumes_toys
+ group = "Costumes & Toys"
+
+/datum/supply_pack/costumes_toys/randomised
+ name = "Collectable Hats Crate"
+ desc = "Flaunt your status with three unique, highly-collectable hats!"
+ cost = 20000
+ var/num_contained = 3 //number of items picked to be contained in a randomised crate
+ contains = list(/obj/item/clothing/head/collectable/chef,
+ /obj/item/clothing/head/collectable/paper,
+ /obj/item/clothing/head/collectable/tophat,
+ /obj/item/clothing/head/collectable/captain,
+ /obj/item/clothing/head/collectable/beret,
+ /obj/item/clothing/head/collectable/welding,
+ /obj/item/clothing/head/collectable/flatcap,
+ /obj/item/clothing/head/collectable/pirate,
+ /obj/item/clothing/head/collectable/kitty,
+ /obj/item/clothing/head/collectable/rabbitears,
+ /obj/item/clothing/head/collectable/wizard,
+ /obj/item/clothing/head/collectable/hardhat,
+ /obj/item/clothing/head/collectable/HoS,
+ /obj/item/clothing/head/collectable/HoP,
+ /obj/item/clothing/head/collectable/thunderdome,
+ /obj/item/clothing/head/collectable/swat,
+ /obj/item/clothing/head/collectable/slime,
+ /obj/item/clothing/head/collectable/police,
+ /obj/item/clothing/head/collectable/slime,
+ /obj/item/clothing/head/collectable/xenom,
+ /obj/item/clothing/head/collectable/petehat)
+ crate_name = "collectable hats crate"
+ crate_type = /obj/structure/closet/crate/wooden
+
+/datum/supply_pack/costumes_toys/randomised/contraband
+ name = "Contraband Crate"
+ desc = "Psst.. bud... want some contraband? I can get you a poster, some nice cigs, dank, even some sponsored items...you know, the good stuff. Just keep it away from the cops, kay?"
+ contraband = TRUE
+ cost = 3000
+ num_contained = 5 //SOME
+ contains = list(/obj/item/poster/random_contraband,
+ /obj/item/poster/random_contraband,
+ /obj/item/reagent_containers/food/snacks/grown/cannabis,
+ /obj/item/reagent_containers/food/snacks/grown/cannabis/rainbow,
+ /obj/item/reagent_containers/food/snacks/grown/cannabis/white,
+ /obj/item/storage/pill_bottle/zoom,
+ /obj/item/storage/pill_bottle/happy,
+ /obj/item/storage/pill_bottle/lsd,
+ /obj/item/storage/pill_bottle/aranesp,
+ /obj/item/storage/pill_bottle/stimulant,
+ /obj/item/toy/cards/deck/syndicate,
+ /obj/item/reagent_containers/food/drinks/bottle/absinthe,
+ /obj/item/clothing/under/syndicate/tacticool,
+ /obj/item/clothing/under/syndicate,
+ /obj/item/suppressor,
+ /obj/item/storage/fancy/cigarettes/cigpack_syndicate,
+ /obj/item/storage/fancy/cigarettes/cigpack_shadyjims,
+ /obj/item/clothing/mask/gas/syndicate,
+ /obj/item/clothing/neck/necklace/dope,
+ /obj/item/vending_refill/donksoft,
+ /obj/item/circuitboard/computer/arcade/amputation)
+ crate_name = "crate"
+
+/datum/supply_pack/costumes_toys/foamforce
+ name = "Foam Force Crate"
+ desc = "Break out the big guns with eight Foam Force shotguns!"
+ cost = 1000
+ contains = list(/obj/item/gun/ballistic/shotgun/toy,
+ /obj/item/gun/ballistic/shotgun/toy,
+ /obj/item/gun/ballistic/shotgun/toy,
+ /obj/item/gun/ballistic/shotgun/toy,
+ /obj/item/gun/ballistic/shotgun/toy,
+ /obj/item/gun/ballistic/shotgun/toy,
+ /obj/item/gun/ballistic/shotgun/toy,
+ /obj/item/gun/ballistic/shotgun/toy)
+ crate_name = "foam force crate"
+
+/datum/supply_pack/costumes_toys/foamforce/bonus
+ name = "Foam Force Pistols Crate"
+ desc = "Psst.. hey bud... remember those old foam force pistols that got discontinued for being too cool? Well I got two of those right here with your name on em. I'll even throw in a spare mag for each, waddya say?"
+ contraband = TRUE
+ cost = 4000
+ contains = list(/obj/item/gun/ballistic/automatic/toy/pistol,
+ /obj/item/gun/ballistic/automatic/toy/pistol,
+ /obj/item/ammo_box/magazine/toy/pistol,
+ /obj/item/ammo_box/magazine/toy/pistol)
+ crate_name = "foam force crate"
+
+/datum/supply_pack/costumes_toys/formalwear
+ name = "Formalwear Crate"
+ desc = "You're gonna like the way you look, I guaranteed it. Contains an asston of fancy clothing."
+ cost = 4750 //Lots of fancy clothing that can be sold back!
+ contains = list(/obj/item/clothing/under/blacktango,
+ /obj/item/clothing/under/assistantformal,
+ /obj/item/clothing/under/assistantformal,
+ /obj/item/clothing/under/lawyer/bluesuit,
+ /obj/item/clothing/suit/toggle/lawyer,
+ /obj/item/clothing/under/lawyer/purpsuit,
+ /obj/item/clothing/suit/toggle/lawyer/purple,
+ /obj/item/clothing/under/lawyer/blacksuit,
+ /obj/item/clothing/suit/toggle/lawyer/black,
+ /obj/item/clothing/accessory/waistcoat,
+ /obj/item/clothing/neck/tie/blue,
+ /obj/item/clothing/neck/tie/red,
+ /obj/item/clothing/neck/tie/black,
+ /obj/item/clothing/head/bowler,
+ /obj/item/clothing/head/fedora,
+ /obj/item/clothing/head/flatcap,
+ /obj/item/clothing/head/beret,
+ /obj/item/clothing/head/that,
+ /obj/item/clothing/shoes/laceup,
+ /obj/item/clothing/shoes/laceup,
+ /obj/item/clothing/shoes/laceup,
+ /obj/item/clothing/under/suit_jacket/charcoal,
+ /obj/item/clothing/under/suit_jacket/navy,
+ /obj/item/clothing/under/suit_jacket/burgundy,
+ /obj/item/clothing/under/suit_jacket/checkered,
+ /obj/item/clothing/under/suit_jacket/tan,
+ /obj/item/lipstick/random)
+ crate_name = "formalwear crate"
+ crate_type = /obj/structure/closet/crate/wooden
+
+/datum/supply_pack/costumes_toys/clownpin
+ name = "Hilarious Firing Pin Crate"
+ desc = "I uh... I'm not really sure what this does. Wanna buy it?"
+ cost = 5000
+ contraband = TRUE
+ contains = list(/obj/item/firing_pin/clown)
+ crate_name = "toy crate" // It's /technically/ a toy. For the clown, at least.
+ crate_type = /obj/structure/closet/crate/wooden
+
+/datum/supply_pack/costumes_toys/lasertag
+ name = "Laser Tag Crate"
+ desc = "Foam Force is for boys. Laser Tag is for men. Contains three sets of red suits, blue suits, matching helmets, and matching laser tag guns."
+ cost = 3500
+ contains = list(/obj/item/gun/energy/laser/redtag,
+ /obj/item/gun/energy/laser/redtag,
+ /obj/item/gun/energy/laser/redtag,
+ /obj/item/gun/energy/laser/bluetag,
+ /obj/item/gun/energy/laser/bluetag,
+ /obj/item/gun/energy/laser/bluetag,
+ /obj/item/clothing/suit/redtag,
+ /obj/item/clothing/suit/redtag,
+ /obj/item/clothing/suit/redtag,
+ /obj/item/clothing/suit/bluetag,
+ /obj/item/clothing/suit/bluetag,
+ /obj/item/clothing/suit/bluetag,
+ /obj/item/clothing/head/helmet/redtaghelm,
+ /obj/item/clothing/head/helmet/redtaghelm,
+ /obj/item/clothing/head/helmet/redtaghelm,
+ /obj/item/clothing/head/helmet/bluetaghelm,
+ /obj/item/clothing/head/helmet/bluetaghelm,
+ /obj/item/clothing/head/helmet/bluetaghelm)
+ crate_name = "laser tag crate"
+
+/datum/supply_pack/costumes_toys/lasertag/pins
+ name = "Laser Tag Firing Pins Crate"
+ desc = "Three laser tag firing pins used in laser-tag units to ensure users are wearing their vests."
+ cost = 3000
+ contraband = TRUE
+ contains = list(/obj/item/storage/box/lasertagpins)
+ crate_name = "laser tag crate"
+
+/datum/supply_pack/costumes_toys/costume_original
+ name = "Original Costume Crate"
+ desc = "Reenact Shakespearean plays with this assortment of outfits. Contains eight different costumes!"
+ cost = 1750
+ contains = list(/obj/item/clothing/head/snowman,
+ /obj/item/clothing/suit/snowman,
+ /obj/item/clothing/head/chicken,
+ /obj/item/clothing/suit/chickensuit,
+ /obj/item/clothing/mask/gas/monkeymask,
+ /obj/item/clothing/suit/monkeysuit,
+ /obj/item/clothing/head/cardborg,
+ /obj/item/clothing/suit/cardborg,
+ /obj/item/clothing/head/xenos,
+ /obj/item/clothing/suit/xenos,
+ /obj/item/clothing/suit/hooded/ian_costume,
+ /obj/item/clothing/suit/hooded/carp_costume,
+ /obj/item/clothing/suit/hooded/bee_costume)
+ crate_name = "original costume crate"
+ crate_type = /obj/structure/closet/crate/wooden
+
+/datum/supply_pack/costumes_toys/costume
+ name = "Standard Costume Crate"
+ desc = "Supply the station's entertainers with the equipment of their trade with these Nanotrasen-approved costumes! Contains a full clown and mime outfit, along with a bike horn and a bottle of nothing."
+ cost = 1300
+ access = ACCESS_THEATRE
+ contains = list(/obj/item/storage/backpack/clown,
+ /obj/item/clothing/shoes/clown_shoes,
+ /obj/item/clothing/mask/gas/clown_hat,
+ /obj/item/clothing/under/rank/clown,
+ /obj/item/bikehorn,
+ /obj/item/clothing/under/rank/mime,
+ /obj/item/clothing/shoes/sneakers/black,
+ /obj/item/clothing/gloves/color/white,
+ /obj/item/clothing/mask/gas/mime,
+ /obj/item/clothing/head/beret,
+ /obj/item/clothing/suit/suspenders,
+ /obj/item/reagent_containers/food/drinks/bottle/bottleofnothing,
+ /obj/item/storage/backpack/mime)
+ crate_name = "standard costume crate"
+ crate_type = /obj/structure/closet/crate/wooden
+
+/datum/supply_pack/costumes_toys/randomised/toys
+ name = "Toy Crate"
+ desc = "Who cares about pride and accomplishment? Skip the gaming and get straight to the sweet rewards with this product! Contains five random toys. Warranty void if used to prank research directors."
+ cost = 1500 // or play the arcade machines ya lazy bum
+ num_contained = 5
+ contains = list(/obj/item/storage/box/snappops,
+ /obj/item/toy/talking/AI,
+ /obj/item/toy/talking/codex_gigas,
+ /obj/item/clothing/under/syndicate/tacticool,
+ /obj/item/toy/sword ,
+ /obj/item/toy/gun,
+ /obj/item/gun/ballistic/shotgun/toy/crossbow,
+ /obj/item/storage/box/fakesyndiesuit,
+ /obj/item/storage/crayons,
+ /obj/item/toy/spinningtoy,
+ /obj/item/toy/prize/ripley,
+ /obj/item/toy/prize/fireripley,
+ /obj/item/toy/prize/deathripley,
+ /obj/item/toy/prize/gygax,
+ /obj/item/toy/prize/durand,
+ /obj/item/toy/prize/honk,
+ /obj/item/toy/prize/marauder,
+ /obj/item/toy/prize/seraph,
+ /obj/item/toy/prize/mauler,
+ /obj/item/toy/prize/odysseus,
+ /obj/item/toy/prize/phazon,
+ /obj/item/toy/prize/reticence,
+ /obj/item/toy/cards/deck,
+ /obj/item/toy/nuke,
+ /obj/item/toy/minimeteor,
+ /obj/item/toy/redbutton,
+ /obj/item/toy/talking/owl,
+ /obj/item/toy/talking/griffin,
+ /obj/item/coin/antagtoken,
+ /obj/item/stack/tile/fakespace/loaded,
+ /obj/item/stack/tile/fakepit/loaded,
+ /obj/item/toy/toy_xeno,
+ /obj/item/storage/box/actionfigure,
+ /obj/item/restraints/handcuffs/fake,
+ /obj/item/grenade/chem_grenade/glitter/pink,
+ /obj/item/grenade/chem_grenade/glitter/blue,
+ /obj/item/grenade/chem_grenade/glitter/white,
+ /obj/item/toy/eightball,
+ /obj/item/toy/windupToolbox,
+ /obj/item/toy/clockwork_watch,
+ /obj/item/toy/toy_dagger,
+ /obj/item/extendohand/acme,
+ /obj/item/hot_potato/harmless/toy,
+ /obj/item/card/emagfake,
+ /obj/item/clothing/shoes/wheelys,
+ /obj/item/clothing/shoes/kindleKicks,
+ /obj/item/storage/belt/military/snack,
+ /obj/item/toy/eightball,
+ /obj/item/vending_refill/donksoft)
+ crate_name = "toy crate"
+ crate_type = /obj/structure/closet/crate/wooden
+
+/datum/supply_pack/costumes_toys/randomised/plush
+ name = "Plush Crate"
+ desc = "Plush tide station wide. Contains 5 random plushies for you to love. Warranty void if your love violates the terms of use."
+ cost = 1500 // or play the arcade machines ya lazy bum
+ num_contained = 5
+ contains = list(/obj/item/toy/plush/random,
+ /obj/item/toy/plush/random,
+ /obj/item/toy/plush/random,
+ /obj/item/toy/plush/random,
+ /obj/item/toy/plush/random) //I'm lazy
+ crate_name = "plushie crate"
+ crate_type = /obj/structure/closet/crate/wooden
+
+/datum/supply_pack/costumes_toys/wizard
+ name = "Wizard Costume Crate"
+ desc = "Pretend to join the Wizard Federation with this full wizard outfit! Nanotrasen would like to remind its employees that actually joining the Wizard Federation is subject to termination of job and life."
+ cost = 2000
+ contains = list(/obj/item/staff,
+ /obj/item/clothing/suit/wizrobe/fake,
+ /obj/item/clothing/shoes/sandal,
+ /obj/item/clothing/head/wizard/fake)
+ crate_name = "wizard costume crate"
+ crate_type = /obj/structure/closet/crate/wooden
+
+/datum/supply_pack/costumes_toys/randomised/fill(obj/structure/closet/crate/C)
+ var/list/L = contains.Copy()
+ for(var/i in 1 to num_contained)
+ var/item = pick_n_take(L)
+ new item(C)
+
+/datum/supply_pack/costumes_toys/wardrobes/autodrobe
+ name = "Autodrobe Supply Crate"
+ desc = "Autodrobe missing your favorite dress? Solve that issue today with this autodrobe refill."
+ cost = 1500
+ contains = list(/obj/item/vending_refill/autodrobe)
+ crate_name = "autodrobe supply crate"
+
+/datum/supply_pack/costumes_toys/wardrobes/cargo
+ name = "Cargo Wardrobe Supply Crate"
+ desc = "This crate contains a refill for the CargoDrobe."
+ cost = 750
+ contains = list(/obj/item/vending_refill/wardrobe/cargo_wardrobe)
+ crate_name = "cargo department supply crate"
+
+/datum/supply_pack/costumes_toys/wardrobes/engineering
+ name = "Engineering Wardrobe Supply Crate"
+ desc = "This crate contains refills for the EngiDrobe and AtmosDrobe."
+ cost = 1500
+ contains = list(/obj/item/vending_refill/wardrobe/engi_wardrobe,
+ /obj/item/vending_refill/wardrobe/atmos_wardrobe)
+ crate_name = "engineering department wardrobe supply crate"
+
+/datum/supply_pack/costumes_toys/wardrobes/general
+ name = "General Wardrobes Supply Crate"
+ desc = "This crate contains refills for the CuraDrobe, BarDrobe, ChefDrobe, JaniDrobe, ChapDrobe."
+ cost = 3750
+ contains = list(/obj/item/vending_refill/wardrobe/curator_wardrobe,
+ /obj/item/vending_refill/wardrobe/bar_wardrobe,
+ /obj/item/vending_refill/wardrobe/chef_wardrobe,
+ /obj/item/vending_refill/wardrobe/jani_wardrobe,
+ /obj/item/vending_refill/wardrobe/chap_wardrobe)
+ crate_name = "general wardrobes vendor refills"
+
+/datum/supply_pack/costumes_toys/wardrobes/hydroponics
+ name = "Hydrobe Supply Crate"
+ desc = "This crate contains a refill for the Hydrobe."
+ cost = 750
+ contains = list(/obj/item/vending_refill/wardrobe/hydro_wardrobe)
+ crate_name = "hydrobe supply crate"
+
+/datum/supply_pack/costumes_toys/wardrobes/medical
+ name = "Medical Wardrobe Supply Crate"
+ desc = "This crate contains refills for the MediDrobe, ChemDrobe, GeneDrobe, and ViroDrobe."
+ cost = 3000
+ contains = list(/obj/item/vending_refill/wardrobe/medi_wardrobe,
+ /obj/item/vending_refill/wardrobe/chem_wardrobe,
+ /obj/item/vending_refill/wardrobe/gene_wardrobe,
+ /obj/item/vending_refill/wardrobe/viro_wardrobe)
+ crate_name = "medical department wardrobe supply crate"
+
+/datum/supply_pack/costumes_toys/wardrobes/science
+ name = "Science Wardrobe Supply Crate"
+ desc = "This crate contains refills for the SciDrobe and RoboDrobe."
+ cost = 1500
+ contains = list(/obj/item/vending_refill/wardrobe/robo_wardrobe,
+ /obj/item/vending_refill/wardrobe/science_wardrobe)
+ crate_name = "science department wardrobe supply crate"
+
+/datum/supply_pack/costumes_toys/wardrobes/security
+ name = "Security Wardrobe Supply Crate"
+ desc = "This crate contains refills for the SecDrobe and LawDrobe."
+ cost = 1500
+ contains = list(/obj/item/vending_refill/wardrobe/sec_wardrobe,
+ /obj/item/vending_refill/wardrobe/law_wardrobe)
+ crate_name = "security department supply crate"
+
+/datum/supply_pack/costumes_toys/kinkmate
+ name = "Kinkmate construction kit"
+ cost = 2000
+ contraband = TRUE
+ contains = list(/obj/item/vending_refill/kink, /obj/item/circuitboard/machine/kinkmate)
+ crate_name = "Kinkmate construction kit"
diff --git a/code/modules/cargo/packs/emergency.dm b/code/modules/cargo/packs/emergency.dm
new file mode 100644
index 0000000000..1987369d20
--- /dev/null
+++ b/code/modules/cargo/packs/emergency.dm
@@ -0,0 +1,275 @@
+
+//Reminders-
+// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
+// cost = 700- Minimum cost, or infinite points are possible.
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////// Emergency ///////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/emergency
+ group = "Emergency"
+
+/datum/supply_pack/emergency/vehicle
+ name = "Biker Gang Kit" //TUNNEL SNAKES OWN THIS TOWN
+ desc = "TUNNEL SNAKES OWN THIS TOWN. Contains an unbranded All Terrain Vehicle, and a complete gang outfit -- consists of black gloves, a menacing skull bandanna, and a SWEET leather overcoat!"
+ cost = 2500
+ contraband = TRUE
+ contains = list(/obj/vehicle/ridden/atv,
+ /obj/item/key,
+ /obj/item/clothing/suit/jacket/leather/overcoat,
+ /obj/item/clothing/gloves/color/black,
+ /obj/item/clothing/head/soft,
+ /obj/item/clothing/mask/bandana/skull)//so you can properly #cargoniabikergang
+ crate_name = "Biker Kit"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/emergency/equipment
+ name = "Emergency Bot/Internals Crate"
+ desc = "Explosions got you down? These supplies are guaranteed to patch up holes, in stations and people alike! Comes with two floorbots, two medbots, five oxygen masks and five small oxygen tanks."
+ cost = 2750
+ contains = list(/mob/living/simple_animal/bot/floorbot,
+ /mob/living/simple_animal/bot/floorbot,
+ /mob/living/simple_animal/bot/medbot,
+ /mob/living/simple_animal/bot/medbot,
+ /obj/item/tank/internals/air,
+ /obj/item/tank/internals/air,
+ /obj/item/tank/internals/air,
+ /obj/item/tank/internals/air,
+ /obj/item/tank/internals/air,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/mask/gas)
+ crate_name = "emergency crate"
+ crate_type = /obj/structure/closet/crate/internals
+
+/datum/supply_pack/emergency/radiatione_emergency
+ name = "Emergenc Radiation Protection Crate"
+ desc = "Survive the Nuclear Apocalypse and Supermatter Engine alike with two sets of Radiation suits. Each set contains a helmet, suit, and Geiger counter. We'll even throw in a few pill bottles that are able to handles radiation and the affects of the poisoning."
+ cost = 2500
+ contains = list(/obj/item/clothing/head/radiation,
+ /obj/item/clothing/head/radiation,
+ /obj/item/clothing/suit/radiation,
+ /obj/item/clothing/suit/radiation,
+ /obj/item/geiger_counter,
+ /obj/item/geiger_counter,
+ /obj/item/storage/pill_bottle/mutarad,
+ /obj/item/storage/firstaid/radbgone)
+ crate_name = "radiation protection crate"
+ crate_type = /obj/structure/closet/crate/radiation
+
+/datum/supply_pack/emergency/rcds
+ name = "Emergency RCDs"
+ desc = "Bombs going off on station? SME blown and now you need to fix the hole it left behind? Well this crate has a pare of Rcds to be able to easily fix up any problem you may have!"
+ cost = 1500
+ contains = list(/obj/item/construction/rcd,
+ /obj/item/construction/rcd)
+ crate_name = "emergency rcds"
+ crate_type = /obj/structure/closet/crate/internals
+
+/datum/supply_pack/emergency/soft_suit
+ name = "Emergency Space Suit "
+ desc = "Is there bombs going off left and right? Is there meteors shooting around the station? Well we have two fragile space suit for emergencys as well as air and masks."
+ cost = 1200
+ contains = list(/obj/item/tank/internals/air,
+ /obj/item/tank/internals/air,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/suit/space/fragile,
+ /obj/item/clothing/suit/space/fragile,
+ /obj/item/clothing/head/helmet/space/fragile,
+ /obj/item/clothing/head/helmet/space/fragile)
+ crate_name = "emergency crate"
+ crate_type = /obj/structure/closet/crate/internals
+
+/datum/supply_pack/emergency/firefighting
+ name = "Firefighting Crate"
+ desc = "Only you can prevent station fires. Partner up with two firefighter suits, gas masks, flashlights, large oxygen tanks, extinguishers, and hardhats!"
+ cost = 1200
+ contains = list(/obj/item/clothing/suit/fire/firefighter,
+ /obj/item/clothing/suit/fire/firefighter,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/mask/gas,
+ /obj/item/flashlight,
+ /obj/item/flashlight,
+ /obj/item/tank/internals/oxygen/red,
+ /obj/item/tank/internals/oxygen/red,
+ /obj/item/extinguisher/advanced,
+ /obj/item/extinguisher/advanced,
+ /obj/item/clothing/head/hardhat/red,
+ /obj/item/clothing/head/hardhat/red)
+ crate_name = "firefighting crate"
+
+/datum/supply_pack/emergency/atmostank
+ name = "Firefighting Tank Backpack"
+ desc = "Mow down fires with this high-capacity fire fighting tank backpack. Requires Atmospherics access to open."
+ cost = 1000
+ access = ACCESS_ATMOSPHERICS
+ contains = list(/obj/item/watertank/atmos)
+ crate_name = "firefighting backpack crate"
+ crate_type = /obj/structure/closet/crate/secure
+
+/datum/supply_pack/emergency/internals
+ name = "Internals Crate"
+ desc = "Master your life energy and control your breathing with three breath masks, three emergency oxygen tanks and three large air tanks."//IS THAT A
+ cost = 1000
+ contains = list(/obj/item/clothing/mask/gas,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/mask/breath,
+ /obj/item/clothing/mask/breath,
+ /obj/item/clothing/mask/breath,
+ /obj/item/tank/internals/emergency_oxygen,
+ /obj/item/tank/internals/emergency_oxygen,
+ /obj/item/tank/internals/emergency_oxygen,
+ /obj/item/tank/internals/air,
+ /obj/item/tank/internals/air,
+ /obj/item/tank/internals/air)
+ crate_name = "internals crate"
+ crate_type = /obj/structure/closet/crate/internals
+
+/datum/supply_pack/emergency/metalfoam
+ name = "Metal Foam Grenade Crate"
+ desc = "Seal up those pesky hull breaches with 14 Metal Foam Grenades."
+ cost = 1500
+ contains = list(/obj/item/storage/box/metalfoam,
+ /obj/item/storage/box/metalfoam)
+ crate_name = "metal foam grenade crate"
+
+/datum/supply_pack/emergency/syndicate
+ name = "NULL_ENTRY"
+ desc = "(#@&^$THIS PACKAGE CONTAINS 30TC WORTH OF SOME RANDOM SYNDICATE GEAR WE HAD LYING AROUND THE WAREHOUSE. GIVE EM HELL, OPERATIVE@&!*() "
+ hidden = TRUE
+ cost = 20000
+ contains = list()
+ crate_name = "emergency crate"
+ crate_type = /obj/structure/closet/crate/internals
+ dangerous = TRUE
+
+/datum/supply_pack/emergency/syndicate/fill(obj/structure/closet/crate/C)
+ var/crate_value = 30
+ var/list/uplink_items = get_uplink_items(SSticker.mode)
+ while(crate_value)
+ var/category = pick(uplink_items)
+ var/item = pick(uplink_items[category])
+ var/datum/uplink_item/I = uplink_items[category][item]
+ if(!I.surplus_nullcrates || prob(100 - I.surplus_nullcrates))
+ continue
+ if(crate_value < I.cost)
+ continue
+ crate_value -= I.cost
+ new I.item(C)
+
+/datum/supply_pack/emergency/plasma_spacesuit
+ name = "Plasmaman Space Envirosuits"
+ desc = "Contains two space-worthy envirosuits for Plasmamen. Order now and we'll throw in two free helmets! Requires EVA access to open."
+ cost = 4000
+ access = ACCESS_EVA
+ contains = list(/obj/item/clothing/suit/space/eva/plasmaman,
+ /obj/item/clothing/suit/space/eva/plasmaman,
+ /obj/item/clothing/head/helmet/space/plasmaman,
+ /obj/item/clothing/head/helmet/space/plasmaman)
+ crate_name = "plasmaman EVA crate"
+ crate_type = /obj/structure/closet/crate/secure
+
+/datum/supply_pack/emergency/plasmaman
+ name = "Plasmaman Supply Kit"
+ desc = "Keep those Plasmamen alive with two sets of Plasmaman outfits. Each set contains a plasmaman jumpsuit, internals tank, and helmet."
+ cost = 2000
+ contains = list(/obj/item/clothing/under/plasmaman,
+ /obj/item/clothing/under/plasmaman,
+ /obj/item/tank/internals/plasmaman/belt/full,
+ /obj/item/tank/internals/plasmaman/belt/full,
+ /obj/item/clothing/head/helmet/space/plasmaman,
+ /obj/item/clothing/head/helmet/space/plasmaman)
+ crate_name = "plasmaman supply kit"
+
+/datum/supply_pack/emergency/radiation
+ name = "Radiation Protection Crate"
+ desc = "Survive the Nuclear Apocalypse and Supermatter Engine alike with two sets of Radiation suits. Each set contains a helmet, suit, and Geiger counter. We'll even throw in a bottle of vodka and some glasses too, considering the life-expectancy of people who order this."
+ cost = 1300
+ contains = list(/obj/item/clothing/head/radiation,
+ /obj/item/clothing/head/radiation,
+ /obj/item/clothing/suit/radiation,
+ /obj/item/clothing/suit/radiation,
+ /obj/item/geiger_counter,
+ /obj/item/geiger_counter,
+ /obj/item/reagent_containers/food/drinks/bottle/vodka,
+ /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass,
+ /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass)
+ crate_name = "radiation protection crate"
+ crate_type = /obj/structure/closet/crate/radiation
+
+/datum/supply_pack/emergency/spacesuit
+ name = "Space Suit Crate"
+ desc = "Contains two aging suits from Space-Goodwill. Requires EVA access to open."
+ cost = 3000
+ access = ACCESS_EVA
+ contains = list(/obj/item/clothing/suit/space,
+ /obj/item/clothing/suit/space,
+ /obj/item/clothing/head/helmet/space,
+ /obj/item/clothing/head/helmet/space,
+ /obj/item/clothing/mask/breath,
+ /obj/item/clothing/mask/breath)
+ crate_name = "space suit crate"
+ crate_type = /obj/structure/closet/crate/secure
+
+/datum/supply_pack/emergency/spacejets
+ name = "Spare EVA Jetpacks"
+ desc = "Contains three EVA grade jectpaks. Requires EVA access to open."
+ cost = 2000
+ access = ACCESS_EVA
+ contains = list(/obj/item/tank/jetpack/carbondioxide/eva,
+ /obj/item/tank/jetpack/carbondioxide/eva,
+ /obj/item/tank/jetpack/carbondioxide/eva)
+ crate_name = "eva jetpacks crate"
+ crate_type = /obj/structure/closet/crate/secure
+
+/datum/supply_pack/emergency/specialops
+ name = "Special Ops Supplies"
+ desc = "(*!&@#TOO CHEAP FOR THAT NULL_ENTRY, HUH OPERATIVE? WELL, THIS LITTLE ORDER CAN STILL HELP YOU OUT IN A PINCH. CONTAINS A BOX OF FIVE EMP GRENADES, THREE SMOKEBOMBS, AN INCENDIARY GRENADE, AND A \"SLEEPY PEN\" FULL OF NICE TOXINS!#@*$"
+ hidden = TRUE
+ cost = 2200
+ contains = list(/obj/item/storage/box/emps,
+ /obj/item/grenade/smokebomb,
+ /obj/item/grenade/smokebomb,
+ /obj/item/grenade/smokebomb,
+ /obj/item/pen/sleepy,
+ /obj/item/grenade/chem_grenade/incendiary)
+ crate_name = "emergency crate"
+ crate_type = /obj/structure/closet/crate/internals
+
+/datum/supply_pack/emergency/weedcontrol
+ name = "Weed Control Crate"
+ desc = "Keep those invasive species OUT. Contains a scythe, gasmask, two sprays of Plant-B-Gone, and two anti-weed chemical grenades. Warranty void if used on ambrosia. Requires Hydroponics access to open."
+ cost = 1800
+ access = ACCESS_HYDROPONICS
+ contains = list(/obj/item/scythe,
+ /obj/item/clothing/mask/gas,
+ /obj/item/grenade/chem_grenade/antiweed,
+ /obj/item/grenade/chem_grenade/antiweed,
+ /obj/item/reagent_containers/spray/plantbgone,
+ /obj/item/reagent_containers/spray/plantbgone)
+ crate_name = "weed control crate"
+ crate_type = /obj/structure/closet/crate/secure/hydroponics
+
+/datum/supply_pack/medical/anitvirus
+ name = "Virus Containment Crate"
+ desc = "Viro let out a death plague Mk II again? Someone didnt wash there hands? Old plagues born anew? Well this crate is for you! Hope you cure it before it brakes out of the station... This crate needs medical access to open and has two bio suits, a box of needles and beakers, five spaceacillin needles, and a medibot."
+ cost = 3000
+ access = ACCESS_MEDICAL
+ contains = list(/mob/living/simple_animal/bot/medbot,
+ /obj/item/clothing/head/bio_hood,
+ /obj/item/clothing/head/bio_hood,
+ /obj/item/clothing/suit/bio_suit,
+ /obj/item/clothing/suit/bio_suit,
+ /obj/item/reagent_containers/syringe/antiviral,
+ /obj/item/reagent_containers/syringe/antiviral,
+ /obj/item/reagent_containers/syringe/antiviral,
+ /obj/item/reagent_containers/syringe/antiviral,
+ /obj/item/reagent_containers/syringe/antiviral,
+ /obj/item/storage/box/syringes,
+ /obj/item/storage/box/beakers)
+ crate_name = "virus containment unit crate"
+ crate_type = /obj/structure/closet/crate/secure/plasma
diff --git a/code/modules/cargo/packs/engine.dm b/code/modules/cargo/packs/engine.dm
new file mode 100644
index 0000000000..a4438c7ef8
--- /dev/null
+++ b/code/modules/cargo/packs/engine.dm
@@ -0,0 +1,169 @@
+
+//Reminders-
+// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
+// cost = 700- Minimum cost, or infinite points are possible.
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////// Engine Construction /////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/engine
+ group = "Engine Construction"
+ crate_type = /obj/structure/closet/crate/engineering
+
+/datum/supply_pack/engine/am_jar
+ name = "Antimatter Containment Jar Crate"
+ desc = "Two Antimatter containment jars stuffed into a single crate."
+ cost = 2300
+ contains = list(/obj/item/am_containment,
+ /obj/item/am_containment)
+ crate_name = "antimatter jar crate"
+
+/datum/supply_pack/engine/am_core
+ name = "Antimatter Control Crate"
+ desc = "The brains of the Antimatter engine, this device is sure to teach the station's powergrid the true meaning of real power."
+ cost = 5200
+ contains = list(/obj/machinery/power/am_control_unit)
+ crate_name = "antimatter control crate"
+
+/datum/supply_pack/engine/am_shielding
+ name = "Antimatter Shielding Crate"
+ desc = "Contains ten Antimatter shields, somehow crammed into a crate."
+ cost = 2500
+ contains = list(/obj/item/am_shielding_container,
+ /obj/item/am_shielding_container,
+ /obj/item/am_shielding_container,
+ /obj/item/am_shielding_container,
+ /obj/item/am_shielding_container,
+ /obj/item/am_shielding_container,
+ /obj/item/am_shielding_container,
+ /obj/item/am_shielding_container,
+ /obj/item/am_shielding_container,
+ /obj/item/am_shielding_container) //10 shields: 3x3 containment and a core
+ crate_name = "antimatter shielding crate"
+
+/datum/supply_pack/engine/emitter
+ name = "Emitter Crate"
+ desc = "Useful for powering forcefield generators while destroying locked crates and intruders alike. Contains two high-powered energy emitters. Requires CE access to open."
+ cost = 1750
+ access = ACCESS_CE
+ contains = list(/obj/machinery/power/emitter,
+ /obj/machinery/power/emitter)
+ crate_name = "emitter crate"
+ crate_type = /obj/structure/closet/crate/secure/engineering
+ dangerous = TRUE
+
+/datum/supply_pack/engine/field_gen
+ name = "Field Generator Crate"
+ desc = "Typically the only thing standing between the station and a messy death. Powered by emitters. Contains two field generators."
+ cost = 1750
+ contains = list(/obj/machinery/field/generator,
+ /obj/machinery/field/generator)
+ crate_name = "field generator crate"
+
+/datum/supply_pack/engine/grounding_rods
+ name = "Grounding Rod Crate"
+ desc = "Four grounding rods guaranteed to keep any uppity tesla's lightning under control."
+ cost = 2200
+ contains = list(/obj/machinery/power/grounding_rod,
+ /obj/machinery/power/grounding_rod,
+ /obj/machinery/power/grounding_rod,
+ /obj/machinery/power/grounding_rod)
+ crate_name = "grounding rod crate"
+ crate_type = /obj/structure/closet/crate/engineering/electrical
+
+/datum/supply_pack/engine/mason
+ name = "M.A.S.O.N RIG Crate"
+ desc = "The rare M.A.S.O.N RIG. Requires CE access to open."
+ cost = 15000
+ access = ACCESS_CE
+ contains = list(/obj/item/clothing/suit/space/hardsuit/ancient/mason)
+ crate_name = "M.A.S.O.N Rig"
+ crate_type = /obj/structure/closet/crate/secure/engineering
+
+/datum/supply_pack/engine/PA
+ name = "Particle Accelerator Crate"
+ desc = "A supermassive black hole or hyper-powered teslaball are the perfect way to spice up any party! This \"My First Apocalypse\" kit contains everything you need to build your own Particle Accelerator! Ages 10 and up."
+ cost = 3750
+ contains = list(/obj/structure/particle_accelerator/fuel_chamber,
+ /obj/machinery/particle_accelerator/control_box,
+ /obj/structure/particle_accelerator/particle_emitter/center,
+ /obj/structure/particle_accelerator/particle_emitter/left,
+ /obj/structure/particle_accelerator/particle_emitter/right,
+ /obj/structure/particle_accelerator/power_box,
+ /obj/structure/particle_accelerator/end_cap)
+ crate_name = "particle accelerator crate"
+
+/datum/supply_pack/engine/collector
+ name = "Radiation Collector Crate"
+ desc = "Contains three radiation collectors. Useful for collecting energy off nearby Supermatter Crystals, Singularities or Teslas!"
+ cost = 2750
+ contains = list(/obj/machinery/power/rad_collector,
+ /obj/machinery/power/rad_collector,
+ /obj/machinery/power/rad_collector)
+ crate_name = "collector crate"
+
+/datum/supply_pack/engine/sing_gen
+ name = "Singularity Generator Crate"
+ desc = "The key to unlocking the power of Lord Singuloth. Particle Accelerator not included."
+ cost = 6000
+ contains = list(/obj/machinery/the_singularitygen)
+ crate_name = "singularity generator crate"
+
+/datum/supply_pack/engine/solar
+ name = "Solar Panel Crate"
+ desc = "Go green with this DIY advanced solar array. Contains twenty one solar assemblies, a solar-control circuit board, and tracker. If you have any questions, please check out the enclosed instruction book."
+ cost = 2850
+ contains = list(/obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/solar_assembly,
+ /obj/item/circuitboard/computer/solar_control,
+ /obj/item/electronics/tracker,
+ /obj/item/paper/guides/jobs/engi/solars)
+ crate_name = "solar panel crate"
+ crate_type = /obj/structure/closet/crate/engineering/electrical
+
+/datum/supply_pack/engine/supermatter_shard
+ name = "Supermatter Shard Crate"
+ desc = "The power of the heavens condensed into a single crystal. Requires CE access to open."
+ cost = 10000
+ access = ACCESS_CE
+ contains = list(/obj/machinery/power/supermatter_crystal/shard)
+ crate_name = "supermatter shard crate"
+ crate_type = /obj/structure/closet/crate/secure/engineering
+ dangerous = TRUE
+
+/datum/supply_pack/engine/tesla_coils
+ name = "Tesla Coil Crate"
+ desc = "Whether it's high-voltage executions, creating research points, or just plain old power generation: This pack of four Tesla coils can do it all!"
+ cost = 3500
+ contains = list(/obj/machinery/power/tesla_coil,
+ /obj/machinery/power/tesla_coil,
+ /obj/machinery/power/tesla_coil,
+ /obj/machinery/power/tesla_coil)
+ crate_name = "tesla coil crate"
+ crate_type = /obj/structure/closet/crate/engineering/electrical
+
+/datum/supply_pack/engine/tesla_gen
+ name = "Tesla Generator Crate"
+ desc = "The key to unlocking the power of the Tesla energy ball. Particle Accelerator not included."
+ cost = 7000
+ contains = list(/obj/machinery/the_singularitygen/tesla)
+ crate_name = "tesla generator crate"
diff --git a/code/modules/cargo/packs/engineering.dm b/code/modules/cargo/packs/engineering.dm
new file mode 100644
index 0000000000..19cb53489e
--- /dev/null
+++ b/code/modules/cargo/packs/engineering.dm
@@ -0,0 +1,229 @@
+
+//Reminders-
+// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
+// cost = 700- Minimum cost, or infinite points are possible.
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////// Engineering /////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/engineering
+ group = "Engineering"
+ crate_type = /obj/structure/closet/crate/engineering
+
+/datum/supply_pack/engineering/shieldgen
+ name = "Anti-breach Shield Projector Crate"
+ desc = "Hull breaches again? Say no more with the Nanotrasen Anti-Breach Shield Projector! Uses forcefield technology to keep the air in, and the space out. Contains two shield projectors."
+ cost = 2500
+ contains = list(/obj/machinery/shieldgen,
+ /obj/machinery/shieldgen)
+ crate_name = "anti-breach shield projector crate"
+
+/datum/supply_pack/engineering/conveyor
+ name = "Conveyor Assembly Crate"
+ desc = "Keep production moving along with six conveyor belts. Conveyor switch included. If you have any questions, check out the enclosed instruction book."
+ cost = 750
+ contains = list(/obj/item/conveyor_construct,
+ /obj/item/conveyor_construct,
+ /obj/item/conveyor_construct,
+ /obj/item/conveyor_construct,
+ /obj/item/conveyor_construct,
+ /obj/item/conveyor_construct,
+ /obj/item/conveyor_switch_construct,
+ /obj/item/paper/guides/conveyor)
+ crate_name = "conveyor assembly crate"
+
+/datum/supply_pack/engineering/engiequipment
+ name = "Engineering Gear Crate"
+ desc = "Gear up with three toolbelts, high-visibility vests, welding helmets, hardhats, and two pairs of meson goggles!"
+ cost = 1500
+ contains = list(/obj/item/storage/belt/utility,
+ /obj/item/storage/belt/utility,
+ /obj/item/storage/belt/utility,
+ /obj/item/clothing/suit/hazardvest,
+ /obj/item/clothing/suit/hazardvest,
+ /obj/item/clothing/suit/hazardvest,
+ /obj/item/clothing/head/welding,
+ /obj/item/clothing/head/welding,
+ /obj/item/clothing/head/welding,
+ /obj/item/clothing/head/hardhat,
+ /obj/item/clothing/head/hardhat,
+ /obj/item/clothing/head/hardhat,
+ /obj/item/clothing/glasses/meson/engine,
+ /obj/item/clothing/glasses/meson/engine)
+ crate_name = "engineering gear crate"
+
+/datum/supply_pack/engineering/engihardsuit
+ name = "Engineering Hardsuit"
+ desc = "Poly 'Who stole all the hardsuits!' Well now you can get more hardsuits if needed! NOTE ONE HARDSUIT IS IN THIS CRATE, as well as one air tank and mask!"
+ cost = 2250
+ contains = list(/obj/item/tank/internals/air,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/suit/space/hardsuit/engine)
+ crate_name = "engineering hardsuit"
+
+/datum/supply_pack/engineering/atmoshardsuit
+ name = "Atmospherics Hardsuit"
+ desc = "Too many techs and not enough hardsuits? Time to buy some more! Comes with gas mask and air tank. Ask the CE to open."
+ cost = 5000
+ access = ACCESS_CE
+ contains = list(/obj/item/tank/internals/air,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/suit/space/hardsuit/engine/atmos)
+ crate_name = "atmospherics hardsuit"
+ crate_type = /obj/structure/closet/crate/secure/engineering
+
+/datum/supply_pack/engineering/industrialrcd
+ name = "Industrial RCD"
+ desc = "A industrial RCD in case the station has gone through more then one meteor storm and the CE needs to bring out the somthing a bit more reliable. Dose not contain spare ammo for the industrial RCD or any other RCD modles."
+ cost = 4500
+ access = ACCESS_CE
+ contains = list(/obj/item/construction/rcd/industrial)
+ crate_name = "industrial rcd"
+ crate_type = /obj/structure/closet/crate/secure/engineering
+
+/datum/supply_pack/engineering/powergamermitts
+ name = "Insulated Gloves Crate"
+ desc = "The backbone of modern society. Barely ever ordered for actual engineering. Contains three insulated gloves."
+ cost = 2300 //Made of pure-grade bullshittinium
+ contains = list(/obj/item/clothing/gloves/color/yellow,
+ /obj/item/clothing/gloves/color/yellow,
+ /obj/item/clothing/gloves/color/yellow)
+ crate_name = "insulated gloves crate"
+ crate_type = /obj/structure/closet/crate/engineering/electrical
+
+/obj/item/stock_parts/cell/inducer_supply
+ maxcharge = 5000
+ charge = 5000
+
+/datum/supply_pack/engineering/inducers
+ name = "NT-75 Electromagnetic Power Inducers Crate"
+ desc = "No rechargers? No problem, with the NT-75 EPI, you can recharge any standard cell-based equipment anytime, anywhere. Contains two Inducers."
+ cost = 2300
+ contains = list(/obj/item/inducer/sci {cell_type = /obj/item/stock_parts/cell/inducer_supply; opened = 0}, /obj/item/inducer/sci {cell_type = /obj/item/stock_parts/cell/inducer_supply; opened = 0}) //FALSE doesn't work in modified type paths apparently.
+ crate_name = "inducer crate"
+ crate_type = /obj/structure/closet/crate/engineering/electrical
+
+/datum/supply_pack/engineering/pacman
+ name = "P.A.C.M.A.N Generator Crate"
+ desc = "Engineers can't set up the engine? Not an issue for you, once you get your hands on this P.A.C.M.A.N. Generator! Takes in plasma and spits out sweet sweet energy."
+ cost = 2250
+ contains = list(/obj/machinery/power/port_gen/pacman)
+ crate_name = "PACMAN generator crate"
+ crate_type = /obj/structure/closet/crate/engineering/electrical
+
+/datum/supply_pack/engineering/power
+ name = "Power Cell Crate"
+ desc = "Looking for power overwhelming? Look no further. Contains three high-voltage power cells."
+ cost = 1000
+ contains = list(/obj/item/stock_parts/cell/high,
+ /obj/item/stock_parts/cell/high,
+ /obj/item/stock_parts/cell/high)
+ crate_name = "power cell crate"
+ crate_type = /obj/structure/closet/crate/engineering/electrical
+
+
+/datum/supply_pack/engineering/siezedpower
+ name = "Siezed Power Cell Crate"
+ desc = "We took the means of power! Contains three high-voltage plus power cells."
+ cost = 1300
+ contraband = TRUE
+ contains = list(/obj/item/stock_parts/cell/high/plus,
+ /obj/item/stock_parts/cell/high/plus,
+ /obj/item/stock_parts/cell/high/plus)
+ crate_name = "siezed crate"
+ crate_type = /obj/structure/closet/crate/engineering/electrical
+
+/datum/supply_pack/engineering/shuttle_engine
+ name = "Shuttle Engine Crate"
+ desc = "Through advanced bluespace-shenanigans, our engineers have managed to fit an entire shuttle engine into one tiny little crate. Requires CE access to open."
+ cost = 5000
+ access = ACCESS_CE
+ contains = list(/obj/structure/shuttle/engine/propulsion/burst/cargo)
+ crate_name = "shuttle engine crate"
+ crate_type = /obj/structure/closet/crate/secure/engineering
+
+/datum/supply_pack/engineering/siezedproduction
+ name = "The Means of Production"
+ desc = "We will win for we have took over the production! S five metal sheets, five wire, three matter bins, one manipulater and one sheet of glass."
+ cost = 1500
+ contraband = TRUE
+ contains = list(/obj/item/stock_parts/cell/high/plus,
+ /obj/item/circuitboard/machine/autolathe,
+ /obj/item/stack/cable_coil/random/five,
+ /obj/item/stack/sheet/metal/five,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/stock_parts/matter_bin,
+ /obj/item/stock_parts/manipulator,
+ /obj/item/stack/sheet/glass,)
+ crate_name = "siezed crate"
+
+/datum/supply_pack/engineering/tools
+ name = "Toolbox Crate"
+ desc = "Any robust spaceman is never far from their trusty toolbox. Contains three electrical toolboxes and three mechanical toolboxes."
+ contains = list(/obj/item/storage/toolbox/electrical,
+ /obj/item/storage/toolbox/electrical,
+ /obj/item/storage/toolbox/electrical,
+ /obj/item/storage/toolbox/mechanical,
+ /obj/item/storage/toolbox/mechanical,
+ /obj/item/storage/toolbox/mechanical)
+ cost = 1200
+ crate_name = "toolbox crate"
+
+/datum/supply_pack/engineering/bsa
+ name = "Bluespace Artillery Parts"
+ desc = "The pride of Nanotrasen Naval Command. The legendary Bluespace Artillery Cannon is a devastating feat of human engineering and testament to wartime determination. Highly advanced research is required for proper construction. "
+ cost = 15000
+ special = TRUE
+ contains = list(/obj/item/circuitboard/machine/bsa/front,
+ /obj/item/circuitboard/machine/bsa/middle,
+ /obj/item/circuitboard/machine/bsa/back,
+ /obj/item/circuitboard/computer/bsa_control
+ )
+ crate_name= "bluespace artillery parts crate"
+
+/datum/supply_pack/engineering/dna_vault
+ name = "DNA Vault Parts"
+ desc = "Secure the longevity of the current state of humanity within this massive library of scientific knowledge, capable of granting superhuman powers and abilities. Highly advanced research is required for proper construction. Also contains five DNA probes."
+ cost = 12000
+ special = TRUE
+ contains = list(
+ /obj/item/circuitboard/machine/dna_vault,
+ /obj/item/dna_probe,
+ /obj/item/dna_probe,
+ /obj/item/dna_probe,
+ /obj/item/dna_probe,
+ /obj/item/dna_probe
+ )
+ crate_name= "dna vault parts crate"
+
+/datum/supply_pack/engineering/dna_probes
+ name = "DNA Vault Samplers"
+ desc = "Contains five DNA probes for use in the DNA vault."
+ cost = 3000
+ special = TRUE
+ contains = list(/obj/item/dna_probe,
+ /obj/item/dna_probe,
+ /obj/item/dna_probe,
+ /obj/item/dna_probe,
+ /obj/item/dna_probe
+ )
+ crate_name= "dna samplers crate"
+
+/datum/supply_pack/engineering/shield_sat
+ name = "Shield Generator Satellite"
+ desc = "Protect the very existence of this station with these Anti-Meteor defenses. Contains three Shield Generator Satellites."
+ cost = 4000
+ contains = list(
+ /obj/machinery/satellite/meteor_shield,
+ /obj/machinery/satellite/meteor_shield,
+ /obj/machinery/satellite/meteor_shield
+ )
+ crate_name= "shield sat crate"
+
+/datum/supply_pack/engineering/shield_sat_control
+ name = "Shield System Control Board"
+ desc = "A control system for the Shield Generator Satellite system."
+ cost = 4000
+ contains = list(/obj/item/circuitboard/computer/sat_control)
+ crate_name= "shield control board crate"
diff --git a/code/modules/cargo/packs/livestock.dm b/code/modules/cargo/packs/livestock.dm
new file mode 100644
index 0000000000..8708562a06
--- /dev/null
+++ b/code/modules/cargo/packs/livestock.dm
@@ -0,0 +1,147 @@
+
+//Reminders-
+// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
+// cost = 700- Minimum cost, or infinite points are possible.
+//////////////////////////////////////////////////////////////////////////////
+////////////////////////////// Livestock /////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/critter
+ group = "Livestock"
+ crate_type = /obj/structure/closet/crate/critter
+
+/datum/supply_pack/critter/butterfly
+ name = "Butterflies Crate"
+ desc = "Not a very dangerous insect, but they do give off a better image than, say, flies or cockroaches."//is that a motherfucking worm reference
+ contraband = TRUE
+ cost = 5000
+ contains = list(/mob/living/simple_animal/butterfly)
+ crate_name = "entomology samples crate"
+
+/datum/supply_pack/critter/butterfly/generate()
+ . = ..()
+ for(var/i in 1 to 49)
+ new /mob/living/simple_animal/butterfly(.)
+
+/datum/supply_pack/critter/cat
+ name = "Cat Crate"
+ desc = "The cat goes meow! Comes with a collar and a nice cat toy! Cheeseburger not included."//i can't believe im making this reference
+ cost = 5000 //Cats are worth as much as corgis.
+ contains = list(/mob/living/simple_animal/pet/cat,
+ /obj/item/clothing/neck/petcollar,
+ /obj/item/toy/cattoy)
+ crate_name = "cat crate"
+
+/datum/supply_pack/critter/cat/generate()
+ . = ..()
+ if(prob(50))
+ var/mob/living/simple_animal/pet/cat/C = locate() in .
+ qdel(C)
+ new /mob/living/simple_animal/pet/cat/Proc(.)
+
+/datum/supply_pack/critter/chick
+ name = "Chicken Crate"
+ desc = "The chicken goes bwaak!"
+ cost = 2000
+ contains = list( /mob/living/simple_animal/chick)
+ crate_name = "chicken crate"
+
+/datum/supply_pack/critter/crab
+ name = "Crab Rocket"
+ desc = "CRAAAAAAB ROCKET. CRAB ROCKET. CRAB ROCKET. CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB ROCKET. CRAFT. ROCKET. BUY. CRAFT ROCKET. CRAB ROOOCKET. CRAB ROOOOCKET. CRAB CRAB CRAB CRAB CRAB CRAB CRAB CRAB ROOOOOOOOOOOOOOOOOOOOOOCK EEEEEEEEEEEEEEEEEEEEEEEEE EEEETTTTTTTTTTTTAAAAAAAAA AAAHHHHHHHHHHHHH. CRAB ROCKET. CRAAAB ROCKEEEEEEEEEGGGGHHHHTT CRAB CRAB CRAABROCKET CRAB ROCKEEEET."//fun fact: i actually spent like 10 minutes and transcribed the entire video.
+ cost = 5000
+ contains = list(/mob/living/simple_animal/crab)
+ crate_name = "look sir free crabs"
+ DropPodOnly = TRUE
+
+/datum/supply_pack/critter/crab/generate()
+ . = ..()
+ for(var/i in 1 to 49)
+ new /mob/living/simple_animal/crab(.)
+
+/datum/supply_pack/critter/corgi
+ name = "Corgi Crate"
+ desc = "Considered the optimal dog breed by thousands of research scientists, this Corgi is but one dog from the millions of Ian's noble bloodline. Comes with a cute collar!"
+ cost = 5000
+ contains = list(/mob/living/simple_animal/pet/dog/corgi,
+ /obj/item/clothing/neck/petcollar)
+ crate_name = "corgi crate"
+
+/datum/supply_pack/critter/corgi/generate()
+ . = ..()
+ if(prob(50))
+ var/mob/living/simple_animal/pet/dog/corgi/D = locate() in .
+ if(D.gender == FEMALE)
+ qdel(D)
+ new /mob/living/simple_animal/pet/dog/corgi/Lisa(.)
+
+/datum/supply_pack/critter/corgis/exotic
+ name = "Exotic Corgi Crate"
+ desc = "Corgis fit for a king, these corgis come in a unique color to signify their superiority. Comes with a cute collar!"
+ cost = 5500
+ contains = list(/mob/living/simple_animal/pet/dog/corgi/exoticcorgi,
+ /obj/item/clothing/neck/petcollar)
+ crate_name = "exotic corgi crate"
+
+/datum/supply_pack/critter/cow
+ name = "Cow Crate"
+ desc = "The cow goes moo!"
+ cost = 3000
+ contains = list(/mob/living/simple_animal/cow)
+ crate_name = "cow crate"
+
+/datum/supply_pack/critter/fox
+ name = "Fox Crate"
+ desc = "The fox goes...? Comes with a collar!"//what does the fox say
+ cost = 5000
+ contains = list(/mob/living/simple_animal/pet/fox,
+ /obj/item/clothing/neck/petcollar)
+ crate_name = "fox crate"
+
+/datum/supply_pack/critter/goat
+ name = "Goat Crate"
+ desc = "The goat goes baa! Warranty void if used as a replacement for Pete."
+ cost = 2500
+ contains = list(/mob/living/simple_animal/hostile/retaliate/goat)
+ crate_name = "goat crate"
+
+/datum/supply_pack/critter/goose
+ name = "Goose Crate"
+ desc = "Angry and violent birds. Evil, evil creatures."
+ cost = 2500
+ contains = list(/mob/living/simple_animal/hostile/retaliate/goose)
+ crate_name = "goose crate"
+
+/datum/supply_pack/critter/pug
+ name = "Pug Crate"
+ desc = "Like a normal dog, but... squished. Comes with a nice collar!"
+ cost = 5000
+ contains = list(/mob/living/simple_animal/pet/dog/pug,
+ /obj/item/clothing/neck/petcollar)
+ crate_name = "pug crate"
+
+/datum/supply_pack/organic/critter/kiwi
+ name = "Space kiwi Crate"
+ cost = 2000
+ contains = list( /mob/living/simple_animal/kiwi)
+ crate_name = "space kiwi crate"
+
+/datum/supply_pack/critter/snake
+ name = "Snake Crate"
+ desc = "Tired of these MOTHER FUCKING snakes on this MOTHER FUCKING space station? Then this isn't the crate for you. Contains three poisonous snakes."
+ cost = 3000
+ contains = list(/mob/living/simple_animal/hostile/retaliate/poison/snake,
+ /mob/living/simple_animal/hostile/retaliate/poison/snake,
+ /mob/living/simple_animal/hostile/retaliate/poison/snake)
+ crate_name = "snake crate"
+
+/datum/supply_pack/critter/secbat
+ name = "Security Bat Crate"
+ desc = "Contains five security bats, perfect to Bat-up any security officer."
+ cost = 2500
+ contains = list(/mob/living/simple_animal/hostile/retaliate/bat/secbat,
+ /mob/living/simple_animal/hostile/retaliate/bat/secbat,
+ /mob/living/simple_animal/hostile/retaliate/bat/secbat,
+ /mob/living/simple_animal/hostile/retaliate/bat/secbat,
+ /mob/living/simple_animal/hostile/retaliate/bat/secbat)
+ crate_name = "security bat crate"
diff --git a/code/modules/cargo/packs/materials.dm b/code/modules/cargo/packs/materials.dm
new file mode 100644
index 0000000000..0f8ad2462a
--- /dev/null
+++ b/code/modules/cargo/packs/materials.dm
@@ -0,0 +1,170 @@
+
+//Reminders-
+// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
+// cost = 700- Minimum cost, or infinite points are possible.
+//////////////////////////////////////////////////////////////////////////////
+/////////////////////// Canisters & Materials ////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/materials
+ group = "Canisters & Materials"
+
+/datum/supply_pack/materials/cardboard50
+ name = "50 Cardboard Sheets"
+ desc = "Create a bunch of boxes."
+ cost = 1000
+ contains = list(/obj/item/stack/sheet/cardboard/fifty)
+ crate_name = "cardboard sheets crate"
+
+/datum/supply_pack/materials/glass50
+ name = "50 Glass Sheets"
+ desc = "Let some nice light in with fifty glass sheets!"
+ cost = 850
+ contains = list(/obj/item/stack/sheet/glass/fifty)
+ crate_name = "glass sheets crate"
+
+/datum/supply_pack/materials/metal50
+ name = "50 Metal Sheets"
+ desc = "Any construction project begins with a good stack of fifty metal sheets!"
+ cost = 850
+ contains = list(/obj/item/stack/sheet/metal/fifty)
+ crate_name = "metal sheets crate"
+
+/datum/supply_pack/materials/plasteel20
+ name = "20 Plasteel Sheets"
+ desc = "Reinforce the station's integrity with twenty plasteel sheets!"
+ cost = 4700
+ contains = list(/obj/item/stack/sheet/plasteel/twenty)
+ crate_name = "plasteel sheets crate"
+
+/datum/supply_pack/materials/plasteel50
+ name = "50 Plasteel Sheets"
+ desc = "For when you REALLY have to reinforce something."
+ cost = 9050
+ contains = list(/obj/item/stack/sheet/plasteel/fifty)
+ crate_name = "plasteel sheets crate"
+
+/datum/supply_pack/materials/plastic50
+ name = "50 Plastic Sheets"
+ desc = "Build a limitless amount of toys with fifty plastic sheets!"
+ cost = 950
+ contains = list(/obj/item/stack/sheet/plastic/fifty)
+ crate_name = "plastic sheets crate"
+
+/datum/supply_pack/materials/sandstone30
+ name = "30 Sandstone Blocks"
+ desc = "Neither sandy nor stoney, these thirty blocks will still get the job done."
+ cost = 800
+ contains = list(/obj/item/stack/sheet/mineral/sandstone/thirty)
+ crate_name = "sandstone blocks crate"
+
+/datum/supply_pack/materials/wood50
+ name = "50 Wood Planks"
+ desc = "Turn cargo's boring metal groundwork into beautiful panelled flooring and much more with fifty wooden planks!"
+ cost = 1450
+ contains = list(/obj/item/stack/sheet/mineral/wood/fifty)
+ crate_name = "wood planks crate"
+
+/datum/supply_pack/materials/rcdammo
+ name = "Spare RDC ammo"
+ desc = "This crate contains sixteen RCD ammo packs, to help with any holes or projects people mite be working on."
+ cost = 3750
+ contains = list(/obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo,
+ /obj/item/rcd_ammo)
+ crate_name = "rcd ammo"
+
+/datum/supply_pack/materials/bz
+ name = "BZ Canister Crate"
+ desc = "Contains a canister of BZ. Requires Toxins access to open."
+ cost = 7500 // Costs 3 credits more than what you can get for selling it.
+ access = ACCESS_TOX_STORAGE
+ contains = list(/obj/machinery/portable_atmospherics/canister/bz)
+ crate_name = "BZ canister crate"
+ crate_type = /obj/structure/closet/crate/secure/science
+
+/datum/supply_pack/materials/carbon_dio
+ name = "Carbon Dioxide Canister"
+ desc = "Contains a canister of Carbon Dioxide."
+ cost = 3000
+ contains = list(/obj/machinery/portable_atmospherics/canister/carbon_dioxide)
+ crate_name = "carbon dioxide canister crate"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/materials/nitrogen
+ name = "Nitrogen Canister"
+ desc = "Contains a canister of Nitrogen."
+ cost = 2000
+ contains = list(/obj/machinery/portable_atmospherics/canister/nitrogen)
+ crate_name = "nitrogen canister crate"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/materials/nitrous_oxide_canister
+ name = "Nitrous Oxide Canister"
+ desc = "Contains a canister of Nitrous Oxide. Requires Atmospherics access to open."
+ cost = 3000
+ access = ACCESS_ATMOSPHERICS
+ contains = list(/obj/machinery/portable_atmospherics/canister/nitrous_oxide)
+ crate_name = "nitrous oxide canister crate"
+ crate_type = /obj/structure/closet/crate/secure
+
+/datum/supply_pack/materials/oxygen
+ name = "Oxygen Canister"
+ desc = "Contains a canister of Oxygen. Canned in Druidia."
+ cost = 1500
+ contains = list(/obj/machinery/portable_atmospherics/canister/oxygen)
+ crate_name = "oxygen canister crate"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/materials/water_vapor
+ name = "Water Vapor Canister"
+ desc = "Contains a canister of Water Vapor. I swear to god if you open this in the halls..."
+ cost = 2500
+ contains = list(/obj/machinery/portable_atmospherics/canister/water_vapor)
+ crate_name = "water vapor canister crate"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/materials/fueltank
+ name = "Fuel Tank Crate"
+ desc = "Contains a welding fuel tank. Caution, highly flammable."
+ cost = 800
+ contains = list(/obj/structure/reagent_dispensers/fueltank)
+ crate_name = "fuel tank crate"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/materials/watertank
+ name = "Water Tank Crate"
+ desc = "Contains a tank of dihydrogen monoxide... sounds dangerous."
+ cost = 600
+ contains = list(/obj/structure/reagent_dispensers/watertank)
+ crate_name = "water tank crate"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/materials/foamtank
+ name = "Firefighting Foam Tank Crate"
+ desc = "Contains a tank of firefighting foam. Also known as \"plasmaman's bane\"."
+ cost = 1500
+ contains = list(/obj/structure/reagent_dispensers/foamtank)
+ crate_name = "foam tank crate"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/materials/hightank
+ name = "Large Water Tank Crate"
+ desc = "Contains a high-capacity water tank. Useful for botany or other service jobs."
+ cost = 1200
+ contains = list(/obj/structure/reagent_dispensers/watertank/high)
+ crate_name = "high-capacity water tank crate"
+ crate_type = /obj/structure/closet/crate/large
diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm
new file mode 100644
index 0000000000..656474cc1d
--- /dev/null
+++ b/code/modules/cargo/packs/medical.dm
@@ -0,0 +1,228 @@
+
+//Reminders-
+// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
+// cost = 700- Minimum cost, or infinite points are possible.
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////// Medical /////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/medical
+ group = "Medical"
+ crate_type = /obj/structure/closet/crate/medical
+
+/datum/supply_pack/medical/firstaidbruises
+ name = "Bruise Treatment Kit Crate"
+ desc = "Contains three first aid kits focused on healing bruises and broken bones."
+ cost = 1000
+ contains = list(/obj/item/storage/firstaid/brute,
+ /obj/item/storage/firstaid/brute,
+ /obj/item/storage/firstaid/brute)
+ crate_name = "brute treatment kit crate"
+
+/datum/supply_pack/medical/firstaidburns
+ name = "Burn Treatment Kit Crate"
+ desc = "Contains three first aid kits focused on healing severe burns."
+ cost = 1000
+ contains = list(/obj/item/storage/firstaid/fire,
+ /obj/item/storage/firstaid/fire,
+ /obj/item/storage/firstaid/fire)
+ crate_name = "burn treatment kit crate"
+
+/datum/supply_pack/medical/bloodpacks
+ name = "Blood Pack Variety Crate"
+ desc = "Contains ten different blood packs for reintroducing blood to patients."
+ cost = 3000
+ contains = list(/obj/item/reagent_containers/blood/random,
+ /obj/item/reagent_containers/blood/random,
+ /obj/item/reagent_containers/blood/APlus,
+ /obj/item/reagent_containers/blood/AMinus,
+ /obj/item/reagent_containers/blood/BPlus,
+ /obj/item/reagent_containers/blood/BMinus,
+ /obj/item/reagent_containers/blood/OPlus,
+ /obj/item/reagent_containers/blood/OMinus,
+ /obj/item/reagent_containers/blood/lizard,
+ /obj/item/reagent_containers/blood/jellyblood,
+ /obj/item/reagent_containers/blood/insect)
+ crate_name = "blood freezer"
+ crate_type = /obj/structure/closet/crate/freezer
+
+/datum/supply_pack/medical/bloodpackssynth
+ name = "Synthetics Blood Pack Crate"
+ desc = "Contains five synthetics blood packs for reintroducing blood to patients."
+ cost = 3000
+ contains = list(/obj/item/reagent_containers/blood/synthetics,
+ /obj/item/reagent_containers/blood/synthetics,
+ /obj/item/reagent_containers/blood/synthetics,
+ /obj/item/reagent_containers/blood/synthetics,
+ /obj/item/reagent_containers/blood/synthetics)
+ crate_name = "blood freezer"
+ crate_type = /obj/structure/closet/crate/freezer
+
+/datum/supply_pack/medical/defibs
+ name = "Defibrillator Crate"
+ desc = "Contains two defibrillators for bringing the recently deceased back to life."
+ cost = 2500
+ contains = list(/obj/item/defibrillator/loaded,
+ /obj/item/defibrillator/loaded)
+ crate_name = "defibrillator crate"
+
+/datum/supply_pack/medical/firstaid
+ name = "First Aid Kit Crate"
+ desc = "Contains four first aid kits for healing most types of wounds."
+ cost = 1000
+ contains = list(/obj/item/storage/firstaid/regular,
+ /obj/item/storage/firstaid/regular,
+ /obj/item/storage/firstaid/regular,
+ /obj/item/storage/firstaid/regular)
+ crate_name = "first aid kit crate"
+
+/datum/supply_pack/medical/iv_drip
+ name = "IV Drip Crate"
+ desc = "Contains a single IV drip stand for intravenous delivery."
+ cost = 800
+ contains = list(/obj/machinery/iv_drip)
+ crate_name = "iv drip crate"
+
+/datum/supply_pack/science/adv_surgery_tools
+ name = "Med-Co Advanced surgery tools"
+ desc = "A full set of Med-Co advanced surgery tools, this crate also comes with a spay of synth flesh as well as a can of . Requires Surgery access to open."
+ cost = 5500
+ access = ACCESS_SURGERY
+ contains = list(/obj/item/storage/belt/medical/surgery_belt_adv,
+ /obj/item/reagent_containers/medspray/synthflesh,
+ /obj/item/reagent_containers/medspray/sterilizine)
+ crate_name = "medco newest surgery tools"
+ crate_type = /obj/structure/closet/crate/medical
+
+/datum/supply_pack/medical/medicalhardsuit
+ name = "Medical Hardsuit"
+ desc = "Got people being spaced left and right? Hole in the same room as the dead body of Hos or cap? Fear not, now you can buy one medical hardsuit with a mask and air tank to save your fellow crewmembers."
+ cost = 2750
+ contains = list(/obj/item/tank/internals/air,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/suit/space/hardsuit/medical)
+ crate_name = "medical hardsuit"
+
+/datum/supply_pack/medical/supplies
+ name = "Medical Supplies Crate"
+ desc = "Contains seven beakers, syringes, and bodybags. Three morphine bottles, four insulin pills. Two charcoal bottles, epinephrine bottles, antitoxin bottles, and large beakers. Finally, a single roll of medical gauze, as well as a bottle of stimulant pills for long, hard work days. German doctor not included."
+ cost = 2500
+ contains = list(/obj/item/reagent_containers/glass/bottle/charcoal,
+ /obj/item/reagent_containers/glass/bottle/charcoal,
+ /obj/item/reagent_containers/glass/bottle/epinephrine,
+ /obj/item/reagent_containers/glass/bottle/epinephrine,
+ /obj/item/reagent_containers/glass/bottle/morphine,
+ /obj/item/reagent_containers/glass/bottle/morphine,
+ /obj/item/reagent_containers/glass/bottle/morphine,
+ /obj/item/reagent_containers/glass/bottle/toxin,
+ /obj/item/reagent_containers/glass/bottle/toxin,
+ /obj/item/reagent_containers/glass/beaker/large,
+ /obj/item/reagent_containers/glass/beaker/large,
+ /obj/item/reagent_containers/pill/insulin,
+ /obj/item/reagent_containers/pill/insulin,
+ /obj/item/reagent_containers/pill/insulin,
+ /obj/item/reagent_containers/pill/insulin,
+ /obj/item/stack/medical/gauze,
+ /obj/item/storage/box/beakers,
+ /obj/item/storage/box/medsprays,
+ /obj/item/storage/box/syringes,
+ /obj/item/storage/box/bodybags,
+ /obj/item/storage/pill_bottle/stimulant)
+ crate_name = "medical supplies crate"
+
+/datum/supply_pack/medical/vending
+ name = "Medical Vending Crate"
+ desc = "Contains refills for medical vending machines."
+ cost = 2000
+ contains = list(/obj/item/vending_refill/medical,
+ /obj/item/vending_refill/wallmed)
+ crate_name = "medical vending crate"
+
+/datum/supply_pack/medical/sprays
+ name = "Medical Sprays"
+ desc = "Contains two cans of Styptic Spray, Silver Sulfadiazine Spray, Synthflesh Spray and Sterilizer Compound Spray."
+ cost = 2250
+ contains = list(/obj/item/reagent_containers/medspray/styptic,
+ /obj/item/reagent_containers/medspray/styptic,
+ /obj/item/reagent_containers/medspray/silver_sulf,
+ /obj/item/reagent_containers/medspray/silver_sulf,
+ /obj/item/reagent_containers/medspray/synthflesh,
+ /obj/item/reagent_containers/medspray/synthflesh,
+ /obj/item/reagent_containers/medspray/sterilizine,
+ /obj/item/reagent_containers/medspray/sterilizine)
+ crate_name = "medical supplies crate"
+
+/datum/supply_pack/medical/firstaidmixed
+ name = "Mixed Medical Kits"
+ desc = "Contains one of each medical kits for dealing with a variety of injured crewmembers."
+ cost = 1250
+ contains = list(/obj/item/storage/firstaid/toxin,
+ /obj/item/storage/firstaid/o2,
+ /obj/item/storage/firstaid/brute,
+ /obj/item/storage/firstaid/fire,
+ /obj/item/storage/firstaid/regular)
+ crate_name = "medical supplies crate"
+
+/datum/supply_pack/medical/firstaidoxygen
+ name = "Oxygen Deprivation Kit Crate"
+ desc = "Contains three first aid kits focused on helping oxygen deprivation victims."
+ cost = 1000
+ contains = list(/obj/item/storage/firstaid/o2,
+ /obj/item/storage/firstaid/o2,
+ /obj/item/storage/firstaid/o2)
+ crate_name = "oxygen deprivation kit crate"
+
+/datum/supply_pack/medical/advrad
+ name = "Radiation Treatment Crate Deluxe"
+ desc = "A crate for when radiation is out of hand... Contains two rad-b-gone kits, one bottle of anti radiation deluxe pill bottle, as well as a radiation treatment deluxe pill bottle!"
+ cost = 3500
+ contains = list(/obj/item/storage/pill_bottle/antirad_plus,
+ /obj/item/storage/pill_bottle/mutarad,
+ /obj/item/storage/firstaid/radbgone,
+ /obj/item/storage/firstaid/radbgone,
+ /obj/item/geiger_counter,
+ /obj/item/geiger_counter)
+ crate_name = "radiation protection crate"
+ crate_type = /obj/structure/closet/crate/radiation
+
+/datum/supply_pack/medical/surgery
+ name = "Surgical Supplies Crate"
+ desc = "Do you want to perform surgery, but don't have one of those fancy shmancy degrees? Just get started with this crate containing a medical duffelbag, Sterilizine spray and collapsible roller bed."
+ cost = 1300
+ contains = list(/obj/item/storage/backpack/duffelbag/med/surgery,
+ /obj/item/reagent_containers/medspray/sterilizine,
+ /obj/item/roller)
+ crate_name = "surgical supplies crate"
+
+/datum/supply_pack/medical/firstaidtoxins
+ name = "Toxin Treatment Kit Crate"
+ desc = "Contains three first aid kits focused on healing damage dealt by heavy toxins."
+ cost = 1000
+ contains = list(/obj/item/storage/firstaid/toxin,
+ /obj/item/storage/firstaid/toxin,
+ /obj/item/storage/firstaid/toxin)
+ crate_name = "toxin treatment kit crate"
+
+/datum/supply_pack/medical/virus
+ name = "Virus Crate"
+ desc = "Contains twelve different bottles, containing several viral samples for virology research. Also includes seven beakers and syringes. Balled-up jeans not included. Requires CMO access to open."
+ cost = 2500
+ access = ACCESS_CMO
+ contains = list(/obj/item/reagent_containers/glass/bottle/flu_virion,
+ /obj/item/reagent_containers/glass/bottle/cold,
+ /obj/item/reagent_containers/glass/bottle/random_virus,
+ /obj/item/reagent_containers/glass/bottle/random_virus,
+ /obj/item/reagent_containers/glass/bottle/random_virus,
+ /obj/item/reagent_containers/glass/bottle/random_virus,
+ /obj/item/reagent_containers/glass/bottle/fake_gbs,
+ /obj/item/reagent_containers/glass/bottle/magnitis,
+ /obj/item/reagent_containers/glass/bottle/pierrot_throat,
+ /obj/item/reagent_containers/glass/bottle/brainrot,
+ /obj/item/reagent_containers/glass/bottle/anxiety,
+ /obj/item/reagent_containers/glass/bottle/beesease,
+ /obj/item/storage/box/syringes,
+ /obj/item/storage/box/beakers,
+ /obj/item/reagent_containers/glass/bottle/mutagen)
+ crate_name = "virus crate"
+ crate_type = /obj/structure/closet/crate/secure/plasma
+ dangerous = TRUE
diff --git a/code/modules/cargo/packs/misc.dm b/code/modules/cargo/packs/misc.dm
new file mode 100644
index 0000000000..c380d5411e
--- /dev/null
+++ b/code/modules/cargo/packs/misc.dm
@@ -0,0 +1,230 @@
+
+//Reminders-
+// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
+// cost = 700- Minimum cost, or infinite points are possible.
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////// Miscellaneous ///////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/misc
+ group = "Miscellaneous Supplies"
+
+/datum/supply_pack/misc/artsupply
+ name = "Art Supplies"
+ desc = "Make some happy little accidents with six canvasses, two easels, two boxes of crayons, and a rainbow crayon!"
+ cost = 800
+ contains = list(/obj/structure/easel,
+ /obj/structure/easel,
+ /obj/item/canvas/nineteenXnineteen,
+ /obj/item/canvas/nineteenXnineteen,
+ /obj/item/canvas/twentythreeXnineteen,
+ /obj/item/canvas/twentythreeXnineteen,
+ /obj/item/canvas/twentythreeXtwentythree,
+ /obj/item/canvas/twentythreeXtwentythree,
+ /obj/item/storage/crayons,
+ /obj/item/storage/crayons,
+ /obj/item/toy/crayon/rainbow,
+ /obj/item/toy/crayon/white,
+ /obj/item/toy/crayon/white)
+ crate_name = "art supply crate"
+ crate_type = /obj/structure/closet/crate/wooden
+
+/datum/supply_pack/misc/captain_pen
+ name = "Captain Pen"
+ desc = "A spare Captain fountain pen."
+ access = ACCESS_CAPTAIN
+ cost = 10000
+ contains = list(/obj/item/pen/fountain/captain)
+ crate_name = "captain pen"
+ crate_type = /obj/structure/closet/crate/secure/weapon //It is a combat pen
+
+/datum/supply_pack/misc/bicycle
+ name = "Bicycle"
+ desc = "Nanotrasen reminds all employees to never toy with powers outside their control."
+ cost = 1000000
+ contains = list(/obj/vehicle/ridden/bicycle)
+ crate_name = "Bicycle Crate"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/misc/bigband
+ name = "Big Band Instrument Collection"
+ desc = "Get your sad station movin' and groovin' with this fine collection! Contains nine different instruments!"
+ cost = 5000
+ crate_name = "Big band musical instruments collection"
+ contains = list(/obj/item/instrument/violin,
+ /obj/item/instrument/guitar,
+ /obj/item/instrument/glockenspiel,
+ /obj/item/instrument/accordion,
+ /obj/item/instrument/saxophone,
+ /obj/item/instrument/trombone,
+ /obj/item/instrument/recorder,
+ /obj/item/instrument/harmonica,
+ /obj/structure/piano/unanchored)
+ crate_type = /obj/structure/closet/crate/wooden
+
+/datum/supply_pack/misc/book_crate
+ name = "Book Crate"
+ desc = "Surplus from the Nanotrasen Archives, these five books are sure to be good reads."
+ cost = 1500
+ contains = list(/obj/item/book/codex_gigas,
+ /obj/item/book/manual/random/,
+ /obj/item/book/manual/random/,
+ /obj/item/book/manual/random/,
+ /obj/item/book/random/triple)
+ crate_type = /obj/structure/closet/crate/wooden
+
+/datum/supply_pack/misc/paper
+ name = "Bureaucracy Crate"
+ desc = "High stacks of papers on your desk Are a big problem - make it Pea-sized with these bureaucratic supplies! Contains five pens, some camera film, hand labeler supplies, a paper bin, three folders, two clipboards and two stamps as well as a briefcase."//that was too forced
+ cost = 1500
+ contains = list(/obj/structure/filingcabinet/chestdrawer/wheeled,
+ /obj/item/camera_film,
+ /obj/item/hand_labeler,
+ /obj/item/hand_labeler_refill,
+ /obj/item/hand_labeler_refill,
+ /obj/item/paper_bin,
+ /obj/item/pen/fourcolor,
+ /obj/item/pen/fourcolor,
+ /obj/item/pen,
+ /obj/item/pen/blue,
+ /obj/item/pen/red,
+ /obj/item/folder/blue,
+ /obj/item/folder/red,
+ /obj/item/folder/yellow,
+ /obj/item/clipboard,
+ /obj/item/clipboard,
+ /obj/item/stamp,
+ /obj/item/stamp/denied,
+ /obj/item/storage/briefcase)
+ crate_name = "bureaucracy crate"
+
+/datum/supply_pack/misc/fountainpens
+ name = "Calligraphy Crate"
+ desc = "Sign death warrants in style with these seven executive fountain pens."
+ cost = 730
+ contains = list(/obj/item/storage/box/fountainpens,
+ /obj/item/paper_bin)
+ crate_type = /obj/structure/closet/crate/wooden
+ crate_name = "calligraphy crate"
+
+/datum/supply_pack/misc/wrapping_paper
+ name = "Festive Wrapping Paper Crate"
+ desc = "Want to mail your loved ones gift-wrapped chocolates, stuffed animals, the Clown's severed head? You can do all that, with this crate full of wrapping paper."
+ cost = 1000
+ contains = list(/obj/item/stack/wrapping_paper)
+ crate_type = /obj/structure/closet/crate/wooden
+ crate_name = "festive wrapping paper crate"
+
+/datum/supply_pack/misc/paper_work
+ name = "Freelance Paper work"
+ desc = "The Nanotrasen Primary Bureaucratic Database Intelligence (PDBI) reports that the station has not completed its funding and grant paperwork this solar cycle. In order to gain further funding, your station is required to fill out (20) ten of these forms or no additional capital will be disbursed. We have sent you ten copies of the following form and we expect every one to be up to Nanotrasen Standards." // Disbursement. It's not a typo, look it up.
+ cost = 700 // Net of 0 credits but makes (120 x 20 = 2400)
+ contains = list(/obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/folder/paperwork,
+ /obj/item/pen/fountain
+ )
+ crate_name = "Paperwork"
+
+/datum/supply_pack/misc/funeral
+ name = "Funeral Supply crate"
+ desc = "At the end of the day, someone's gonna want someone dead. Give them a proper send-off with these funeral supplies! Contains a coffin with burial garmets and flowers."
+ cost = 800
+ contains = list(/obj/item/clothing/under/burial,
+ /obj/item/reagent_containers/food/snacks/grown/harebell,
+ /obj/item/reagent_containers/food/snacks/grown/poppy/geranium
+ )
+ crate_name = "coffin"
+ crate_type = /obj/structure/closet/crate/coffin
+
+/datum/supply_pack/misc/jukebox
+ name = "Jukebox"
+ cost = 10000
+ contains = list(/obj/machinery/jukebox)
+ crate_name = "Jukebox"
+
+/datum/supply_pack/misc/lewd
+ name = "Lewd Crate" // OwO
+ desc = "Psss want to have a good time with your sluts? Well I got what you want maid clothing, dildos, collars and more!"
+ cost = 5250
+ contraband = TRUE
+ contains = list(/obj/item/dildo/custom,
+ /obj/item/dildo/custom,
+ /obj/item/vending_refill/kink,
+ /obj/item/vending_refill/kink,
+ /obj/item/clothing/under/maid,
+ /obj/item/clothing/under/maid,
+ /obj/item/electropack/shockcollar,
+ /obj/item/electropack/shockcollar,
+ /obj/item/restraints/handcuffs/fake/kinky,
+ /obj/item/restraints/handcuffs/fake/kinky,
+ /obj/item/clothing/head/kitty/genuine, // Why its illegal
+ /obj/item/clothing/head/kitty/genuine,
+ /obj/item/storage/pill_bottle/penis_enlargement,
+ /obj/structure/reagent_dispensers/keg/aphro)
+ crate_name = "lewd kit"
+ crate_type = /obj/structure/closet/crate
+
+/datum/supply_pack/misc/lewdkeg
+ name = "Lewd Deluxe Keg"
+ desc = "That other stuff not getting you ready? Well I have a Chemslut making tons of the good stuff."
+ cost = 7500 //It can be a weapon
+ contraband = TRUE
+ contains = list(/obj/structure/reagent_dispensers/keg/aphro/strong)
+ crate_name = "deluxe keg"
+ crate_type = /obj/structure/closet/crate
+
+/datum/supply_pack/misc/religious_supplies
+ name = "Religious Supplies Crate"
+ desc = "Keep your local chaplain happy and well-supplied, lest they call down judgement upon your cargo bay. Contains two bottles of holywater, bibles, chaplain robes, and burial garmets."
+ cost = 4000 // it costs so much because the Space Church is ran by Space Jews
+ contains = list(/obj/item/reagent_containers/food/drinks/bottle/holywater,
+ /obj/item/reagent_containers/food/drinks/bottle/holywater,
+ /obj/item/storage/book/bible/booze,
+ /obj/item/storage/book/bible/booze,
+ /obj/item/clothing/suit/hooded/chaplain_hoodie,
+ /obj/item/clothing/suit/hooded/chaplain_hoodie
+ )
+ crate_name = "religious supplies crate"
+
+/datum/supply_pack/misc/randomised/promiscuous
+ name = "Promiscuous Organs"
+ desc = "Do YOU want to have more genital? Well we have just the thing for you~. This crate has two autosurgeon, that will let you have a new sex, organ to impress that hot stud and or chick."
+ cost = 4000 //Only get 2!
+ contraband = TRUE
+ var/num_contained = 2
+ contains = list(/obj/item/autosurgeon/penis,
+ /obj/item/autosurgeon/testicles,
+ /obj/item/autosurgeon/vagina,
+ /obj/item/autosurgeon/breasts,
+ /obj/item/autosurgeon/womb)
+ crate_name = "promiscuous organs"
+
+/datum/supply_pack/misc/toner
+ name = "Toner Crate"
+ desc = "Spent too much ink printing butt pictures? Fret not, with these six toner refills, you'll be printing butts 'till the cows come home!'"
+ cost = 1000
+ contains = list(/obj/item/toner,
+ /obj/item/toner,
+ /obj/item/toner,
+ /obj/item/toner,
+ /obj/item/toner,
+ /obj/item/toner)
+ crate_name = "toner crate"
diff --git a/code/modules/cargo/packs/organic.dm b/code/modules/cargo/packs/organic.dm
new file mode 100644
index 0000000000..2b5df207c3
--- /dev/null
+++ b/code/modules/cargo/packs/organic.dm
@@ -0,0 +1,290 @@
+
+//Reminders-
+// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
+// cost = 700- Minimum cost, or infinite points are possible.
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////// Organic /////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/organic
+ group = "Food & Hydroponics"
+ crate_type = /obj/structure/closet/crate/freezer
+
+/datum/supply_pack/organic/hydroponics/beekeeping_suits
+ name = "Beekeeper Suit Crate"
+ desc = "Bee business booming? Better be benevolent and boost botany by bestowing bi-Beekeeper-suits! Contains two beekeeper suits and matching headwear."
+ cost = 1300
+ contains = list(/obj/item/clothing/head/beekeeper_head,
+ /obj/item/clothing/suit/beekeeper_suit,
+ /obj/item/clothing/head/beekeeper_head,
+ /obj/item/clothing/suit/beekeeper_suit)
+ crate_name = "beekeeper suits"
+ crate_type = /obj/structure/closet/crate/hydroponics
+
+/datum/supply_pack/organic/hydroponics/beekeeping_fullkit
+ name = "Beekeeping Starter Crate"
+ desc = "BEES BEES BEES. Contains three honey frames, a beekeeper suit and helmet, flyswatter, bee house, and, of course, a pure-bred Nanotrasen-Standardized Queen Bee!"
+ cost = 1800
+ contains = list(/obj/structure/beebox/unwrenched,
+ /obj/item/honey_frame,
+ /obj/item/honey_frame,
+ /obj/item/honey_frame,
+ /obj/item/queen_bee/bought,
+ /obj/item/clothing/head/beekeeper_head,
+ /obj/item/clothing/suit/beekeeper_suit,
+ /obj/item/melee/flyswatter)
+ crate_name = "beekeeping starter crate"
+ crate_type = /obj/structure/closet/crate/hydroponics
+
+/datum/supply_pack/organic/candy/randomised
+ name = "Candy Crate"
+ desc = "For people that have a insatiable sweet tooth! Has ten candies to be eaten up.."
+ cost = 2500
+ var/num_contained = 10 //number of items picked to be contained in a randomised crate
+ contains = list(/obj/item/reagent_containers/food/snacks/candy,
+ /obj/item/reagent_containers/food/snacks/lollipop,
+ /obj/item/reagent_containers/food/snacks/gumball,
+ /obj/item/reagent_containers/food/snacks/chocolateegg,
+ /obj/item/reagent_containers/food/snacks/donut,
+ /obj/item/reagent_containers/food/snacks/cookie,
+ /obj/item/reagent_containers/food/snacks/sugarcookie,
+ /obj/item/reagent_containers/food/snacks/chococornet,
+ /obj/item/reagent_containers/food/snacks/mint,
+ /obj/item/reagent_containers/food/snacks/spiderlollipop,
+ /obj/item/reagent_containers/food/snacks/chococoin,
+ /obj/item/reagent_containers/food/snacks/fudgedice,
+ /obj/item/reagent_containers/food/snacks/chocoorange,
+ /obj/item/reagent_containers/food/snacks/honeybar,
+ /obj/item/reagent_containers/food/snacks/tinychocolate,
+ /obj/item/reagent_containers/food/snacks/spacetwinkie,
+ /obj/item/reagent_containers/food/snacks/syndicake,
+ /obj/item/reagent_containers/food/snacks/cheesiehonkers,
+ /obj/item/reagent_containers/food/snacks/sugarcookie/spookyskull,
+ /obj/item/reagent_containers/food/snacks/sugarcookie/spookycoffin,
+ /obj/item/reagent_containers/food/snacks/candy_corn,
+ /obj/item/reagent_containers/food/snacks/candiedapple,
+ /obj/item/reagent_containers/food/snacks/chocolatebar,
+ /obj/item/reagent_containers/food/snacks/candyheart,
+ /obj/item/storage/fancy/heart_box,
+ /obj/item/storage/fancy/donut_box)
+ crate_name = "candy crate"
+
+/datum/supply_pack/organic/cutlery
+ name = "Kitchen Cutlery Deluxe Set"
+ desc = "Need to slice and dice away those ''Tomatos'' well we got what you need! From a nice set of knifes, forks, plates, glasses, and a whetstone for when you got some grizzle that is a bit harder to slice then normal."
+ cost = 10000
+ contraband = TRUE
+ contains = list(/obj/item/sharpener,
+ /obj/item/kitchen/fork,
+ /obj/item/kitchen/fork,
+ /obj/item/kitchen/knife,
+ /obj/item/kitchen/knife,
+ /obj/item/kitchen/knife,
+ /obj/item/kitchen/knife,
+ /obj/item/kitchen/knife/butcher,
+ /obj/item/kitchen/knife/butcher,
+ /obj/item/kitchen/rollingpin, //Deluxe for a reason
+ /obj/item/trash/plate,
+ /obj/item/trash/plate,
+ /obj/item/trash/plate,
+ /obj/item/trash/plate,
+ /obj/item/reagent_containers/food/drinks/drinkingglass,
+ /obj/item/reagent_containers/food/drinks/drinkingglass,
+ /obj/item/reagent_containers/food/drinks/drinkingglass,
+ /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass,
+ /obj/item/reagent_containers/food/drinks/drinkingglass/shotglass)
+ crate_name = "kitchen cutlery deluxe set"
+
+/datum/supply_pack/organic/food
+ name = "Food Crate"
+ desc = "Get things cooking with this crate full of useful ingredients! Contains a two dozen eggs, three bananas, and two bags of flour and rice, two cartons of milk, soymilk, as well as salt and pepper shakers, a enzyme and sugar bottle, and three slabs of monkeymeat."
+ cost = 1000
+ contains = list(/obj/item/reagent_containers/food/condiment/flour,
+ /obj/item/reagent_containers/food/condiment/flour,
+ /obj/item/reagent_containers/food/condiment/rice,
+ /obj/item/reagent_containers/food/condiment/rice,
+ /obj/item/reagent_containers/food/condiment/milk,
+ /obj/item/reagent_containers/food/condiment/milk,
+ /obj/item/reagent_containers/food/condiment/soymilk,
+ /obj/item/reagent_containers/food/condiment/saltshaker,
+ /obj/item/reagent_containers/food/condiment/peppermill,
+ /obj/item/storage/fancy/egg_box,
+ /obj/item/storage/fancy/egg_box,
+ /obj/item/reagent_containers/food/condiment/enzyme,
+ /obj/item/reagent_containers/food/condiment/sugar,
+ /obj/item/reagent_containers/food/snacks/meat/slab/monkey,
+ /obj/item/reagent_containers/food/snacks/meat/slab/monkey,
+ /obj/item/reagent_containers/food/snacks/meat/slab/monkey,
+ /obj/item/reagent_containers/food/snacks/grown/banana,
+ /obj/item/reagent_containers/food/snacks/grown/banana,
+ /obj/item/reagent_containers/food/snacks/grown/banana)
+ crate_name = "food crate"
+
+/datum/supply_pack/organic/cream_piee
+ name = "High-yield Clown-grade Cream Pie Crate"
+ desc = "Designed by Aussec's Advanced Warfare Research Division, these high-yield, Clown-grade cream pies are powered by a synergy of performance and efficiency. Guaranteed to provide maximum results."
+ cost = 6000
+ contains = list(/obj/item/storage/backpack/duffelbag/clown/cream_pie)
+ crate_name = "party equipment crate"
+ contraband = TRUE
+ access = ACCESS_THEATRE
+ crate_type = /obj/structure/closet/crate/secure
+
+/datum/supply_pack/organic/hunting
+ name = "Huntting gear"
+ desc = "Even in space, we can fine prey to hunt, this crate contains everthing a fine hunter needs to have a sporting time. This crate needs armory access to open. A true huntter only needs a fine bottle of cognac, a nice coat, some good o' cigars, and of cource a huntting shotgun. "
+ cost = 3500
+ contraband = TRUE
+ contains = list(/obj/item/clothing/head/flatcap,
+ /obj/item/clothing/suit/hooded/wintercoat/captain,
+ /obj/item/reagent_containers/food/drinks/bottle/cognac,
+ /obj/item/storage/fancy/cigarettes/cigars/havana,
+ /obj/item/clothing/gloves/color/white,
+ /obj/item/clothing/under/rank/curator,
+ /obj/item/gun/ballistic/shotgun/lethal)
+ access = ACCESS_ARMORY
+ crate_name = "sporting crate"
+ crate_type = /obj/structure/closet/crate/secure // Would have liked a wooden crate but access >:(
+
+/datum/supply_pack/organic/hydroponics
+ name = "Hydroponics Crate"
+ desc = "Supplies for growing a great garden! Contains two bottles of ammonia, two Plant-B-Gone spray bottles, a hatchet, cultivator, plant analyzer, as well as a pair of leather gloves and a botanist's apron."
+ cost = 1750
+ contains = list(/obj/item/reagent_containers/spray/plantbgone,
+ /obj/item/reagent_containers/spray/plantbgone,
+ /obj/item/reagent_containers/glass/bottle/ammonia,
+ /obj/item/reagent_containers/glass/bottle/ammonia,
+ /obj/item/hatchet,
+ /obj/item/cultivator,
+ /obj/item/plant_analyzer,
+ /obj/item/clothing/gloves/botanic_leather,
+ /obj/item/clothing/suit/apron)
+ crate_name = "hydroponics crate"
+ crate_type = /obj/structure/closet/crate/hydroponics
+
+/datum/supply_pack/organic/hydroponics/hydrotank
+ name = "Hydroponics Backpack Crate"
+ desc = "Bring on the flood with this high-capacity backpack crate. Contains 500 units of life-giving H2O. Requires hydroponics access to open."
+ cost = 1200
+ access = ACCESS_HYDROPONICS
+ contains = list(/obj/item/watertank)
+ crate_name = "hydroponics backpack crate"
+ crate_type = /obj/structure/closet/crate/secure
+
+/datum/supply_pack/organic/mre
+ name = "MRE supply kit (emergency rations)"
+ desc = "The lights are out. Oxygen's running low. You've run out of food except space weevils. Don't let this be you! Order our NT branded MRE kits today! This pack contains 5 MRE packs with a randomized menu and an oxygen tank."
+ cost = 2000
+ contains = list(/obj/item/storage/box/mre/menu1/safe,
+ /obj/item/storage/box/mre/menu1/safe,
+ /obj/item/storage/box/mre/menu2/safe,
+ /obj/item/storage/box/mre/menu2/safe,
+ /obj/item/storage/box/mre/menu3,
+ /obj/item/storage/box/mre/menu4/safe)
+ crate_name = "MRE crate (emergency rations)"
+
+/datum/supply_pack/organic/pizza
+ name = "Pizza Crate"
+ desc = "Best prices on this side of the galaxy. All deliveries are guaranteed to be 99% anomaly-free!"
+ cost = 6000 // Best prices this side of the galaxy.
+ contains = list(/obj/item/pizzabox/margherita,
+ /obj/item/pizzabox/mushroom,
+ /obj/item/pizzabox/meat,
+ /obj/item/pizzabox/vegetable,
+ /obj/item/pizzabox/pineapple)
+ crate_name = "pizza crate"
+ var/static/anomalous_box_provided = FALSE
+
+/datum/supply_pack/organic/pizza/fill(obj/structure/closet/crate/C)
+ . = ..()
+ if(!anomalous_box_provided)
+ for(var/obj/item/pizzabox/P in C)
+ if(prob(1)) //1% chance for each box, so 4% total chance per order
+ var/obj/item/pizzabox/infinite/fourfiveeight = new(C)
+ fourfiveeight.boxtag = P.boxtag
+ qdel(P)
+ anomalous_box_provided = TRUE
+ log_game("An anomalous pizza box was provided in a pizza crate at during cargo delivery")
+ if(prob(50))
+ addtimer(CALLBACK(src, .proc/anomalous_pizza_report), rand(300, 1800))
+ else
+ message_admins("An anomalous pizza box was silently created with no command report in a pizza crate delivery.")
+ break
+
+/datum/supply_pack/organic/pizza/proc/anomalous_pizza_report()
+ print_command_report("[station_name()], our anomalous materials divison has reported a missing object that is highly likely to have been sent to your station during a routine cargo \
+ delivery. Please search all crates and manifests provided with the delivery and return the object if is located. The object resembles a standard \[DATA EXPUNGED\] and is to be \
+ considered \[REDACTED\] and returned at your leisure. Note that objects the anomaly produces are specifically attuned exactly to the individual opening the anomaly; regardless \
+ of species, the individual will find the object edible and it will taste great according to their personal definitions, which vary significantly based on person and species.")
+
+/datum/supply_pack/organic/potted_plants
+ name = "Potted Plants Crate"
+ desc = "Spruce up the station with these lovely plants! Contains a random assortment of five potted plants from Nanotrasen's potted plant research division. Warranty void if thrown."
+ cost = 730
+ contains = list(/obj/item/twohanded/required/kirbyplants/random,
+ /obj/item/twohanded/required/kirbyplants/random,
+ /obj/item/twohanded/required/kirbyplants/random,
+ /obj/item/twohanded/required/kirbyplants/random,
+ /obj/item/twohanded/required/kirbyplants/random)
+ crate_name = "potted plants crate"
+ crate_type = /obj/structure/closet/crate/hydroponics
+
+/datum/supply_pack/organic/seeds
+ name = "Seeds Crate"
+ desc = "Big things have small beginnings. Contains thirteen different seeds."
+ cost = 1250
+ contains = list(/obj/item/seeds/chili,
+ /obj/item/seeds/berry,
+ /obj/item/seeds/corn,
+ /obj/item/seeds/eggplant,
+ /obj/item/seeds/tomato,
+ /obj/item/seeds/soya,
+ /obj/item/seeds/wheat,
+ /obj/item/seeds/wheat/rice,
+ /obj/item/seeds/carrot,
+ /obj/item/seeds/sunflower,
+ /obj/item/seeds/chanter,
+ /obj/item/seeds/potato,
+ /obj/item/seeds/sugarcane)
+ crate_name = "seeds crate"
+ crate_type = /obj/structure/closet/crate/hydroponics
+
+/datum/supply_pack/organic/vday
+ name = "Surplus Valentine Crate"
+ desc = "Turns out we got warehouses of this love-y dove-y crap. Were sending out small barged buddle of Valentine gear. This crate has two boxes of chocolate, three poppy flowers, five candy hearts, and three cards."
+ cost = 3000
+ contraband = TRUE
+ contains = list(/obj/item/storage/fancy/heart_box,
+ /obj/item/storage/fancy/heart_box,
+ /obj/item/reagent_containers/food/snacks/grown/poppy,
+ /obj/item/reagent_containers/food/snacks/grown/poppy,
+ /obj/item/reagent_containers/food/snacks/grown/poppy,
+ /obj/item/reagent_containers/food/snacks/candyheart,
+ /obj/item/reagent_containers/food/snacks/candyheart,
+ /obj/item/reagent_containers/food/snacks/candyheart,
+ /obj/item/reagent_containers/food/snacks/candyheart,
+ /obj/item/reagent_containers/food/snacks/candyheart,
+ /obj/item/valentine,
+ /obj/item/valentine,
+ /obj/item/valentine)
+ crate_name = "valentine crate"
+ crate_type = /obj/structure/closet/crate/secure
+
+/datum/supply_pack/organic/exoticseeds
+ name = "Exotic Seeds Crate"
+ desc = "Any entrepreneuring botanist's dream. Contains twelve different seeds, including three replica-pod seeds and two mystery seeds!"
+ cost = 1500
+ contains = list(/obj/item/seeds/nettle,
+ /obj/item/seeds/replicapod,
+ /obj/item/seeds/replicapod,
+ /obj/item/seeds/replicapod,
+ /obj/item/seeds/plump,
+ /obj/item/seeds/liberty,
+ /obj/item/seeds/amanita,
+ /obj/item/seeds/reishi,
+ /obj/item/seeds/banana,
+ /obj/item/seeds/eggplant/eggy,
+ /obj/item/seeds/random,
+ /obj/item/seeds/random)
+ crate_name = "exotic seeds crate"
+ crate_type = /obj/structure/closet/crate/hydroponics
diff --git a/code/modules/cargo/packs/science.dm b/code/modules/cargo/packs/science.dm
new file mode 100644
index 0000000000..ace64b21fb
--- /dev/null
+++ b/code/modules/cargo/packs/science.dm
@@ -0,0 +1,216 @@
+
+//Reminders-
+// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
+// cost = 700- Minimum cost, or infinite points are possible.
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////// Science /////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/science
+ group = "Science"
+ crate_type = /obj/structure/closet/crate/science
+
+/* For later
+/datum/supply_pack/science/monkey
+ name = "Ape Cube Crate"
+ desc = "Pss what a new test subject with supper strangth, speed, and love for bananas all at the same time? Say no more... Contains a single ape cube. Dont add water!"
+ contraband = TRUE
+ cost = 2500
+ contains = list (/obj/item/reagent_containers/food/snacks/monkeycube/ape)
+ crate_name = "ape cube crate"
+*/
+
+/datum/supply_pack/science/aliens
+ name = "Advanced Alien Alloy Crate Crate"
+ desc = "Hello brothers from the stars!!! Our fellow brethren have made contact at long last and gave us gifts man! They really did build the prymi- Connection Error- Bro we’ll send you a sheet of advanced alien alloy."
+ cost = 15000
+ contraband = TRUE
+ DropPodOnly = TRUE
+ contains = list(/obj/item/stack/sheet/mineral/abductor)
+ crate_name = "alien bro alloy crate"
+
+/datum/supply_pack/science/beakers
+ name = "Chemistry Beackers Crate"
+ desc = "Glassware for any chemistry lab! Contains four small beakers, three large, two plastic, and one metamaterial. As well as three droppers and two pairs of latex gloves."
+ cost = 1500
+ contains = list(/obj/item/reagent_containers/glass/beaker,
+ /obj/item/reagent_containers/glass/beaker,
+ /obj/item/reagent_containers/glass/beaker,
+ /obj/item/reagent_containers/glass/beaker,
+ /obj/item/reagent_containers/glass/beaker/large,
+ /obj/item/reagent_containers/glass/beaker/large,
+ /obj/item/reagent_containers/glass/beaker/large,
+ /obj/item/reagent_containers/glass/beaker/plastic,
+ /obj/item/reagent_containers/glass/beaker/plastic,
+ /obj/item/reagent_containers/glass/beaker/meta,
+ /obj/item/reagent_containers/glass/beaker/noreact,
+ /obj/item/reagent_containers/dropper,
+ /obj/item/reagent_containers/dropper,
+ /obj/item/reagent_containers/dropper,
+ /obj/item/clothing/gloves/color/latex,
+ /obj/item/clothing/gloves/color/latex)
+ crate_name = "chemistry beaker crate"
+
+/datum/supply_pack/science/robotics/mecha_odysseus
+ name = "Circuit Crate (Odysseus)"
+ desc = "Ever wanted to build your own giant medical robot? Well, now you can! Contains the Odysseus main control board and Odysseus peripherals board. Requires Robotics access to open."
+ cost = 2500
+ access = ACCESS_ROBOTICS
+ contains = list(/obj/item/circuitboard/mecha/odysseus/peripherals,
+ /obj/item/circuitboard/mecha/odysseus/main)
+ crate_name = "\improper Odysseus circuit crate"
+ crate_type = /obj/structure/closet/crate/secure/science
+
+/datum/supply_pack/science/robotics/mecha_ripley
+ name = "Circuit Crate (Ripley APLU)"
+ desc = "Rip apart rocks and xenomorphs alike with the Ripley APLU. Contains the Main Ripley control board, as well as the Ripley Peripherals board. Requires Robotics access to open."
+ cost = 3000
+ access = ACCESS_ROBOTICS
+ contains = list(/obj/item/book/manual/ripley_build_and_repair,
+ /obj/item/circuitboard/mecha/ripley/main,
+ /obj/item/circuitboard/mecha/ripley/peripherals)
+ crate_name = "\improper APLU Ripley circuit crate"
+ crate_type = /obj/structure/closet/crate/secure/science
+
+/datum/supply_pack/science/circuitry
+ name = "Circuitry Starter Pack Crate"
+ desc = "Journey into the mysterious world of Circuitry with this starter pack. Contains a circuit printer, analyzer, debugger and wirer. Power cells not included."
+ cost = 1000
+ contains = list(/obj/item/integrated_electronics/analyzer,
+ /obj/item/integrated_circuit_printer,
+ /obj/item/integrated_electronics/debugger,
+ /obj/item/integrated_electronics/wirer)
+ crate_name = "circuitry starter pack crate"
+
+/datum/supply_pack/science/monkey
+ name = "Monkey Cube Crate"
+ desc = "Stop monkeying around! Contains seven monkey cubes. Just add water!"
+ cost = 2000
+ contains = list (/obj/item/storage/box/monkeycubes)
+ crate_name = "monkey cube crate"
+
+/datum/supply_pack/science/nitrilegloves
+ name = "Nitrile Gloves Crate"
+ desc = "Handling toxic chemicals? Well worry not, keep your flesh intact with some nitrile made gloves! Contains three pairs of nitrile gloves."
+ cost = 1500
+ contains = list(/obj/item/clothing/gloves/color/latex/nitrile,
+ /obj/item/clothing/gloves/color/latex/nitrile,
+ /obj/item/clothing/gloves/color/latex/nitrile)
+ crate_name = "nitrile gloves crate"
+
+/datum/supply_pack/science/nuke_b_gone
+ name = "Nuke Defusal Kit"
+ desc = "Contains set of tools to defuse a nuke."
+ cost = 7500 //Usefull for traitors/nukies that fucked up
+ dangerous = TRUE
+ DropPodOnly = TRUE
+ contains = list(/obj/item/nuke_core_container/nt,
+ /obj/item/screwdriver/nuke/nt,
+ /obj/item/paper/guides/nt/nuke_instructions)
+ crate_name = "safe defusal kit storage"
+
+/datum/supply_pack/science/plasma
+ name = "Plasma Assembly Crate"
+ desc = "Everything you need to burn something to the ground, this contains three plasma assembly sets. Each set contains a plasma tank, igniter, proximity sensor, and timer! Warranty void if exposed to high temperatures. Requires Toxins access to open."
+ cost = 1800
+ access = ACCESS_TOX_STORAGE
+ contains = list(/obj/item/tank/internals/plasma,
+ /obj/item/tank/internals/plasma,
+ /obj/item/tank/internals/plasma,
+ /obj/item/assembly/igniter,
+ /obj/item/assembly/igniter,
+ /obj/item/assembly/igniter,
+ /obj/item/assembly/prox_sensor,
+ /obj/item/assembly/prox_sensor,
+ /obj/item/assembly/prox_sensor,
+ /obj/item/assembly/timer,
+ /obj/item/assembly/timer,
+ /obj/item/assembly/timer)
+ crate_name = "plasma assembly crate"
+ crate_type = /obj/structure/closet/crate/secure/plasma
+
+/datum/supply_pack/science/relic
+ name = "Relic Crate"
+ desc = "Ever want to play with old discounted toys? Look no more. Contains two relics."
+ cost = 1000
+ contraband = TRUE
+ contains = list(/obj/item/relic,
+ /obj/item/relic)
+ crate_name = "relic crate"
+
+/datum/supply_pack/science/robotics
+ name = "Robotics Assembly Crate"
+ desc = "The tools you need to replace those finicky humans with a loyal robot army! Contains three proximity sensors, two high-powered cells, six flashes, and an electrical toolbox. Requires Robotics access to open."
+ cost = 1500
+ access = ACCESS_ROBOTICS
+ contains = list(/obj/item/assembly/prox_sensor,
+ /obj/item/assembly/prox_sensor,
+ /obj/item/assembly/prox_sensor,
+ /obj/item/storage/toolbox/electrical,
+ /obj/item/storage/box/flashes,
+ /obj/item/stock_parts/cell/high,
+ /obj/item/stock_parts/cell/high)
+ crate_name = "robotics assembly crate"
+ crate_type = /obj/structure/closet/crate/secure/science
+
+/datum/supply_pack/science/shieldwalls
+ name = "Shield Generator Crate"
+ desc = "These high powered Shield Wall Generators are guaranteed to keep any unwanted lifeforms on the outside, where they belong! Contains four shield wall generators. Requires Teleporter access to open."
+ cost = 2000
+ access = ACCESS_TELEPORTER
+ contains = list(/obj/machinery/shieldwallgen,
+ /obj/machinery/shieldwallgen,
+ /obj/machinery/shieldwallgen,
+ /obj/machinery/shieldwallgen)
+ crate_name = "shield generators crate"
+ crate_type = /obj/structure/closet/crate/secure/science
+
+/datum/supply_pack/science/slime
+ name = "Slime Core Crate"
+ desc = "Ran out of slimes? No problem, contains one gray slime core. Requires Xenobio access to open."
+ cost = 1000
+ access = ACCESS_XENOBIOLOGY
+ contains = list(/obj/item/slime_extract/grey)
+ crate_name = "slime core crate"
+ crate_type = /obj/structure/closet/crate/secure/science
+
+/datum/supply_pack/science/supermater
+ name = "Supermatter Extraction Tools Crate"
+ desc = "Contains a set of tools to extract a sliver of supermatter. Consult your CE today!"
+ cost = 7500 //Usefull for traitors that fucked up
+ hidden = TRUE
+ contains = list(/obj/item/nuke_core_container/supermatter,
+ /obj/item/scalpel/supermatter,
+ /obj/item/hemostat/supermatter,
+ /obj/item/paper/guides/antag/supermatter_sliver)
+ crate_name = "supermatter extraction kit crate"
+
+/datum/supply_pack/science/tablets
+ name = "Tablet Crate"
+ desc = "What's a computer? Contains five cargo tablets."
+ cost = 3000
+ contains = list(/obj/item/modular_computer/tablet/preset/cargo,
+ /obj/item/modular_computer/tablet/preset/cargo,
+ /obj/item/modular_computer/tablet/preset/cargo,
+ /obj/item/modular_computer/tablet/preset/cargo,
+ /obj/item/modular_computer/tablet/preset/cargo)
+ crate_name = "tablet crate"
+
+/datum/supply_pack/science/transfer_valves
+ name = "Tank Transfer Valves Crate"
+ desc = "The key ingredient for making a lot of people very angry very fast. Contains two tank transfer valves. Requires RD access to open."
+ cost = 6000
+ access = ACCESS_RD
+ contains = list(/obj/item/transfer_valve,
+ /obj/item/transfer_valve)
+ crate_name = "tank transfer valves crate"
+ crate_type = /obj/structure/closet/crate/secure/science
+ dangerous = TRUE
+
+/datum/supply_pack/science/tech_slugs
+ name = "Tech Slug Ammo Shells"
+ desc = "A new type of shell that is able to be made into a few different dangerous types. Contains two boxes of tech slugs, 14 shells in all."
+ cost = 1700
+ contains = list(/obj/item/storage/box/techsslug,
+ /obj/item/storage/box/techsslug)
+ crate_name = "tech slug crate"
diff --git a/code/modules/cargo/packs/security.dm b/code/modules/cargo/packs/security.dm
new file mode 100644
index 0000000000..3c68fe7f6d
--- /dev/null
+++ b/code/modules/cargo/packs/security.dm
@@ -0,0 +1,192 @@
+
+//Reminders-
+// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
+// cost = 700- Minimum cost, or infinite points are possible.
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////// Security ////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/security
+ group = "Security"
+ access = ACCESS_SECURITY
+ crate_type = /obj/structure/closet/crate/secure/gear
+
+/datum/supply_pack/security/armor
+ name = "Armor Crate"
+ desc = "Three vests of well-rounded, decently-protective armor. Requires Security access to open."
+ cost = 1200
+ contains = list(/obj/item/clothing/suit/armor/vest,
+ /obj/item/clothing/suit/armor/vest,
+ /obj/item/clothing/suit/armor/vest)
+ crate_name = "armor crate"
+
+/datum/supply_pack/security/disabler
+ name = "Disabler Crate"
+ desc = "Three stamina-draining disabler weapons. Requires Security access to open."
+ cost = 1300
+ contains = list(/obj/item/gun/energy/disabler,
+ /obj/item/gun/energy/disabler,
+ /obj/item/gun/energy/disabler)
+ crate_name = "disabler crate"
+
+/datum/supply_pack/security/forensics
+ name = "Forensics Crate"
+ desc = "Stay hot on the criminal's heels with Nanotrasen's Detective Essentials(tm). Contains a forensics scanner, six evidence bags, camera, tape recorder, white crayon, and of course, a fedora. Requires Security access to open."
+ cost = 1800
+ contains = list(/obj/item/detective_scanner,
+ /obj/item/storage/box/evidence,
+ /obj/item/camera,
+ /obj/item/taperecorder,
+ /obj/item/toy/crayon/white,
+ /obj/item/clothing/head/fedora/det_hat)
+ crate_name = "forensics crate"
+
+/datum/supply_pack/security/helmets
+ name = "Helmets Crate"
+ desc = "Contains three standard-issue brain buckets. Requires Security access to open."
+ cost = 1200
+ contains = list(/obj/item/clothing/head/helmet/sec,
+ /obj/item/clothing/head/helmet/sec,
+ /obj/item/clothing/head/helmet/sec)
+ crate_name = "helmet crate"
+
+/datum/supply_pack/security/laser
+ name = "Lasers Crate"
+ desc = "Contains three lethal, high-energy laser guns. Requires Security access to open."
+ cost = 1750
+ contains = list(/obj/item/gun/energy/laser,
+ /obj/item/gun/energy/laser,
+ /obj/item/gun/energy/laser)
+ crate_name = "laser crate"
+
+/datum/supply_pack/security/russianclothing
+ name = "Russian Surplus Clothing"
+ desc = "An old russian crate full of surplus armor that they used to use! Has two sets of bulletproff armor, a few union suits and some warm hats!"
+ contraband = TRUE
+ cost = 5750 // Its basicly sec suits, good boots/gloves
+ contains = list(/obj/item/clothing/suit/security/officer/russian,
+ /obj/item/clothing/suit/security/officer/russian,
+ /obj/item/clothing/shoes/combat,
+ /obj/item/clothing/shoes/combat,
+ /obj/item/clothing/head/ushanka,
+ /obj/item/clothing/head/ushanka,
+ /obj/item/clothing/suit/armor/bulletproof,
+ /obj/item/clothing/suit/armor/bulletproof,
+ /obj/item/clothing/head/helmet/alt,
+ /obj/item/clothing/head/helmet/alt,
+ /obj/item/clothing/gloves/combat,
+ /obj/item/clothing/gloves/combat,
+ /obj/item/clothing/mask/gas,
+ /obj/item/clothing/mask/gas)
+ crate_name = "surplus russian clothing"
+ crate_type = /obj/structure/closet/crate/internals
+
+/datum/supply_pack/security/russianmosin
+ name = "Russian Minutemen Gear"
+ desc = "An old russian Minutemen crate, comes with a full russian outfit, a mosin and a stripper clip."
+ contraband = TRUE
+ access = FALSE
+ cost = 5500 //
+ contains = list(/obj/item/clothing/suit/security/officer/russian,
+ /obj/item/clothing/shoes/combat,
+ /obj/item/clothing/head/ushanka,
+ /obj/item/clothing/suit/armor/bulletproof,
+ /obj/item/clothing/head/helmet/alt,
+ /obj/item/clothing/gloves/combat,
+ /obj/item/clothing/mask/gas,
+ /obj/item/gun/ballistic/shotgun/boltaction,
+ /obj/item/ammo_box/a762)
+ crate_name = "surplus russian gear"
+ crate_type = /obj/structure/closet/crate/internals
+
+/datum/supply_pack/security/sechardsuit
+ name = "Sec Hardsuit"
+ desc = "One Sec Hardsuit with a small air tank and mask."
+ cost = 3000 // half of SWAT gear for have the armor and half the gear
+ contains = list(/obj/item/clothing/suit/space/hardsuit/security,
+ /obj/item/tank/internals/air,
+ /obj/item/clothing/mask/gas)
+ crate_name = "sec hardsuit crate"
+
+/datum/supply_pack/security/securitybarriers
+ name = "Security Barrier Grenades"
+ desc = "Stem the tide with four Security Barrier grenades. Requires Security access to open."
+ contains = list(/obj/item/grenade/barrier,
+ /obj/item/grenade/barrier,
+ /obj/item/grenade/barrier,
+ /obj/item/grenade/barrier)
+ cost = 2000
+ crate_name = "security barriers crate"
+
+/datum/supply_pack/security/securityclothes
+ name = "Security Clothing Crate"
+ desc = "Contains appropriate outfits for the station's private security force. Contains outfits for the Warden, Head of Security, and two Security Officers. Each outfit comes with a rank-appropriate jumpsuit, suit, and beret. Requires Security access to open."
+ cost = 3250
+ contains = list(/obj/item/clothing/under/rank/security/navyblue,
+ /obj/item/clothing/under/rank/security/navyblue,
+ /obj/item/clothing/suit/security/officer,
+ /obj/item/clothing/suit/security/officer,
+ /obj/item/clothing/head/beret/sec/navyofficer,
+ /obj/item/clothing/head/beret/sec/navyofficer,
+ /obj/item/clothing/under/rank/warden/navyblue,
+ /obj/item/clothing/suit/security/warden,
+ /obj/item/clothing/head/beret/sec/navywarden,
+ /obj/item/clothing/under/rank/head_of_security/navyblue,
+ /obj/item/clothing/suit/security/hos,
+ /obj/item/clothing/head/beret/sec/navyhos)
+ crate_name = "security clothing crate"
+
+/datum/supply_pack/security/supplies
+ name = "Security Supplies Crate"
+ desc = "Contains seven flashbangs, seven teargas grenades, six flashes, and seven handcuffs. Requires Security access to open."
+ cost = 1200
+ contains = list(/obj/item/storage/box/flashbangs,
+ /obj/item/storage/box/teargas,
+ /obj/item/storage/box/flashes,
+ /obj/item/storage/box/handcuffs)
+ crate_name = "security supply crate"
+
+/datum/supply_pack/security/firingpins
+ name = "Standard Firing Pins Crate"
+ desc = "Upgrade your arsenal with 10 standard firing pins. Requires Security access to open."
+ cost = 2000
+ contains = list(/obj/item/storage/box/firingpins,
+ /obj/item/storage/box/firingpins)
+ crate_name = "firing pins crate"
+
+/datum/supply_pack/security/justiceinbound
+ name = "Standard Justice Enforcer Crate"
+ desc = "This is it. The Bee's Knees. The Creme of the Crop. The Pick of the Litter. The best of the best of the best. The Crown Jewel of Nanotrasen. The Alpha and the Omega of security headwear. Guaranteed to strike fear into the hearts of each and every criminal aboard the station. Also comes with a security gasmask. Requires Security access to open."
+ cost = 6000 //justice comes at a price. An expensive, noisy price.
+ contraband = TRUE
+ contains = list(/obj/item/clothing/head/helmet/justice,
+ /obj/item/clothing/mask/gas/sechailer)
+ crate_name = "security clothing crate"
+
+/datum/supply_pack/security/baton
+ name = "Stun Batons Crate"
+ desc = "Arm the Civil Protection Forces with three stun batons. Batteries included. Requires Security access to open."
+ cost = 1200
+ contains = list(/obj/item/melee/baton/loaded,
+ /obj/item/melee/baton/loaded,
+ /obj/item/melee/baton/loaded)
+ crate_name = "stun baton crate"
+
+/datum/supply_pack/security/taser
+ name = "Taser Crate"
+ desc = "From the depths of stunbased combat, this order rises above, supreme. Contains three hybrid tasers, capable of firing both electrodes and disabling shots. Requires Security access to open."
+ cost = 3500
+ contains = list(/obj/item/gun/energy/e_gun/advtaser,
+ /obj/item/gun/energy/e_gun/advtaser,
+ /obj/item/gun/energy/e_gun/advtaser)
+ crate_name = "taser crate"
+
+/datum/supply_pack/security/wall_flash
+ name = "Wall-Mounted Flash Crate"
+ desc = "Contains four wall-mounted flashes. Requires Security access to open."
+ cost = 1000
+ contains = list(/obj/item/storage/box/wall_flash,
+ /obj/item/storage/box/wall_flash,
+ /obj/item/storage/box/wall_flash,
+ /obj/item/storage/box/wall_flash)
+ crate_name = "wall-mounted flash crate"
diff --git a/code/modules/cargo/packs/service.dm b/code/modules/cargo/packs/service.dm
new file mode 100644
index 0000000000..14bde519e1
--- /dev/null
+++ b/code/modules/cargo/packs/service.dm
@@ -0,0 +1,266 @@
+
+//Reminders-
+// If you add something to this list, please group it by type and sort it alphabetically instead of just jamming it in like an animal
+// cost = 700- Minimum cost, or infinite points are possible.
+//////////////////////////////////////////////////////////////////////////////
+/////////////////////////////// Service //////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/service
+ group = "Service"
+
+/datum/supply_pack/service/advlighting
+ name = "Advanced Lighting crate"
+ desc = "Thanks to advanced lighting tech we here at the Lamp Factory have be able to produce more lamps and lamp items! This crate has three lamps, a box of lights and a state of the art rapid-light-device!"
+ cost = 2750
+ contains = list(/obj/item/construction/rld,
+ /obj/item/flashlight/lamp,
+ /obj/item/flashlight/lamp,
+ /obj/item/flashlight/lamp/green,
+ /obj/item/storage/box/lights/mixed)
+ crate_name = "advanced lighting crate"
+ crate_type = /obj/structure/closet/crate/secure
+
+/datum/supply_pack/service/cargo_supples
+ name = "Cargo Supplies Crate"
+ desc = "Sold everything that wasn't bolted down? You can get right back to work with this crate containing stamps, an export scanner, destination tagger, hand labeler and some package wrapping."
+ cost = 1000
+ contains = list(/obj/item/stamp,
+ /obj/item/stamp/denied,
+ /obj/item/export_scanner,
+ /obj/item/destTagger,
+ /obj/item/hand_labeler,
+ /obj/item/stack/packageWrap)
+ crate_name = "cargo supplies crate"
+
+/datum/supply_pack/service/carpet_exotic
+ name = "Exotic Carpet Crate"
+ desc = "Exotic carpets straight from Space Russia, for all your decorating needs. Contains 100 tiles each of 10 different flooring patterns."
+ cost = 7000
+ contains = list(/obj/item/stack/tile/carpet/blue/fifty,
+ /obj/item/stack/tile/carpet/blue/fifty,
+ /obj/item/stack/tile/carpet/cyan/fifty,
+ /obj/item/stack/tile/carpet/cyan/fifty,
+ /obj/item/stack/tile/carpet/green/fifty,
+ /obj/item/stack/tile/carpet/green/fifty,
+ /obj/item/stack/tile/carpet/orange/fifty,
+ /obj/item/stack/tile/carpet/orange/fifty,
+ /obj/item/stack/tile/carpet/purple/fifty,
+ /obj/item/stack/tile/carpet/purple/fifty,
+ /obj/item/stack/tile/carpet/red/fifty,
+ /obj/item/stack/tile/carpet/red/fifty,
+ /obj/item/stack/tile/carpet/royalblue/fifty,
+ /obj/item/stack/tile/carpet/royalblue/fifty,
+ /obj/item/stack/tile/carpet/royalblack/fifty,
+ /obj/item/stack/tile/carpet/royalblack/fifty,
+ /obj/item/stack/tile/carpet/blackred/fifty,
+ /obj/item/stack/tile/carpet/blackred/fifty,
+ /obj/item/stack/tile/carpet/monochrome/fifty,
+ /obj/item/stack/tile/carpet/monochrome/fifty)
+ crate_name = "exotic carpet crate"
+
+/datum/supply_pack/service/food_cart
+ name = "Food Cart Crate"
+ desc = "Want to sell food on the go? Cook lost their cart? Well we just so happen to have a few carts to spare!"
+ cost = 1000
+ contains = list(/obj/machinery/food_cart)
+ crate_name = "food cart crate"
+ crate_type = /obj/structure/closet/crate
+
+/datum/supply_pack/service/noslipfloor
+ name = "High-traction Floor Tiles"
+ desc = "Make slipping a thing of the past with sixty industrial-grade anti-slip floortiles!"
+ cost = 2000
+ contains = list(/obj/item/stack/tile/noslip/thirty,
+ /obj/item/stack/tile/noslip/thirty)
+ crate_name = "high-traction floor tiles crate"
+
+/datum/supply_pack/service/icecream_cart
+ name = "Ice Cream Cart Crate"
+ desc = "Plasma fire a to hot for you, want a nice treat after a hard days work? Well now we have the cart for you! This Ice Cream Vat has everthing you need to make you and your friends so ice cream treats! This cart comes stocked with some ingredients for each type of scoopable icecream."
+ cost = 2750 //Comes prestocked with basic ingredients
+ contains = list(/obj/machinery/icecream_vat)
+ crate_name = "ice cream vat crate"
+ crate_type = /obj/structure/closet/crate
+
+/datum/supply_pack/service/janitor
+ name = "Janitorial Supplies Crate"
+ desc = "Fight back against dirt and grime with Nanotrasen's Janitorial Essentials(tm)! Contains three buckets, caution signs, and cleaner grenades. Also has a single mop, spray cleaner, rag, NT soap and a trash bag."
+ cost = 1300
+ contains = list(/obj/item/reagent_containers/glass/bucket,
+ /obj/item/reagent_containers/glass/bucket,
+ /obj/item/reagent_containers/glass/bucket,
+ /obj/item/mop,
+ /obj/item/caution,
+ /obj/item/caution,
+ /obj/item/caution,
+ /obj/item/storage/bag/trash,
+ /obj/item/reagent_containers/spray/cleaner,
+ /obj/item/reagent_containers/rag,
+ /obj/item/grenade/chem_grenade/cleaner,
+ /obj/item/grenade/chem_grenade/cleaner,
+ /obj/item/grenade/chem_grenade/cleaner,
+ /obj/item/soap/nanotrasen)
+ crate_name = "janitorial supplies crate"
+
+/datum/supply_pack/service/janitor/janicart
+ name = "Janitorial Cart and Galoshes Crate"
+ desc = "The keystone to any successful janitor. As long as you have feet, this pair of galoshes will keep them firmly planted on the ground. Also contains a janitorial cart."
+ cost = 2000
+ contains = list(/obj/structure/janitorialcart,
+ /obj/item/clothing/shoes/galoshes)
+ crate_name = "janitorial cart crate"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/service/janitor/janitank
+ name = "Janitor Backpack Crate"
+ desc = "Call forth divine judgement upon dirt and grime with this high capacity janitor backpack. Contains 500 units of station-cleansing cleaner. Requires janitor access to open."
+ cost = 1000
+ access = ACCESS_JANITOR
+ contains = list(/obj/item/watertank/janitor)
+ crate_name = "janitor backpack crate"
+ crate_type = /obj/structure/closet/crate/secure
+
+/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 = 1750
+ access = ACCESS_JANITOR
+ contains = list(/obj/item/caution,
+ /obj/item/caution,
+ /obj/item/caution,
+ /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!"
+ cost = 2000
+ contains = list(/mob/living/simple_animal/bot/mulebot)
+ crate_name = "\improper MULEbot Crate"
+ crate_type = /obj/structure/closet/crate/large
+
+/datum/supply_pack/service/party
+ name = "Party Equipment"
+ desc = "Celebrate both life and death on the station with Nanotrasen's Party Essentials(tm)! Contains seven colored glowsticks, four beers, two ales, and a bottle of patron, goldschlager, and shaker!"
+ cost = 2000
+ contains = list(/obj/item/storage/box/drinkingglasses,
+ /obj/item/reagent_containers/food/drinks/shaker,
+ /obj/item/reagent_containers/food/drinks/bottle/patron,
+ /obj/item/reagent_containers/food/drinks/bottle/goldschlager,
+ /obj/item/reagent_containers/food/drinks/ale,
+ /obj/item/reagent_containers/food/drinks/ale,
+ /obj/item/reagent_containers/food/drinks/beer,
+ /obj/item/reagent_containers/food/drinks/beer,
+ /obj/item/reagent_containers/food/drinks/beer,
+ /obj/item/reagent_containers/food/drinks/beer,
+ /obj/item/flashlight/glowstick,
+ /obj/item/flashlight/glowstick/red,
+ /obj/item/flashlight/glowstick/blue,
+ /obj/item/flashlight/glowstick/cyan,
+ /obj/item/flashlight/glowstick/orange,
+ /obj/item/flashlight/glowstick/yellow,
+ /obj/item/flashlight/glowstick/pink)
+ crate_name = "party equipment crate"
+
+/datum/supply_pack/service/carpet
+ name = "Premium Carpet Crate"
+ desc = "Plasteel floor tiles getting on your nerves? These stacks of extra soft carpet will tie any room together. Contains the classics."
+ cost = 1000
+ contains = list(/obj/item/stack/tile/carpet/fifty,
+ /obj/item/stack/tile/carpet/fifty,
+ /obj/item/stack/tile/carpet/black/fifty,
+ /obj/item/stack/tile/carpet/black/fifty)
+ crate_name = "premium carpet crate"
+
+/datum/supply_pack/service/carpet2
+ name = "Premium Carpet Crate #2"
+ desc = "Plasteel floor tiles getting on your nerves? These stacks of extra soft carpet will tie any room together. Contains red, and monochrome"
+ cost = 1000
+ contains = list(/obj/item/stack/tile/carpet/blackred/fifty,
+ /obj/item/stack/tile/carpet/blackred/fifty,
+ /obj/item/stack/tile/carpet/monochrome/fifty,
+ /obj/item/stack/tile/carpet/monochrome/fifty)
+ crate_name = "premium carpet crate #2"
+
+/datum/supply_pack/service/lightbulbs
+ name = "Replacement Lights"
+ desc = "May the light of Aether shine upon this station! Or at least, the light of forty two light tubes and twenty one light bulbs as well as a light replacer."
+ cost = 1200
+ contains = list(/obj/item/storage/box/lights/mixed,
+ /obj/item/storage/box/lights/mixed,
+ /obj/item/storage/box/lights/mixed,
+ /obj/item/lightreplacer)
+ crate_name = "replacement lights"
+
+/datum/supply_pack/service/minerkit
+ name = "Shaft Miner Starter Kit"
+ desc = "All the miners died too fast? Assistant wants to get a taste of life off-station? Either way, this kit is the best way to turn a regular crewman into an ore-producing, monster-slaying machine. Contains meson goggles, a pickaxe, advanced mining scanner, cargo headset, ore bag, gasmask, and explorer suit. Requires QM access to open."
+ cost = 2500
+ access = ACCESS_QM
+ contains = list(/obj/item/pickaxe/mini,
+ /obj/item/clothing/glasses/meson,
+ /obj/item/t_scanner/adv_mining_scanner/lesser,
+ /obj/item/radio/headset/headset_cargo/mining,
+ /obj/item/storage/bag/ore,
+ /obj/item/clothing/suit/hooded/explorer/standard,
+ /obj/item/clothing/mask/gas/explorer)
+ crate_name = "shaft miner starter kit"
+ crate_type = /obj/structure/closet/crate/secure
+
+//////////////////////////////////////////////////////////////////////////////
+/////////////////////////// Vending Restocks /////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+/datum/supply_pack/service/vending/bartending
+ name = "Bartending Supply Crate"
+ desc = "Bring on the booze with vending machine refills, as well as a free book containing the well-kept secrets to the bartending trade!"
+ cost = 2000
+ contains = list(/obj/item/vending_refill/boozeomat,
+ /obj/item/vending_refill/coffee,
+ /obj/item/book/granter/action/drink_fling)
+ crate_name = "bartending supply crate"
+
+/datum/supply_pack/service/vending/cigarette
+ name = "Cigarette Supply Crate"
+ desc = "Don't believe the reports - smoke today! Contains a cigarette vending machine refill."
+ cost = 1500
+ contains = list(/obj/item/vending_refill/cigarette)
+ crate_name = "cigarette supply crate"
+ crate_type = /obj/structure/closet/crate
+
+/datum/supply_pack/service/vending/games
+ name = "Games Supply Crate"
+ desc = "Get your game on with this game vending machine refill."
+ cost = 1000
+ contains = list(/obj/item/vending_refill/games)
+ crate_name = "games supply crate"
+ crate_type = /obj/structure/closet/crate
+
+/datum/supply_pack/service/vending/snack
+ name = "Snack Supply Crate"
+ desc = "One vending machine refill of cavity-bringin' goodness! The number one dentist recommended order!"
+ cost = 1500
+ contains = list(/obj/item/vending_refill/snack)
+ crate_name = "snacks supply crate"
+
+/datum/supply_pack/service/vending/cola
+ name = "Softdrinks Supply Crate"
+ desc = "Got whacked by a toolbox, but you still have those pesky teeth? Get rid of those pearly whites with this soda machine refill, today!"
+ cost = 1500
+ contains = list(/obj/item/vending_refill/cola)
+ crate_name = "soft drinks supply crate"
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
index c6166ca970..edec4d74a6 100644
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -86,6 +86,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/skin_tone = "caucasian1" //Skin color
var/eye_color = "000" //Eye color
var/horn_color = "85615a" //Horn color
+ var/wing_color = "fff" //Wing color
var/datum/species/pref_species = new /datum/species/human() //Mutant race
var/list/features = list("mcolor" = "FFF",
"tail_lizard" = "Smooth",
@@ -112,7 +113,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
"xenohead" = "Standard",
"xenotail" = "Xenomorph Tail",
"taur" = "None",
- "exhibitionist" = FALSE,
"genitals_use_skintone" = FALSE,
"has_cock" = FALSE,
"cock_shape" = "Human",
@@ -591,6 +591,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "
Decorative wings
"
dat += "[features["deco_wings"]]"
+ dat += "Change "
+
if("insect_wings" in pref_species.default_features)
if(!mutant_category)
dat += APPEARANCE_CATEGORY_COLUMN
@@ -598,6 +600,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "
"
@@ -70,8 +72,8 @@
if(check_rights_for(target.client, R_FUN)) //Allows admins to view faxes
return TRUE
if(isAI(target))
- var/mob/living/silicon/ai/ai = target
- return get_dist(src, ai.current) < 2
+ force_stars = TRUE
+ return TRUE
if(iscyborg(target))
return get_dist(src, target) < 2
return ..()
@@ -133,18 +135,8 @@
playsound(loc, 'sound/items/bikehorn.ogg', 50, 1)
addtimer(CALLBACK(src, .proc/reset_spamflag), 20)
-
/obj/item/paper/attack_ai(mob/living/silicon/ai/user)
- var/dist
- if(istype(user) && user.current) //is AI
- dist = get_dist(src, user.current)
- else //cyborg or AI not seeing through a camera
- dist = get_dist(src, user)
- if(dist < 2)
- show_content(user)
- else
- to_chat(user, "You can't quite see it.")
-
+ show_content(user)
/obj/item/paper/proc/addtofield(id, text, links = 0)
var/locid = 0
@@ -331,7 +323,7 @@
to_chat(user, "You stamp the paper with your rubber stamp.")
ui.render_all()
- if(P.is_hot())
+ if(P.get_temperature())
if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10))
user.visible_message("[user] accidentally ignites [user.p_them()]self!", \
"You miss the paper and accidentally light yourself on fire!")
diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm
index e0aeaa106d..6d9c6373ba 100644
--- a/code/modules/paperwork/paperbin.dm
+++ b/code/modules/paperwork/paperbin.dm
@@ -154,7 +154,7 @@
qdel(src)
/obj/item/paper_bin/bundlenatural/attackby(obj/item/W, mob/user)
- if(W.is_sharp())
+ if(W.get_sharpness())
to_chat(user, "You snip \the [src], spilling paper everywhere.")
var/turf/T = get_turf(src.loc)
while(total_paper > 0)
diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm
index 4b08ccf608..b547089aef 100644
--- a/code/modules/paperwork/paperplane.dm
+++ b/code/modules/paperwork/paperplane.dm
@@ -76,7 +76,7 @@
internalPaper.attackby(P, user) //spoofed attack to update internal paper.
update_icon()
- else if(P.is_hot())
+ else if(P.get_temperature())
if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10))
user.visible_message("[user] accidentally ignites [user.p_them()]self!", \
"You miss [src] and accidentally light yourself on fire!")
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 5bcb7a60df..fece60f268 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -158,6 +158,7 @@
if(..())
if(reagents.total_volume)
if(M.reagents)
+ reagents.reaction(M, INJECT)
reagents.trans_to(M, reagents.total_volume)
@@ -200,7 +201,7 @@
throwforce = 35
playsound(user, 'sound/weapons/saberon.ogg', 5, 1)
to_chat(user, "[src] is now active.")
- GET_COMPONENT_FROM(butchering, /datum/component/butchering, src)
+ var/datum/component/butchering/butchering = src.GetComponent(/datum/component/butchering)
butchering.butchering_enabled = on
update_icon()
diff --git a/code/modules/photography/photos/album.dm b/code/modules/photography/photos/album.dm
index bd77d468d7..3400ed6de0 100644
--- a/code/modules/photography/photos/album.dm
+++ b/code/modules/photography/photos/album.dm
@@ -13,7 +13,7 @@
/obj/item/storage/photo_album/Initialize()
. = ..()
- GET_COMPONENT(STR, /datum/component/storage)
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.can_hold = typecacheof(list(/obj/item/photo))
STR.max_combined_w_class = 42
STR.max_items = 21
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index 1759f31344..bbbf8edae5 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -20,6 +20,7 @@
var/self_recharge = 0 //does it self recharge, over time, or not?
var/ratingdesc = TRUE
var/grown_battery = FALSE // If it's a grown that acts as a battery, add a wire overlay to it.
+ rad_flags = RAD_NO_CONTAMINATE // Prevent the same cheese as with the stock parts
/obj/item/stock_parts/cell/get_cell()
return src
@@ -201,7 +202,7 @@
/obj/item/stock_parts/cell/lascarbine
name = "laser carbine power supply"
- maxcharge = 2500
+ maxcharge = 1500 //20 laser shots.
/obj/item/stock_parts/cell/pulse //200 pulse shots
name = "pulse rifle power cell"
diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm
index 4d6ede69d1..71a8565d26 100644
--- a/code/modules/power/singularity/emitter.dm
+++ b/code/modules/power/singularity/emitter.dm
@@ -199,6 +199,7 @@
if(prob(35))
sparks.start()
P.firer = user ? user : src
+ P.fired_from = src
if(last_projectile_params)
P.p_x = last_projectile_params[2]
P.p_y = last_projectile_params[3]
diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm
index 120976b61f..e6fa1e0ee4 100644
--- a/code/modules/power/supermatter/supermatter.dm
+++ b/code/modules/power/supermatter/supermatter.dm
@@ -29,7 +29,7 @@
#define MOLE_HEAT_PENALTY 350 //Heat damage scales around this. Too hot setups with this amount of moles do regular damage, anything above and below is scaled
#define POWER_PENALTY_THRESHOLD 5000 //Higher == Engine can generate more power before triggering the high power penalties.
#define SEVERE_POWER_PENALTY_THRESHOLD 7000 //Same as above, but causes more dangerous effects
-#define CRITICAL_POWER_PENALTY_THRESHOLD 9000 //Even more dangerous effects, threshold for tesla delamination
+#define CRITICAL_POWER_PENALTY_THRESHOLD 12000 //Even more dangerous effects, threshold for tesla delamination
#define HEAT_PENALTY_THRESHOLD 40 //Higher == Crystal safe operational temperature is higher.
#define DAMAGE_HARDCAP 0.002
#define DAMAGE_INCREASE_MULTIPLIER 0.25
@@ -421,7 +421,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
if(prob(50))
radiation_pulse(src, power * (1 + (tritiumcomp * TRITIUM_RADIOACTIVITY_MODIFIER) + ((pluoxiumcomp * PLUOXIUM_RADIOACTIVITY_MODIFIER) * pluoxiumbonus) * (power_transmission_bonus/(10-(bzcomp * BZ_RADIOACTIVITY_MODIFIER))))) // Rad Modifiers BZ(500%), Tritium(300%), and Pluoxium(-200%)
if(bzcomp >= 0.4 && prob(30 * bzcomp))
- src.fire_nuclear_particles() // Start to emit radballs at a maximum of 30% chance per tick
+ fire_nuclear_particle() // Start to emit radballs at a maximum of 30% chance per tick
var/device_energy = power * REACTION_POWER_MODIFIER
diff --git a/code/modules/projectiles/ammunition/_firing.dm b/code/modules/projectiles/ammunition/_firing.dm
index 441088c78c..a83042c90a 100644
--- a/code/modules/projectiles/ammunition/_firing.dm
+++ b/code/modules/projectiles/ammunition/_firing.dm
@@ -1,8 +1,8 @@
-/obj/item/ammo_casing/proc/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread)
+/obj/item/ammo_casing/proc/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread, atom/fired_from)
distro += variance
for (var/i = max(1, pellets), i > 0, i--)
var/targloc = get_turf(target)
- ready_proj(target, user, quiet, zone_override)
+ ready_proj(target, user, quiet, zone_override, fired_from)
if(distro) //We have to spread a pixel-precision bullet. throw_proj was called before so angles should exist by now...
if(randomspread)
spread = round((rand() - 0.5) * distro)
@@ -20,11 +20,12 @@
update_icon()
return 1
-/obj/item/ammo_casing/proc/ready_proj(atom/target, mob/living/user, quiet, zone_override = "")
+/obj/item/ammo_casing/proc/ready_proj(atom/target, mob/living/user, quiet, zone_override = "", fired_from)
if (!BB)
return
BB.original = target
BB.firer = user
+ BB.fired_from = fired_from
if (zone_override)
BB.def_zone = zone_override
else
diff --git a/code/modules/projectiles/ammunition/caseless/_caseless.dm b/code/modules/projectiles/ammunition/caseless/_caseless.dm
index a6b65f79e3..11f7b8670d 100644
--- a/code/modules/projectiles/ammunition/caseless/_caseless.dm
+++ b/code/modules/projectiles/ammunition/caseless/_caseless.dm
@@ -3,7 +3,7 @@
firing_effect_type = null
heavy_metal = FALSE
-/obj/item/ammo_casing/caseless/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread)
+/obj/item/ammo_casing/caseless/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread, atom/fired_from)
if (..()) //successfully firing
moveToNullspace()
QDEL_NULL(src)
diff --git a/code/modules/projectiles/ammunition/energy/laser.dm b/code/modules/projectiles/ammunition/energy/laser.dm
index 638711e8d4..0940144721 100644
--- a/code/modules/projectiles/ammunition/energy/laser.dm
+++ b/code/modules/projectiles/ammunition/energy/laser.dm
@@ -71,9 +71,3 @@
projectile_type = /obj/item/projectile/beam/mindflayer
select_name = "MINDFUCK"
fire_sound = 'sound/weapons/laser.ogg'
-
-/obj/item/ammo_casing/energy/laser/weak
- projectile_type = /obj/item/projectile/beam/weak/minigun
- e_cost = 10
- fire_sound = 'sound/weapons/gatling.ogg'
- click_cooldown_override = 1
diff --git a/code/modules/projectiles/boxes_magazines/external/smg.dm b/code/modules/projectiles/boxes_magazines/external/smg.dm
index 65724e503a..783b8b895b 100644
--- a/code/modules/projectiles/boxes_magazines/external/smg.dm
+++ b/code/modules/projectiles/boxes_magazines/external/smg.dm
@@ -3,11 +3,11 @@
icon_state = "46x30mmt-20"
ammo_type = /obj/item/ammo_casing/c46x30mm
caliber = "4.6x30mm"
- max_ammo = 20
+ max_ammo = 32
/obj/item/ammo_box/magazine/wt550m9/update_icon()
..()
- icon_state = "46x30mmt-[round(ammo_count(),4)]"
+ icon_state = "46x30mmt-[round(20*(ammo_count()/max_ammo),4)]"
/obj/item/ammo_box/magazine/wt550m9/wtap
name = "wt550 magazine (Armour Piercing 4.6x30mm)"
@@ -16,7 +16,7 @@
/obj/item/ammo_box/magazine/wt550m9/wtap/update_icon()
..()
- icon_state = "46x30mmtA-[round(ammo_count(),4)]"
+ icon_state = "46x30mmtA-[round(20*(ammo_count()/max_ammo),4)]"
/obj/item/ammo_box/magazine/wt550m9/wtic
name = "wt550 magazine (Incendiary 4.6x30mm)"
@@ -25,7 +25,7 @@
/obj/item/ammo_box/magazine/wt550m9/wtic/update_icon()
..()
- icon_state = "46x30mmtI-[round(ammo_count(),4)]"
+ icon_state = "46x30mmtI-[round(20*(ammo_count()/max_ammo),4)]"
/obj/item/ammo_box/magazine/uzim9mm
name = "uzi magazine (9mm)"
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index fb3ed19f82..96b396243b 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -34,6 +34,7 @@
var/semicd = 0 //cooldown handler
var/weapon_weight = WEAPON_LIGHT //currently only used for inaccuracy
var/spread = 0 //Spread induced by the gun itself.
+ var/burst_spread = 0 //Spread induced by the gun itself during burst fire per iteration. Only checked if spread is 0.
var/randomspread = 1 //Set to 0 for shotguns. This is used for weapons that don't fire all their bullets at once.
var/inaccuracy_modifier = 1
@@ -62,16 +63,18 @@
var/zoomed = FALSE //Zoom toggle
var/zoom_amt = 3 //Distance in TURFs to move the user's screen forward (the "zoom" effect)
var/zoom_out_amt = 0
- var/datum/action/toggle_scope_zoom/azoom
+ var/datum/action/item_action/toggle_scope_zoom/azoom
+
+ var/dualwield_spread_mult = 1 //dualwield spread multiplier
/obj/item/gun/Initialize()
. = ..()
if(pin)
pin = new pin(src)
if(gun_light)
- alight = new /datum/action/item_action/toggle_gunlight(src)
- build_zooming()
-
+ alight = new (src)
+ if(zoomable)
+ azoom = new (src)
/obj/item/gun/CheckParts(list/parts_list)
..()
@@ -185,7 +188,7 @@
if(G == src || G.weapon_weight >= WEAPON_MEDIUM)
continue
else if(G.can_trigger_gun(user))
- bonus_spread += 24 * G.weapon_weight
+ bonus_spread += 24 * G.weapon_weight * G.dualwield_spread_mult
loop_counter++
addtimer(CALLBACK(G, /obj/item/gun.proc/process_fire, target, user, TRUE, params, null, bonus_spread), loop_counter)
@@ -226,11 +229,11 @@
to_chat(user, " [src] is lethally chambered! You don't want to risk harming anyone...")
return
if(randomspread)
- sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread))
+ sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread), 1)
else //Smart spread
- sprd = round((((rand_spr/burst_size) * iteration) - (0.5 + (rand_spr * 0.25))) * (randomized_gun_spread + randomized_bonus_spread))
+ sprd = round((((rand_spr/burst_size) * iteration) - (0.5 + (rand_spr * 0.25))) * (randomized_gun_spread + randomized_bonus_spread), 1)
- if(!chambered.fire_casing(target, user, params, ,suppressed, zone_override, sprd))
+ if(!chambered.fire_casing(target, user, params, ,suppressed, zone_override, sprd, src))
shoot_with_empty_chamber(user)
firing_burst = FALSE
return FALSE
@@ -259,7 +262,9 @@
var/randomized_gun_spread = 0
var/rand_spr = rand()
if(spread)
- randomized_gun_spread = rand(0,spread)
+ randomized_gun_spread = rand(0, spread)
+ else if(burst_size > 1 && burst_spread)
+ randomized_gun_spread = rand(0, burst_spread)
if(HAS_TRAIT(user, TRAIT_POOR_AIM)) //nice shootin' tex
bonus_spread += 25
var/randomized_bonus_spread = rand(0, bonus_spread)
@@ -275,7 +280,7 @@
to_chat(user, " [src] is lethally chambered! You don't want to risk harming anyone...")
return
sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread))
- if(!chambered.fire_casing(target, user, params, , suppressed, zone_override, sprd))
+ if(!chambered.fire_casing(target, user, params, , suppressed, zone_override, sprd, src))
shoot_with_empty_chamber(user)
return
else
@@ -293,6 +298,7 @@
if(user)
user.update_inv_hands()
+ SEND_SIGNAL(user, COMSIG_LIVING_GUN_PROCESS_FIRE, target, params, zone_override)
SSblackbox.record_feedback("tally", "gun_fired", 1, type)
return TRUE
@@ -372,6 +378,12 @@
else
return ..()
+/obj/item/gun/ui_action_click(mob/user, action)
+ if(istype(action, /datum/action/item_action/toggle_scope_zoom))
+ zoom(user)
+ else if(istype(action, alight))
+ toggle_gunlight()
+
/obj/item/gun/proc/toggle_gunlight()
if(!gun_light)
return
@@ -407,21 +419,10 @@
var/datum/action/A = X
A.UpdateButtonIcon()
-/obj/item/gun/pickup(mob/user)
- ..()
- if(azoom)
- azoom.Grant(user)
- if(alight)
- alight.Grant(user)
-
-/obj/item/gun/dropped(mob/user)
- ..()
- if(zoomed)
- zoom(user,FALSE)
- if(azoom)
- azoom.Remove(user)
- if(alight)
- alight.Remove(user)
+/obj/item/gun/item_action_slot_check(slot, mob/user, datum/action/A)
+ if(istype(A, /datum/action/item_action/toggle_scope_zoom) && slot != SLOT_HANDS)
+ return FALSE
+ return ..()
/obj/item/gun/proc/handle_suicide(mob/living/carbon/human/user, mob/living/carbon/human/target, params, bypass_timer)
if(!ishuman(user) || !ishuman(target))
@@ -468,41 +469,32 @@
// ZOOMING //
/////////////
-/datum/action/toggle_scope_zoom
+/datum/action/item_action/toggle_scope_zoom
name = "Toggle Scope"
- check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_LYING
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "sniper_zoom"
- var/obj/item/gun/gun = null
-/datum/action/toggle_scope_zoom/Trigger()
- gun.zoom(owner)
-
-/datum/action/toggle_scope_zoom/IsAvailable()
+/datum/action/item_action/toggle_scope_zoom/IsAvailable()
. = ..()
- if(!gun)
- return FALSE
if(!.)
- gun.zoom(owner, FALSE)
- if(!owner.get_held_index_of_item(gun))
- return FALSE
-
-/datum/action/toggle_scope_zoom/Remove(mob/living/L)
- gun.zoom(L, FALSE)
- ..()
+ var/obj/item/gun/G = target
+ G.zoom(owner, FALSE)
+/datum/action/item_action/toggle_scope_zoom/Remove(mob/living/L)
+ var/obj/item/gun/G = target
+ G.zoom(L, FALSE)
+ return ..()
/obj/item/gun/proc/zoom(mob/living/user, forced_zoom)
- if(!user || !user.client)
+ if(!(user?.client))
return
- switch(forced_zoom)
- if(FALSE)
- zoomed = FALSE
- if(TRUE)
- zoomed = TRUE
- else
- zoomed = !zoomed
+ if(!isnull(forced_zoom))
+ if(zoomed == forced_zoom)
+ return
+ zoomed = forced_zoom
+ else
+ zoomed = !zoomed
if(zoomed)
var/_x = 0
@@ -524,16 +516,6 @@
user.client.change_view(CONFIG_GET(string/default_view))
user.client.pixel_x = 0
user.client.pixel_y = 0
- return zoomed
-
-//Proc, so that gun accessories/scopes/etc. can easily add zooming.
-/obj/item/gun/proc/build_zooming()
- if(azoom)
- return
-
- if(zoomable)
- azoom = new()
- azoom.gun = src
/obj/item/gun/handle_atom_del(atom/A)
if(A == chambered)
diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm
index 1117bc1000..2f198c1319 100644
--- a/code/modules/projectiles/guns/ballistic.dm
+++ b/code/modules/projectiles/guns/ballistic.dm
@@ -26,7 +26,6 @@
else
icon_state = "[initial(icon_state)][suppressed ? "-suppressed" : ""][sawn_off ? "-sawn" : ""]"
-
/obj/item/gun/ballistic/process_chamber(empty_chamber = 1)
var/obj/item/ammo_casing/AC = chambered //Find chambered round
if(istype(AC)) //there's a chambered round
@@ -170,7 +169,7 @@
if(iscarbon(user))
var/mob/living/carbon/C = user
user_dna = C.dna
- B.add_blood_DNA(user_dna)
+ B.add_blood_DNA(user_dna, C.diseases)
var/datum/callback/gibspawner = CALLBACK(GLOBAL_PROC, /proc/spawn_atom_to_turf, /obj/effect/gibspawner/generic, B, 1, FALSE, list(user_dna))
B.throw_at(target, BRAINS_BLOWN_THROW_RANGE, BRAINS_BLOWN_THROW_SPEED, callback=gibspawner)
return(BRUTELOSS)
diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm
index 4bd65a7b20..5182c96671 100644
--- a/code/modules/projectiles/guns/ballistic/automatic.dm
+++ b/code/modules/projectiles/guns/ballistic/automatic.dm
@@ -2,6 +2,7 @@
w_class = WEIGHT_CLASS_NORMAL
var/alarmed = 0
var/select = 1
+ var/automatic_burst_overlay = TRUE
can_suppress = TRUE
burst_size = 3
fire_delay = 2
@@ -19,10 +20,11 @@
/obj/item/gun/ballistic/automatic/update_icon()
..()
- if(!select)
- add_overlay("[initial(icon_state)]semi")
- if(select == 1)
- add_overlay("[initial(icon_state)]burst")
+ if(automatic_burst_overlay)
+ if(!select)
+ add_overlay("[initial(icon_state)]semi")
+ if(select == 1)
+ add_overlay("[initial(icon_state)]burst")
icon_state = "[initial(icon_state)][magazine ? "-[magazine.max_ammo]" : ""][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
/obj/item/gun/ballistic/automatic/attackby(obj/item/A, mob/user, params)
@@ -51,19 +53,20 @@
else
to_chat(user, "You cannot seem to get \the [src] out of your hands!")
-/obj/item/gun/ballistic/automatic/ui_action_click()
- burst_select()
+/obj/item/gun/ballistic/automatic/ui_action_click(mob/user, action)
+ if(istype(action, /datum/action/item_action/toggle_firemode))
+ burst_select()
+ else
+ return ..()
/obj/item/gun/ballistic/automatic/proc/burst_select()
var/mob/living/carbon/human/user = usr
select = !select
if(!select)
- burst_size = 1
- fire_delay = 0
+ disable_burst()
to_chat(user, "You switch to semi-automatic.")
else
- burst_size = initial(burst_size)
- fire_delay = initial(fire_delay)
+ enable_burst()
to_chat(user, "You switch to [burst_size]-rnd burst.")
playsound(user, 'sound/weapons/empty.ogg', 100, 1)
@@ -72,6 +75,14 @@
var/datum/action/A = X
A.UpdateButtonIcon()
+/obj/item/gun/ballistic/automatic/proc/enable_burst()
+ burst_size = initial(burst_size)
+ fire_delay = initial(fire_delay)
+
+/obj/item/gun/ballistic/automatic/proc/disable_burst()
+ burst_size = 1
+ fire_delay = 0
+
/obj/item/gun/ballistic/automatic/can_shoot()
return get_ammo()
@@ -106,7 +117,6 @@
/obj/item/gun/ballistic/automatic/c20r/afterattack()
. = ..()
empty_alarm()
- return
/obj/item/gun/ballistic/automatic/c20r/update_icon()
..()
@@ -118,17 +128,25 @@
icon_state = "wt550"
item_state = "arg"
mag_type = /obj/item/ammo_box/magazine/wt550m9
- fire_delay = 2
can_suppress = FALSE
- burst_size = 0
- actions_types = list()
+ burst_size = 2
+ fire_delay = 1
can_bayonet = TRUE
knife_x_offset = 25
knife_y_offset = 12
+ automatic_burst_overlay = FALSE
+
+/obj/item/gun/ballistic/automatic/wt550/enable_burst()
+ . = ..()
+ spread = 15
+
+/obj/item/gun/ballistic/automatic/wt550/disable_burst()
+ . = ..()
+ spread = 0
/obj/item/gun/ballistic/automatic/wt550/update_icon()
..()
- icon_state = "wt550[magazine ? "-[CEILING(get_ammo(0)/4, 1)*4]" : ""]"
+ icon_state = "wt550[magazine ? "-[CEILING(( (get_ammo(FALSE) / magazine.max_ammo) * 20) /4, 1)*4]" : "-0"]" //Sprites only support up to 20.
/obj/item/gun/ballistic/automatic/mini_uzi
name = "\improper Type U3 Uzi"
diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm
index 6060ceba99..2cccc57d9e 100644
--- a/code/modules/projectiles/guns/energy.dm
+++ b/code/modules/projectiles/guns/energy.dm
@@ -174,9 +174,6 @@
itemState += "[ratio]"
item_state = itemState
-/obj/item/gun/energy/ui_action_click()
- toggle_gunlight()
-
/obj/item/gun/energy/suicide_act(mob/living/user)
if (istype(user) && can_shoot() && can_trigger_gun(user) && user.get_bodypart(BODY_ZONE_HEAD))
user.visible_message("[user] is putting the barrel of [src] in [user.p_their()] mouth. It looks like [user.p_theyre()] trying to commit suicide!")
diff --git a/code/modules/projectiles/guns/energy/energy_gun.dm b/code/modules/projectiles/guns/energy/energy_gun.dm
index de738c9047..163deae0ed 100644
--- a/code/modules/projectiles/guns/energy/energy_gun.dm
+++ b/code/modules/projectiles/guns/energy/energy_gun.dm
@@ -55,7 +55,7 @@
desc = "This is an expensive, modern recreation of an antique laser gun. This gun has several unique firemodes, but lacks the ability to recharge over time."
icon_state = "hoslaser"
force = 10
- ammo_type = list(/obj/item/ammo_casing/energy/electrode/hos, /obj/item/ammo_casing/energy/laser/hos, /obj/item/ammo_casing/energy/disabler)
+ ammo_type = list(/obj/item/ammo_casing/energy/electrode/hos, /obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser/hos)
ammo_x_offset = 4
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
@@ -97,7 +97,7 @@
pin = null
can_charge = 0
ammo_x_offset = 1
- ammo_type = list(/obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/laser, /obj/item/ammo_casing/energy/disabler)
+ ammo_type = list(/obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/laser)
selfcharge = EGUN_SELFCHARGE
var/fail_tick = 0
var/fail_chance = 0
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index a4ec979a06..646b4bd57d 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -78,6 +78,12 @@
else
to_chat(user, "There are no modifications currently installed.")
+/obj/item/gun/energy/kinetic_accelerator/Exited(atom/movable/AM)
+ . = ..()
+ if((AM in modkits) && istype(AM, /obj/item/borg/upgrade/modkit))
+ var/obj/item/borg/upgrade/modkit/M = AM
+ M.uninstall(src, FALSE)
+
/obj/item/gun/energy/kinetic_accelerator/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/borg/upgrade/modkit))
var/obj/item/borg/upgrade/modkit/MK = I
@@ -261,7 +267,7 @@
icon_state = "modkit"
w_class = WEIGHT_CLASS_SMALL
require_module = 1
- module_type = /obj/item/robot_module/miner
+ module_type = list(/obj/item/robot_module/miner)
var/denied_type = null
var/maximum_of_type = 1
var/cost = 30
@@ -287,6 +293,8 @@
/obj/item/borg/upgrade/modkit/proc/install(obj/item/gun/energy/kinetic_accelerator/KA, mob/user)
. = TRUE
+ if(src in KA.modkits) // Sanity check to prevent installing the same modkit twice thanks to occasional click/lag delays.
+ return
if(minebot_upgrade)
if(minebot_exclusive && !istype(KA.loc, /mob/living/simple_animal/hostile/mining_drone))
to_chat(user, "The modkit you're trying to install is only rated for minebot use.")
@@ -322,11 +330,10 @@
for(var/obj/item/gun/energy/kinetic_accelerator/cyborg/KA in R.module.modules)
uninstall(KA)
-/obj/item/borg/upgrade/modkit/proc/uninstall(obj/item/gun/energy/kinetic_accelerator/KA)
- forceMove(get_turf(KA))
+/obj/item/borg/upgrade/modkit/proc/uninstall(obj/item/gun/energy/kinetic_accelerator/KA, forcemove = TRUE)
KA.modkits -= src
-
-
+ if(forcemove)
+ forceMove(get_turf(KA))
/obj/item/borg/upgrade/modkit/proc/modify_projectile(obj/item/projectile/kinetic/K)
diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm
index bb97f9cf99..2bb813d793 100644
--- a/code/modules/projectiles/guns/energy/laser.dm
+++ b/code/modules/projectiles/guns/energy/laser.dm
@@ -181,7 +181,7 @@
/obj/item/gun/energy/laser/redtag/hitscan/chaplain/Initialize()
. = ..()
- AddComponent(/datum/component/anti_magic, TRUE, TRUE)
+ AddComponent(/datum/component/anti_magic, TRUE, TRUE, FALSE, null, null, FALSE)
/obj/item/gun/energy/laser/redtag/hitscan/chaplain/handle_suicide(mob/living/carbon/human/user, mob/living/carbon/human/target, params, bypass_timer)
if(!ishuman(user) || !ishuman(target))
diff --git a/code/modules/projectiles/guns/energy/minigun.dm b/code/modules/projectiles/guns/energy/minigun.dm
deleted file mode 100644
index d903cda47c..0000000000
--- a/code/modules/projectiles/guns/energy/minigun.dm
+++ /dev/null
@@ -1,149 +0,0 @@
-//The ammo/gun is stored in a back slot item
-/obj/item/minigunpack2
- name = " Laser Gatling Pack"
- desc = "A massive battery pack with an attached laser gatling gun!"
- icon = 'icons/obj/guns/minigun.dmi'
- icon_state = "holstered"
- item_state = "backpack"
- lefthand_file = 'icons/mob/inhands/equipment/backpack_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/equipment/backpack_righthand.dmi'
- slot_flags = ITEM_SLOT_BACK
- w_class = WEIGHT_CLASS_HUGE
- var/obj/item/gun/energy/minigun/gun
- var/armed = 0 //whether the gun is attached, 0 is attached, 1 is the gun is wielded.
- var/overheat = 0
- var/overheat_max = 60
- var/heat_diffusion = 5
-
-/obj/item/minigunpack2/Initialize()
- . = ..()
- gun = new(src)
- START_PROCESSING(SSobj, src)
-
-/obj/item/minigunpack2/Destroy()
- STOP_PROCESSING(SSobj, src)
- return ..()
-
-/obj/item/minigunpack2/process()
- overheat = max(0, overheat - heat_diffusion)
-
-//ATTACK HAND IGNORING PARENT RETURN VALUE
-/obj/item/minigunpack2/attack_hand(var/mob/living/carbon/user)
- if(src.loc == user)
- if(!armed)
- if(user.get_item_by_slot(SLOT_BACK) == src)
- armed = 1
- if(!user.put_in_hands(gun))
- armed = 0
- to_chat(user, "You need a free hand to hold the gun!")
- return
- update_icon()
- user.update_inv_back()
- else
- to_chat(user, "You are already holding the gun!")
- else
- ..()
-
-/obj/item/minigunpack2/attackby(obj/item/W, mob/user, params)
- if(W == gun) //Don't need armed check, because if you have the gun assume its armed.
- user.dropItemToGround(gun, TRUE)
- else
- ..()
-
-/obj/item/minigunpack2/dropped(mob/user)
- if(armed)
- user.dropItemToGround(gun, TRUE)
-
-/obj/item/minigunpack2/MouseDrop(atom/over_object)
- . = ..()
- if(armed)
- return
- if(iscarbon(usr))
- var/mob/M = usr
-
- if(!over_object)
- return
-
- if(!M.incapacitated())
-
- if(istype(over_object, /obj/screen/inventory/hand))
- var/obj/screen/inventory/hand/H = over_object
- M.putItemFromInventoryInHandIfPossible(src, H.held_index)
-
-
-/obj/item/minigunpack2/update_icon()
- if(armed)
- icon_state = "notholstered"
- else
- icon_state = "holstered"
-
-/obj/item/minigunpack2/proc/attach_gun(var/mob/user)
- if(!gun)
- gun = new(src)
- gun.forceMove(src)
- armed = 0
- if(user)
- to_chat(user, "You attach the [gun.name] to the [name].")
- else
- src.visible_message("The [gun.name] snaps back onto the [name]!")
- update_icon()
- user.update_inv_back()
-
-
-/obj/item/gun/energy/minigun
- name = "laser gatling gun"
- desc = "An advanced laser cannon with an incredible rate of fire. Requires a bulky backpack power source to use."
- icon = 'icons/obj/guns/minigun.dmi'
- icon_state = "minigun_spin"
- item_state = "minigun"
- flags_1 = CONDUCT_1
- force = 15
- recoil = 2
- slowdown = 1
- slot_flags = null
- w_class = WEIGHT_CLASS_HUGE
- materials = list()
- ammo_type = list(/obj/item/ammo_casing/energy/laser/weak)
- burst_size = 2
- automatic = 1
- can_charge = 0
- selfcharge = EGUN_SELFCHARGE
- charge_tick = 2
- charge_delay = 5
- weapon_weight = WEAPON_HEAVY
- item_flags = NEEDS_PERMIT | SLOWS_WHILE_IN_HAND
- var/obj/item/minigunpack2/ammo_pack
-
-/obj/item/gun/energy/minigun/Initialize()
- if(istype(loc, /obj/item/minigunpack2)) //We should spawn inside an ammo pack so let's use that one.
- ammo_pack = loc
- else
- return INITIALIZE_HINT_QDEL //No pack, no gun
-
- return ..()
-
-/obj/item/gun/energy/minigun/attack_self(mob/living/user)
- return
-
-/obj/item/gun/energy/minigun/dropped(mob/user)
- if(ammo_pack)
- ammo_pack.attach_gun(user)
- else
- qdel(src)
-
-/obj/item/gun/energy/minigun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
- if(ammo_pack)
- if(ammo_pack.overheat < ammo_pack.overheat_max)
- ammo_pack.overheat += burst_size
- ..()
- else
- to_chat(user, "The gun's heat sensor locked the trigger to prevent lens damage.")
-
-/obj/item/gun/energy/minigun/afterattack(atom/target, mob/living/user, flag, params)
- if(!ammo_pack || ammo_pack.loc != user)
- to_chat(user, "You need the backpack power source to fire the gun!")
- . = ..()
-
-/obj/item/gun/energy/minigun/dropped(mob/living/user)
- ammo_pack.attach_gun(user)
-
diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm
index 44c7894467..c5d4c36813 100644
--- a/code/modules/projectiles/guns/energy/stun.dm
+++ b/code/modules/projectiles/guns/energy/stun.dm
@@ -20,7 +20,7 @@
name = "hybrid taser"
desc = "A dual-mode taser designed to fire both short-range high-power electrodes and long-range disabler beams."
icon_state = "advtaser"
- ammo_type = list(/obj/item/ammo_casing/energy/electrode, /obj/item/ammo_casing/energy/disabler)
+ ammo_type = list(/obj/item/ammo_casing/energy/disabler, /obj/item/ammo_casing/energy/electrode)
ammo_x_offset = 2
/obj/item/gun/energy/e_gun/advtaser/cyborg
diff --git a/code/modules/projectiles/guns/magic.dm b/code/modules/projectiles/guns/magic.dm
index 9dd25bf3e3..55f21a5a2b 100644
--- a/code/modules/projectiles/guns/magic.dm
+++ b/code/modules/projectiles/guns/magic.dm
@@ -9,6 +9,7 @@
fire_sound = 'sound/weapons/emitter.ogg'
flags_1 = CONDUCT_1
w_class = WEIGHT_CLASS_HUGE
+ var/checks_antimagic = FALSE
var/max_charges = 6
var/charges = 0
var/recharge_rate = 4
@@ -31,6 +32,9 @@
return
else
no_den_usage = 0
+ if(checks_antimagic && user.anti_magic_check(TRUE, FALSE, FALSE, 0, TRUE))
+ to_chat(user, "Something is interfering with [src].")
+ return
. = ..()
/obj/item/gun/magic/can_shoot()
diff --git a/code/modules/projectiles/guns/magic/wand.dm b/code/modules/projectiles/guns/magic/wand.dm
index 42033d8c88..4cdfc6d70d 100644
--- a/code/modules/projectiles/guns/magic/wand.dm
+++ b/code/modules/projectiles/guns/magic/wand.dm
@@ -87,14 +87,17 @@
max_charges = 10 //10, 5, 5, 4
/obj/item/gun/magic/wand/resurrection/zap_self(mob/living/user)
+ ..()
+ charges--
+ if(user.anti_magic_check())
+ user.visible_message("[src] has no effect on [user]!")
+ return
user.revive(full_heal = 1)
if(iscarbon(user))
var/mob/living/carbon/C = user
C.regenerate_limbs()
C.regenerate_organs()
to_chat(user, "You feel great!")
- charges--
- ..()
/obj/item/gun/magic/wand/resurrection/debug //for testing
name = "debug wand of healing"
diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm
index e4d13ad315..92fe91c222 100644
--- a/code/modules/projectiles/guns/misc/beam_rifle.dm
+++ b/code/modules/projectiles/guns/misc/beam_rifle.dm
@@ -45,7 +45,7 @@
var/aiming_lastangle = 0
var/mob/current_user = null
var/list/obj/effect/projectile/tracer/current_tracers
-
+
var/structure_piercing = 1
var/structure_bleed_coeff = 0.7
var/wall_pierce_amount = 0
@@ -76,7 +76,7 @@
var/static/image/drained_overlay = image(icon = 'icons/obj/guns/energy.dmi', icon_state = "esniper_empty")
var/datum/action/item_action/zoom_lock_action/zoom_lock_action
- var/datum/component/mobhook
+ var/mob/listeningTo
/obj/item/gun/energy/beam_rifle/debug
delay = 0
@@ -111,7 +111,9 @@
to_chat(owner, "You switch [src]'s zooming processor to center mode.")
if(ZOOM_LOCK_OFF)
to_chat(owner, "You disable [src]'s zooming system.")
- reset_zooming()
+ reset_zooming()
+ else
+ return ..()
/obj/item/gun/energy/beam_rifle/proc/set_autozoom_pixel_offsets_immediate(current_angle)
if(zoom_lock == ZOOM_LOCK_CENTER_VIEW || zoom_lock == ZOOM_LOCK_OFF)
@@ -172,7 +174,7 @@
STOP_PROCESSING(SSfastprocess, src)
set_user(null)
QDEL_LIST(current_tracers)
- QDEL_NULL(mobhook)
+ listeningTo = null
return ..()
/obj/item/gun/energy/beam_rifle/emp_act(severity)
@@ -259,14 +261,17 @@
if(user == current_user)
return
stop_aiming(current_user)
- QDEL_NULL(mobhook)
+ if(listeningTo)
+ UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+ listeningTo = null
if(istype(current_user))
LAZYREMOVE(current_user.mousemove_intercept_objects, src)
current_user = null
if(istype(user))
current_user = user
LAZYOR(current_user.mousemove_intercept_objects, src)
- mobhook = user.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_mob_move)))
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/on_mob_move)
+ listeningTo = user
/obj/item/gun/energy/beam_rifle/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
if(aiming)
diff --git a/code/modules/projectiles/guns/misc/syringe_gun.dm b/code/modules/projectiles/guns/misc/syringe_gun.dm
index 26e66b1987..342ceecbc2 100644
--- a/code/modules/projectiles/guns/misc/syringe_gun.dm
+++ b/code/modules/projectiles/guns/misc/syringe_gun.dm
@@ -122,3 +122,32 @@
else
to_chat(user, "You can't put the [A] into \the [src]!")
return FALSE
+
+/obj/item/gun/syringe/dart/rapiddart
+ name = "Repeating dart gun"
+ icon_state = "rapiddartgun"
+ item_state = "rapiddartgun"
+
+/obj/item/gun/syringe/dart/rapiddart/CheckParts(list/parts_list)
+ var/obj/item/reagent_containers/glass/beaker/B = locate(/obj/item/reagent_containers/glass/beaker) in parts_list
+
+ if(istype(B, /obj/item/reagent_containers/glass/beaker/large))
+ desc = "[initial(desc)] A modification of the dart gun's pressure chamber has been perfomed using a [B], extending it's holding size to [max_syringes]."
+ max_syringes = 2
+ return
+ else if(istype(B, /obj/item/reagent_containers/glass/beaker/plastic))
+ desc = "[initial(desc)] A modification of the dart gun's pressure chamber has been perfomed using a [B], extending it's holding size to [max_syringes]."
+ max_syringes = 3
+ return
+ else if(istype(B, /obj/item/reagent_containers/glass/beaker/meta))
+ desc = "[initial(desc)] A modification of the dart gun's pressure chamber has been perfomed using a [B], extending it's holding size to [max_syringes]."
+ max_syringes = 4
+ return
+ else if(istype(B, /obj/item/reagent_containers/glass/beaker/bluespace))
+ desc = "[initial(desc)] A modification of the dart gun's pressure chamber has been perfomed using a [B], extending it's holding size to [max_syringes]."
+ max_syringes = 6
+ return
+ else
+ max_syringes = 1
+ desc = "[initial(desc)] It has a [B] strapped to it, but it doesn't seem to be doing anything."
+ ..()
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index efae090707..88e766edfc 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -17,6 +17,7 @@
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/def_zone = "" //Aiming at
var/atom/movable/firer = null//Who shot it
+ var/atom/fired_from = null // the atom that the projectile was fired from (gun, turret)
var/suppressed = FALSE //Attack message
var/candink = FALSE //Can this projectile play the dink sound when hitting the head?
var/yo = null
@@ -88,6 +89,8 @@
//Effects
var/stun = 0
var/knockdown = 0
+ var/knockdown_stamoverride
+ var/knockdown_stam_max
var/unconscious = 0
var/irradiate = 0
var/stutter = 0
@@ -129,6 +132,8 @@
return TRUE
/obj/item/projectile/proc/on_hit(atom/target, blocked = FALSE)
+ if(fired_from)
+ SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_ON_HIT, firer, target, Angle)
var/turf/target_loca = get_turf(target)
var/hitx
@@ -161,15 +166,26 @@
var/splatter_dir = dir
if(starting)
splatter_dir = get_dir(starting, target_loca)
- if(isalien(L))
+ var/obj/item/bodypart/B = L.get_bodypart(def_zone)
+ if(B && B.status == BODYPART_ROBOTIC) // So if you hit a robotic, it sparks instead of bloodspatters
+ do_sparks(2, FALSE, target.loc)
+ if(prob(25))
+ new /obj/effect/decal/cleanable/oil(target_loca)
+ else if(isalien(L))
new /obj/effect/temp_visual/dir_setting/bloodsplatter/xenosplatter(target_loca, splatter_dir)
else
- new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir)
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, bloodtype_to_color(H.dna.blood_type))
+ else
+ new /obj/effect/temp_visual/dir_setting/bloodsplatter(target_loca, splatter_dir, bloodtype_to_color())
+
if(iscarbon(L))
var/mob/living/carbon/C = L
C.bleed(damage)
else
L.add_splatter_floor(target_loca)
+
else if(impact_effect_type && !hitscan)
new impact_effect_type(target_loca, hitx, hity)
@@ -202,7 +218,7 @@
else
L.log_message("has been shot by [firer] with [src]", LOG_ATTACK, color="orange")
- return L.apply_effects(stun, knockdown, unconscious, irradiate, slur, stutter, eyeblur, drowsy, blocked, stamina, jitter)
+ return L.apply_effects(stun, knockdown, unconscious, irradiate, slur, stutter, eyeblur, drowsy, blocked, stamina, jitter, knockdown_stamoverride, knockdown_stam_max)
/obj/item/projectile/proc/vol_by_damage()
if(src.damage)
@@ -219,8 +235,8 @@
beam_segments[beam_index] = null
/obj/item/projectile/Bump(atom/A)
- var/datum/point/pcache = trajectory.copy_to()
- if(check_ricochet(A) && check_ricochet_flag(A) && ricochets < ricochets_max)
+ if(trajectory && check_ricochet(A) && check_ricochet_flag(A) && ricochets < ricochets_max)
+ var/datum/point/pcache = trajectory.copy_to()
ricochets++
if(A.handle_ricochet(src))
on_ricochet(A)
@@ -343,6 +359,8 @@
pixel_move(1, FALSE)
/obj/item/projectile/proc/fire(angle, atom/direct_target)
+ if(fired_from)
+ SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_BEFORE_FIRE, src, original)
//If no angle needs to resolve it from xo/yo!
if(!log_override && firer && original)
log_combat(firer, original, "fired at", src, "from [get_area_name(src, TRUE)]")
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index d8154b367d..e43eb5a3bc 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -39,14 +39,6 @@
/obj/item/projectile/beam/weak
damage = 15
-/obj/item/projectile/beam/weak/minigun
- damage = 12.5
- armour_penetration = 40
-
-/obj/item/projectile/beam/weak/minigun/Initialize()
- .=..()
- speed = pick(0.7,0.75,0.8,0.85,0.9,0.95,1,1.05,1.1,1.15)
-
/obj/item/projectile/beam/weak/penetrator
armour_penetration = 50
diff --git a/code/modules/projectiles/projectile/bullets/smg.dm b/code/modules/projectiles/projectile/bullets/smg.dm
index dfc6df537d..94ec2d3c2b 100644
--- a/code/modules/projectiles/projectile/bullets/smg.dm
+++ b/code/modules/projectiles/projectile/bullets/smg.dm
@@ -1,60 +1,69 @@
-// .45 (M1911 & C20r)
-
-/obj/item/projectile/bullet/c45
- name = ".45 bullet"
- damage = 20
- stamina = 65
-
-/obj/item/projectile/bullet/c45_nostamina
- name = ".45 bullet"
- damage = 30
-
-/obj/item/projectile/bullet/c45_cleaning
- name = ".45 bullet"
- damage = 24
- stamina = 10
-
-/obj/item/projectile/bullet/c45_cleaning/on_hit(atom/target, blocked = FALSE)
- . = ..()
- var/turf/T = get_turf(target)
-
- //section shamelessly copypasta'd from the clean component
- SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- for(var/A in T)
- if(is_cleanable(A))
- qdel(A)
- else if(istype(A, /obj/item))
- var/obj/item/I = A
- SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- if(ismob(I.loc))
- var/mob/M = I.loc
- M.regenerate_icons()
- else if(ishuman(A))
- var/mob/living/carbon/human/cleaned_human = A
- if(cleaned_human.head)
- SEND_SIGNAL(cleaned_human.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- if(cleaned_human.wear_suit)
- SEND_SIGNAL(cleaned_human.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- else if(cleaned_human.w_uniform)
- SEND_SIGNAL(cleaned_human.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- if(cleaned_human.shoes)
- SEND_SIGNAL(cleaned_human.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- SEND_SIGNAL(cleaned_human, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
- cleaned_human.wash_cream()
- cleaned_human.regenerate_icons()
-
-// 4.6x30mm (Autorifles)
-
-/obj/item/projectile/bullet/c46x30mm
- name = "4.6x30mm bullet"
- damage = 20
-
-/obj/item/projectile/bullet/c46x30mm_ap
- name = "4.6x30mm armor-piercing bullet"
- damage = 15
- armour_penetration = 40
-
-/obj/item/projectile/bullet/incendiary/c46x30mm
- name = "4.6x30mm incendiary bullet"
- damage = 10
- fire_stacks = 1
+// .45 (M1911 & C20r)
+
+/obj/item/projectile/bullet/c45
+ name = ".45 bullet"
+ damage = 20
+ stamina = 65
+
+/obj/item/projectile/bullet/c45_nostamina
+ name = ".45 bullet"
+ damage = 30
+
+/obj/item/projectile/bullet/c45_cleaning
+ name = ".45 bullet"
+ damage = 24
+ stamina = 10
+
+/obj/item/projectile/bullet/c45_cleaning/on_hit(atom/target, blocked = FALSE)
+ . = ..()
+ var/turf/T = get_turf(target)
+ SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ for(var/A in T)
+ if(is_cleanable(A))
+ qdel(A)
+ else if(isitem(A))
+ var/obj/item/cleaned_item = A
+ SEND_SIGNAL(cleaned_item, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_item.clean_blood()
+ if(ismob(cleaned_item.loc))
+ var/mob/M = cleaned_item.loc
+ M.regenerate_icons()
+ else if(ishuman(A))
+ var/mob/living/carbon/human/cleaned_human = A
+ if(cleaned_human.lying)
+ if(cleaned_human.head)
+ SEND_SIGNAL(cleaned_human.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.head.clean_blood()
+ cleaned_human.update_inv_head()
+ if(cleaned_human.wear_suit)
+ SEND_SIGNAL(cleaned_human.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.wear_suit.clean_blood()
+ cleaned_human.update_inv_wear_suit()
+ else if(cleaned_human.w_uniform)
+ SEND_SIGNAL(cleaned_human.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.w_uniform.clean_blood()
+ cleaned_human.update_inv_w_uniform()
+ if(cleaned_human.shoes)
+ SEND_SIGNAL(cleaned_human.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.shoes.clean_blood()
+ cleaned_human.update_inv_shoes()
+ SEND_SIGNAL(cleaned_human, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ cleaned_human.clean_blood()
+ cleaned_human.wash_cream()
+ cleaned_human.regenerate_icons()
+
+// 4.6x30mm (Autorifles)
+
+/obj/item/projectile/bullet/c46x30mm
+ name = "4.6x30mm bullet"
+ damage = 15
+
+/obj/item/projectile/bullet/c46x30mm_ap
+ name = "4.6x30mm armor-piercing bullet"
+ damage = 12.5
+ armour_penetration = 40
+
+/obj/item/projectile/bullet/incendiary/c46x30mm
+ name = "4.6x30mm incendiary bullet"
+ damage = 7.5
+ fire_stacks = 1
diff --git a/code/modules/projectiles/projectile/energy/nuclear_particle.dm b/code/modules/projectiles/projectile/energy/nuclear_particle.dm
index 1753587ad3..e08f806fe5 100644
--- a/code/modules/projectiles/projectile/energy/nuclear_particle.dm
+++ b/code/modules/projectiles/projectile/energy/nuclear_particle.dm
@@ -3,10 +3,9 @@
name = "nuclear particle"
icon_state = "nuclear_particle"
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
- damage = 20
- damage_type = TOX
- irradiate = 2500 //enough to knockdown and induce vomiting
- speed = 0.4
+ flag = "rad"
+ irradiate = 5000
+ speed = 0.4
hitsound = 'sound/weapons/emitter2.ogg'
impact_type = /obj/effect/projectile/impact/xray
var/static/list/particle_colors = list(
@@ -25,22 +24,6 @@
add_atom_colour(particle_colors[our_color], FIXED_COLOUR_PRIORITY)
set_light(4, 3, particle_colors[our_color]) //Range of 4, brightness of 3 - Same range as a flashlight
-/atom/proc/fire_nuclear_particles(power_ratio) //used by fusion to fire random # of nuclear particles - power ratio determines about how many are fired
- var/random_particles = rand(3,6)
- var/particles_to_fire
- var/particles_fired
- switch(power_ratio) //multiply random_particles * factor for whatever tier
- if(0 to FUSION_MID_TIER_THRESHOLD)
- particles_to_fire = random_particles * FUSION_PARTICLE_FACTOR_LOW
- if(FUSION_MID_TIER_THRESHOLD to FUSION_HIGH_TIER_THRESHOLD)
- particles_to_fire = random_particles * FUSION_PARTICLE_FACTOR_MID
- if(FUSION_HIGH_TIER_THRESHOLD to FUSION_SUPER_TIER_THRESHOLD)
- particles_to_fire = random_particles * FUSION_PARTICLE_FACTOR_HIGH
- if(FUSION_SUPER_TIER_THRESHOLD to INFINITY)
- particles_to_fire = random_particles * FUSION_PARTICLE_FACTOR_SUPER
- while(particles_to_fire)
- particles_fired++
- var/angle = rand(0,360)
- var/obj/item/projectile/energy/nuclear_particle/P = new /obj/item/projectile/energy/nuclear_particle(src)
- addtimer(CALLBACK(P, /obj/item/projectile.proc/fire, angle), particles_fired) //multiply particles fired * delay so the particles end up stagnated (once every decisecond)
- particles_to_fire--
\ No newline at end of file
+/atom/proc/fire_nuclear_particle(angle = rand(0,360)) //used by fusion to fire random nuclear particles. Fires one particle in a random direction.
+ var/obj/item/projectile/energy/nuclear_particle/P = new /obj/item/projectile/energy/nuclear_particle(src)
+ P.fire(angle)
diff --git a/code/modules/projectiles/projectile/energy/stun.dm b/code/modules/projectiles/projectile/energy/stun.dm
index 895a165f49..d7c8b8b082 100644
--- a/code/modules/projectiles/projectile/energy/stun.dm
+++ b/code/modules/projectiles/projectile/energy/stun.dm
@@ -3,7 +3,9 @@
icon_state = "spark"
color = "#FFFF00"
nodamage = 1
- knockdown = 100
+ knockdown = 60
+ knockdown_stamoverride = 36
+ knockdown_stam_max = 50
stutter = 5
jitter = 20
hitsound = 'sound/weapons/taserhit.ogg'
@@ -11,6 +13,7 @@
tracer_type = /obj/effect/projectile/tracer/stun
muzzle_type = /obj/effect/projectile/muzzle/stun
impact_type = /obj/effect/projectile/impact/stun
+ var/tase_duration = 50
/obj/item/projectile/energy/electrode/on_hit(atom/target, blocked = FALSE)
. = ..()
@@ -23,6 +26,7 @@
if(C.dna && C.dna.check_mutation(HULK))
C.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk")
else if((C.status_flags & CANKNOCKDOWN) && !HAS_TRAIT(C, TRAIT_STUNIMMUNE))
+ C.apply_status_effect(STATUS_EFFECT_TASED, tase_duration)
addtimer(CALLBACK(C, /mob/living/carbon.proc/do_jitter_animation, jitter), 5)
/obj/item/projectile/energy/electrode/on_range() //to ensure the bolt sparks when it reaches the end of its range if it didn't hit a target yet
diff --git a/code/modules/projectiles/projectile/special/neurotoxin.dm b/code/modules/projectiles/projectile/special/neurotoxin.dm
index baf1495abb..1d359585c0 100644
--- a/code/modules/projectiles/projectile/special/neurotoxin.dm
+++ b/code/modules/projectiles/projectile/special/neurotoxin.dm
@@ -8,7 +8,7 @@
if(isalien(target))
knockdown = 0
nodamage = TRUE
- else if(isliving(target))
+ else if(iscarbon(target))
var/mob/living/L = target
L.Knockdown(100, TRUE, FALSE, 30, 25)
return ..()
diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
index 9a228b28e3..b5bfa06786 100644
--- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm
@@ -157,8 +157,8 @@
if(beaker)
beaker.ex_act(severity, target)
-/obj/machinery/chem_dispenser/handle_atom_del(atom/A)
- ..()
+/obj/machinery/chem_dispenser/Exited(atom/movable/A, atom/newloc)
+ . = ..()
if(A == beaker)
beaker = null
cut_overlays()
@@ -252,7 +252,7 @@
if(!is_operational())
return
var/amount = text2num(params["amount"])
- if(beaker && amount in beaker.possible_transfer_amounts)
+ if(beaker && (amount in beaker.possible_transfer_amounts))
beaker.reagents.remove_all(amount)
work_animation()
. = TRUE
diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm
index 96aa0901e0..f540ae850d 100644
--- a/code/modules/reagents/chemistry/machinery/chem_master.dm
+++ b/code/modules/reagents/chemistry/machinery/chem_master.dm
@@ -175,7 +175,7 @@
data["chosenPillStyle"] = chosenPillStyle
data["isPillBottleLoaded"] = bottle ? 1 : 0
if(bottle)
- GET_COMPONENT_FROM(STRB, /datum/component/storage, bottle)
+ var/datum/component/storage/STRB = bottle.GetComponent(/datum/component/storage)
data["pillBotContent"] = bottle.contents.len
data["pillBotMaxContent"] = STRB.max_items
@@ -263,7 +263,7 @@
var/target_loc = bottle ? bottle : drop_location()
var/drop_threshold = INFINITY
if(bottle)
- GET_COMPONENT_FROM(STRB, /datum/component/storage, bottle)
+ var/datum/component/storage/STRB = bottle.GetComponent(/datum/component/storage)
if(STRB)
drop_threshold = STRB.max_items - bottle.contents.len
@@ -384,6 +384,38 @@
adjust_item_drop_location(P)
reagents.trans_to(P, vol_part)
. = TRUE
+
+ if("createDart")
+ for(var/datum/reagent/R in reagents.reagent_list)
+ if(!(istype(R, /datum/reagent/medicine)))
+ visible_message("The [src] beeps, \"SmartDarts are insoluble with non-medicinal compounds.\"")
+ return
+
+ var/many = params["many"]
+ if(reagents.total_volume == 0)
+ return
+ var/amount = 1
+ var/vol_each = min(reagents.total_volume, 20)
+ if(text2num(many))
+ amount = CLAMP(round(input(usr, "Max 10. Buffer content will be split evenly.", "How many darts?", amount) as num|null), 0, 10)
+ if(!amount)
+ return
+ vol_each = min(reagents.total_volume / amount, 20)
+
+ var/name = stripped_input(usr,"Name:","Name your SmartDart!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)
+ if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
+ return
+
+ var/obj/item/reagent_containers/syringe/dart/D
+ for(var/i = 0; i < amount; i++)
+ D = new /obj/item/reagent_containers/syringe/dart(drop_location())
+ D.name = trim("[name] SmartDart")
+ adjust_item_drop_location(D)
+ reagents.trans_to(D, vol_each)
+ D.mode=!mode
+ D.update_icon()
+ . = TRUE
+
//END CITADEL ADDITIONS
if("analyzeBeak")
var/datum/reagent/R = GLOB.chemical_reagents_list[params["id"]]
diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm
index 6efa4276b6..05fa4d382a 100644
--- a/code/modules/reagents/chemistry/machinery/pandemic.dm
+++ b/code/modules/reagents/chemistry/machinery/pandemic.dm
@@ -188,7 +188,7 @@
to_chat(usr, "ERROR: Cannot replicate virus strain.")
return
A = A.Copy()
- var/list/data = list("viruses" = list(A))
+ var/list/data = list("blood_DNA" = "UNKNOWN DNA", "blood_type" = "SY", "viruses" = list(A))
var/obj/item/reagent_containers/glass/bottle/B = new(drop_location())
B.name = "[A.name] culture bottle"
B.desc = "A small bottle. Contains [A.agent] culture in synthblood medium."
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index dd51ce2bc7..1afbed3533 100644
--- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
@@ -407,10 +407,10 @@
/datum/reagent/consumable/nuka_cola/on_mob_metabolize(mob/living/L)
..()
- ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.add_movespeed_modifier(id, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
/datum/reagent/consumable/nuka_cola/on_mob_end_metabolize(mob/living/L)
- REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.remove_movespeed_modifier(id)
..()
/datum/reagent/consumable/nuka_cola/on_mob_life(mob/living/carbon/M)
diff --git a/code/modules/reagents/chemistry/reagents/drug_reagents.dm b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
index f3df72cd4d..15d517a0f5 100644
--- a/code/modules/reagents/chemistry/reagents/drug_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drug_reagents.dm
@@ -423,7 +423,7 @@
. = 1
/datum/reagent/drug/happiness/addiction_act_stage1(mob/living/M)// all work and no play makes jack a dull boy
- GET_COMPONENT_FROM(mood, /datum/component/mood, M)
+ var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
mood.setSanity(min(mood.sanity, SANITY_DISTURBED))
M.Jitter(5)
if(prob(20))
@@ -431,7 +431,7 @@
..()
/datum/reagent/drug/happiness/addiction_act_stage2(mob/living/M)
- GET_COMPONENT_FROM(mood, /datum/component/mood, M)
+ var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
mood.setSanity(min(mood.sanity, SANITY_UNSTABLE))
M.Jitter(10)
if(prob(30))
@@ -439,7 +439,7 @@
..()
/datum/reagent/drug/happiness/addiction_act_stage3(mob/living/M)
- GET_COMPONENT_FROM(mood, /datum/component/mood, M)
+ var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
mood.setSanity(min(mood.sanity, SANITY_CRAZY))
M.Jitter(15)
if(prob(40))
@@ -447,7 +447,7 @@
..()
/datum/reagent/drug/happiness/addiction_act_stage4(mob/living/carbon/human/M)
- GET_COMPONENT_FROM(mood, /datum/component/mood, M)
+ var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
mood.setSanity(SANITY_INSANE)
M.Jitter(20)
if(prob(50))
@@ -469,7 +469,7 @@
/datum/reagent/drug/skooma/on_mob_metabolize(mob/living/L)
. = ..()
- ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.add_movespeed_modifier(id, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
L.next_move_modifier *= 2
if(ishuman(L))
var/mob/living/carbon/human/H = L
@@ -480,7 +480,7 @@
/datum/reagent/drug/skooma/on_mob_end_metabolize(mob/living/L)
. = ..()
- REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.remove_movespeed_modifier(id)
L.next_move_modifier *= 0.5
if(ishuman(L))
var/mob/living/carbon/human/H = L
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index 951a77b0e8..592f7bc592 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -236,10 +236,12 @@
/datum/reagent/medicine/silver_sulfadiazine
name = "Silver Sulfadiazine"
id = "silver_sulfadiazine"
- description = "If used in touch-based applications, immediately restores burn wounds as well as restoring more over time. If ingested through other means, deals minor toxin damage."
+ description = "If used in touch-based applications, immediately restores burn wounds as well as restoring more over time. It is mildly poisonous taken orally or by injection. If overdosed, deals brute and minor liver damage."
reagent_state = LIQUID
pH = 7.2
color = "#ffeac9"
+ metabolization_rate = 5 * REAGENTS_METABOLISM
+ overdose_threshold = 50
/datum/reagent/medicine/silver_sulfadiazine/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
if(iscarbon(M) && M.stat != DEAD)
@@ -260,6 +262,15 @@
..()
. = 1
+/datum/reagent/medicine/silver_sulfadiazine/overdose_start(mob/living/M)
+ metabolization_rate = 15 * REAGENTS_METABOLISM
+ M.adjustBruteLoss(2*REM, 0)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ C.applyLiverDamage(1)
+ ..()
+ . = 1
+
/datum/reagent/medicine/oxandrolone
name = "Oxandrolone"
id = "oxandrolone"
@@ -271,7 +282,7 @@
pH = 10.7
/datum/reagent/medicine/oxandrolone/on_mob_life(mob/living/carbon/M)
- if(M.getFireLoss() > 50)
+ if(M.getFireLoss() > 25)
M.adjustFireLoss(-4*REM, 0) //Twice as effective as silver sulfadiazine for severe burns
else
M.adjustFireLoss(-0.5*REM, 0) //But only a quarter as effective for more minor ones
@@ -287,10 +298,12 @@
/datum/reagent/medicine/styptic_powder
name = "Styptic Powder"
id = "styptic_powder"
- description = "If used in touch-based applications, immediately restores bruising as well as restoring more over time. If ingested through other means, deals minor toxin damage."
+ description = "If used in touch-based applications, immediately restores bruising as well as restoring more over time. It is poisonous if taken orally or by injection. If overdosed, deals brute and minor liver damage."
reagent_state = LIQUID
color = "#FF9696"
pH = 6.7
+ metabolization_rate = 5 * REAGENTS_METABOLISM
+ overdose_threshold = 50
/datum/reagent/medicine/styptic_powder/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
if(iscarbon(M) && M.stat != DEAD)
@@ -312,6 +325,15 @@
..()
. = 1
+datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
+ metabolization_rate = 15 * REAGENTS_METABOLISM
+ M.adjustBruteLoss(2*REM, 0)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ C.applyLiverDamage(1)
+ ..()
+ . = 1
+
/datum/reagent/medicine/salglu_solution
name = "Saline-Glucose Solution"
id = "salglu_solution"
@@ -398,23 +420,35 @@
/datum/reagent/medicine/synthflesh
name = "Synthflesh"
id = "synthflesh"
- description = "Has a 100% chance of instantly healing brute and burn damage. One unit of the chemical will heal one point of damage. Touch application only."
+ description = "Has a 100% chance of healing large amounts of brute and burn damage very quickly. One unit of the chemical will heal one point of damage. Touch application only."
reagent_state = LIQUID
color = "#FFEBEB"
pH = 11.5
+ metabolization_rate = 5 * REAGENTS_METABOLISM
+ overdose_threshold = 40
/datum/reagent/medicine/synthflesh/reaction_mob(mob/living/M, method=TOUCH, reac_volume,show_message = 1)
if(iscarbon(M))
if (M.stat == DEAD)
show_message = 0
- if(method in list(PATCH, TOUCH))
- M.adjustBruteLoss(-1.25 * reac_volume)
- M.adjustFireLoss(-1.25 * reac_volume)
+ if(method in list(INGEST, VAPOR))
+ var/mob/living/carbon/C = M
+ C.losebreath++
+ C.emote("cough")
+ to_chat(M, "You feel your throat closing up!")
+ else if(method == INJECT)
+ return
+ else if(method in list(PATCH, TOUCH))
+ M.adjustBruteLoss(-1 * reac_volume)
+ M.adjustFireLoss(-1 * reac_volume)
if(show_message)
to_chat(M, "You feel your burns and bruises healing! It stings like hell!")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "painful_medicine", /datum/mood_event/painful_medicine)
..()
+/datum/reagent/medicine/synthflesh/overdose_start(mob/living/M)
+ metabolization_rate = 15 * REAGENTS_METABOLISM
+
/datum/reagent/medicine/charcoal
name = "Charcoal"
id = "charcoal"
@@ -545,7 +579,7 @@
/datum/reagent/medicine/sal_acid/on_mob_life(mob/living/carbon/M)
- if(M.getBruteLoss() > 50)
+ if(M.getBruteLoss() > 25)
M.adjustBruteLoss(-4*REM, 0) //Twice as effective as styptic powder for severe bruising
else
M.adjustBruteLoss(-0.5*REM, 0) //But only a quarter as effective for more minor ones
@@ -950,10 +984,10 @@
/datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/L)
..()
- ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.add_movespeed_modifier(id, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
/datum/reagent/medicine/stimulants/on_mob_end_metabolize(mob/living/L)
- REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.remove_movespeed_modifier(id)
..()
/datum/reagent/medicine/stimulants/on_mob_life(mob/living/carbon/M)
@@ -1274,10 +1308,10 @@
/datum/reagent/medicine/changelinghaste/on_mob_metabolize(mob/living/L)
..()
- ADD_TRAIT(L, TRAIT_GOTTAGOREALLYFAST, id)
+ L.add_movespeed_modifier(id, update=TRUE, priority=100, multiplicative_slowdown=-2, blacklisted_movetypes=(FLYING|FLOATING))
/datum/reagent/medicine/changelinghaste/on_mob_end_metabolize(mob/living/L)
- REMOVE_TRAIT(L, TRAIT_GOTTAGOREALLYFAST, id)
+ L.remove_movespeed_modifier(id)
..()
/datum/reagent/medicine/changelinghaste/on_mob_life(mob/living/carbon/M)
@@ -1297,10 +1331,12 @@
/datum/reagent/medicine/corazone/on_mob_metabolize(mob/living/M)
..()
- ADD_TRAIT(M, TRAIT_STABLEHEART, id)
+ ADD_TRAIT(M, TRAIT_STABLEHEART, type)
+ ADD_TRAIT(M, TRAIT_STABLELIVER, type)
/datum/reagent/medicine/corazone/on_mob_end_metabolize(mob/living/M)
- REMOVE_TRAIT(M, TRAIT_STABLEHEART, id)
+ REMOVE_TRAIT(M, TRAIT_STABLEHEART, type)
+ REMOVE_TRAIT(M, TRAIT_STABLELIVER, type)
..()
/datum/reagent/medicine/muscle_stimulant
@@ -1407,7 +1443,7 @@
M.dizziness = max(0, M.dizziness-6)
M.confused = max(0, M.confused-6)
M.disgust = max(0, M.disgust-6)
- GET_COMPONENT_FROM(mood, /datum/component/mood, M)
+ var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
if(mood.sanity <= SANITY_NEUTRAL) // only take effect if in negative sanity and then...
mood.setSanity(min(mood.sanity+5, SANITY_NEUTRAL)) // set minimum to prevent unwanted spiking over neutral
..()
diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm
index 95b4a33c0d..af6a65ebe1 100644
--- a/code/modules/reagents/chemistry/reagents/other_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm
@@ -1,9 +1,9 @@
/datum/reagent/blood
- data = list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "blood_type"= null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
name = "Blood"
id = "blood"
- color = "#C80000" // rgb: 200, 0, 0
- description = "Blood from a human, or otherwise."
+ color = BLOOD_COLOR_HUMAN // rgb: 200, 0, 0
+ description = "Blood from some creature."
metabolization_rate = 5 //fast rate so it disappears fast.
taste_description = "iron"
taste_mult = 1.3
@@ -28,27 +28,75 @@
if(iscarbon(L))
var/mob/living/carbon/C = L
- if(C.get_blood_id() == "blood" && (method == INJECT || (method == INGEST && C.dna && C.dna.species && (DRINKSBLOOD in C.dna.species.species_traits))))
- if(!data || !(data["blood_type"] in get_safe_blood(C.dna.blood_type)))
- C.reagents.add_reagent("toxin", reac_volume * 0.5)
- else
- C.blood_volume = min(C.blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM)
+ var/blood_id = C.get_blood_id()
+ if((blood_id == "blood" || blood_id == "jellyblood") && (method == INJECT || (method == INGEST && C.dna && C.dna.species && (DRINKSBLOOD in C.dna.species.species_traits))))
+ C.blood_volume = min(C.blood_volume + round(reac_volume, 0.1), BLOOD_VOLUME_MAXIMUM * C.blood_ratio)
+ // we don't care about bloodtype here, we're just refilling the mob
- if(reac_volume >= 10 && istype(L))
+ if(reac_volume >= 10 && istype(L) && method != INJECT)
L.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
+/datum/reagent/blood/on_mob_life(mob/living/carbon/C) //Because lethals are preferred over stamina. damnifino.
+ var/blood_id = C.get_blood_id()
+ if((blood_id == "blood" || blood_id == "jellyblood"))
+ if(!data || !(data["blood_type"] in get_safe_blood(C.dna.blood_type))) //we only care about bloodtype here because this is where the poisoning should be
+ C.adjustToxLoss(rand(2,8)*REM, TRUE, TRUE) //forced to ensure people don't use it to gain beneficial toxin as slime person
+ ..()
+
/datum/reagent/blood/reaction_obj(obj/O, volume)
if(volume >= 3 && istype(O))
- O.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
+ O.add_blood_DNA(data)
+
+/datum/reagent/blood/reaction_turf(turf/T, reac_volume)//splash the blood all over the place
+ if(!istype(T))
+ return
+ if(reac_volume < 3)
+ return
+
+ var/obj/effect/decal/cleanable/blood/B = locate() in T //find some blood here
+ if(!B)
+ B = new(T)
+ if(data["blood_DNA"])
+ B.blood_DNA[data["blood_DNA"]] = data["blood_type"]
+ if(!B.reagents)
+ B.reagents.add_reagent(id, reac_volume)
+ B.update_icon()
/datum/reagent/blood/on_new(list/data)
if(istype(data))
SetViruses(src, data)
+ color = bloodtype_to_color(data["blood_type"])
+ if(data["blood_type"] == "SY")
+ name = "Synthetic Blood"
+ taste_description = "oily"
+
+ if(data["blood_type"] == "X*")
+ name = "Xenomorph Blood"
+ taste_description = "acidic heresy"
+ shot_glass_icon_state = "shotglassgreen"
+ pH = 2.5
+
+ if(data["blood_type"] == "HF")
+ name = "Hydraulic Blood"
+ taste_description = "burnt oil"
+ pH = 9.75
+
+ if(data["blood_type"] == "BUG")
+ name = "Insect Blood"
+ taste_description = "greasy"
+ pH = 7.25
+
+ if(data["blood_type"] == "L")
+ name = "Lizard Blood"
+ taste_description = "spicy"
+ pH = 6.85
+
+
/datum/reagent/blood/on_merge(list/mix_data)
if(data && mix_data)
if(data["blood_DNA"] != mix_data["blood_DNA"])
- data["cloneable"] = 0 //On mix, consider the genetic sampling unviable for pod cloning if the DNA sample doesn't match.
+ data["cloneable"] = FALSE //On mix, consider the genetic sampling unviable for pod cloning if the DNA sample doesn't match.
if(data["viruses"] || mix_data["viruses"])
var/list/mix1 = data["viruses"]
@@ -78,27 +126,111 @@
var/datum/disease/D = thing
. += D
-/datum/reagent/blood/reaction_turf(turf/T, reac_volume)//splash the blood all over the place
- if(!istype(T))
- return
- if(reac_volume < 3)
- return
+/datum/reagent/blood/synthetics
+ data = list("donor"=null,"viruses"=null,"blood_DNA"="REPLICATED", "bloodcolor" = BLOOD_COLOR_SYNTHETIC, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ name = "Synthetic Blood"
+ id = "syntheticblood"
+ taste_description = "oily"
+ color = BLOOD_COLOR_SYNTHETIC // rgb: 11, 7, 48
- var/obj/effect/decal/cleanable/blood/B = locate() in T //find some blood here
- if(!B)
- B = new(T)
- if(data["blood_DNA"])
- B.add_blood_DNA(list(data["blood_DNA"] = data["blood_type"]))
+/datum/reagent/blood/lizard
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_LIZARD, "blood_type"="L","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ name = "Lizard Blood"
+ id = "lizardblood"
+ taste_description = "spicy"
+ color = BLOOD_COLOR_LIZARD // rgb: 11, 7, 48
+ pH = 6.85
+
+/datum/reagent/blood/jellyblood
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SLIME, "blood_type"="GEL","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ name = "Slime Jelly Blood"
+ id = "jellyblood"
+ description = "A gooey semi-liquid produced from one of the deadliest lifeforms in existence. SO REAL."
+ color = BLOOD_COLOR_SLIME
+ taste_description = "slime"
+ taste_mult = 1.3
+ pH = 4
+
+/datum/reagent/blood/xenomorph
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_XENO, "blood_type"="X*","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ name = "Xenomorph Blood"
+ id = "xenoblood"
+ taste_description = "acidic heresy"
+ color = BLOOD_COLOR_XENO // greenish yellow ooze
+ shot_glass_icon_state = "shotglassgreen"
+ pH = 2.5
+
+/datum/reagent/blood/oil
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_OIL, "blood_type"="HF","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ name = "Hydraulic Blood"
+ id = "oilblood"
+ taste_description = "burnt oil"
+ color = BLOOD_COLOR_OIL // dark, y'know, expected batman colors.
+ pH = 9.75
+
+/datum/reagent/blood/insect
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_BUG, "blood_type"="BUG","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ name = "Insectoid Blood"
+ id = "bugblood"
+ taste_description = "waxy"
+ color = BLOOD_COLOR_BUG // Bug colored, I guess.
+ pH = 7.25
+
+
+/datum/reagent/blood/jellyblood/on_mob_life(mob/living/carbon/M)
+ if(prob(10))
+ if(M.dna?.species?.exotic_bloodtype != "GEL")
+ to_chat(M, "Your insides are burning!")
+ M.adjustToxLoss(rand(20,60)*REM, 0)
+ . = 1
+ else if(prob(40) && isjellyperson(M))
+ M.heal_bodypart_damage(2*REM)
+ . = 1
+ ..()
/datum/reagent/liquidgibs
name = "Liquid gibs"
id = "liquidgibs"
- color = "#FF9966"
+ color = BLOOD_COLOR_HUMAN
description = "You don't even want to think about what's in here."
taste_description = "gross iron"
shot_glass_icon_state = "shotglassred"
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "blood_type"= "O+","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
pH = 7.45
+/datum/reagent/liquidgibs/xeno
+ name = "Liquid xeno gibs"
+ id = "liquidxenogibs"
+ color = BLOOD_COLOR_XENO
+ taste_description = "blended heresy"
+ shot_glass_icon_state = "shotglassgreen"
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_XENO, "blood_type"="X*","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ pH = 2.5
+
+/datum/reagent/liquidgibs/slime
+ name = "Slime sludge"
+ id = "liquidslimegibs"
+ color = BLOOD_COLOR_SLIME
+ taste_description = "slime"
+ shot_glass_icon_state = "shotglassgreen"
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SLIME, "blood_type"="GEL","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ pH = 4
+
+/datum/reagent/liquidgibs/synth
+ name = "Synthetic sludge"
+ id = "liquidsyntheticgibs"
+ color = BLOOD_COLOR_SYNTHETIC
+ taste_description = "jellied plastic"
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SYNTHETIC, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+
+/datum/reagent/liquidgibs/oil
+ name = "Hydraulic sludge"
+ id = "liquidoilgibs"
+ color = BLOOD_COLOR_OIL
+ taste_description = "chunky burnt oil"
+ data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_OIL, "blood_type"="HF","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
+ pH = 9.75
+
/datum/reagent/vaccine
//data must contain virus type
name = "Vaccine"
@@ -585,6 +717,30 @@
race = /datum/species/android
mutationtext = "The pain subsides. You feel... artificial."
+//Citadel Races
+/datum/reagent/mutationtoxin/mammal
+ name = "Mammal Mutation Toxin"
+ id = "mammalmutationtoxin"
+ description = "A glowing toxin."
+ color = "#5EFF3B" //RGB: 94, 255, 59
+ race = /datum/species/mammal
+ mutationtext = "The pain subsides. You feel... fluffier."
+
+/datum/reagent/mutationtoxin/insect
+ name = "Insect Mutation Toxin"
+ id = "insectmutationtoxin"
+ description = "A glowing toxin."
+ color = "#5EFF3B" //RGB: 94, 255, 59
+ race = /datum/species/insect
+ mutationtext = "The pain subsides. You feel... attracted to dark, moist areas."
+
+/datum/reagent/mutationtoxin/xenoperson
+ name = "Xeno-Hybrid Mutation Toxin"
+ id = "xenopersonmutationtoxin"
+ description = "A glowing toxin."
+ color = "#5EFF3B" //RGB: 94, 255, 59
+ race = /datum/species/xeno
+ mutationtext = "The pain subsides. You feel... oddly longing for the Queen." //sadly, not the British one.
//BLACKLISTED RACES
/datum/reagent/mutationtoxin/skeleton
@@ -947,12 +1103,12 @@
reagent_state = SOLID
taste_description = "iron"
pH = 6
-
+ overdose_threshold = 30
color = "#c2391d"
/datum/reagent/iron/on_mob_life(mob/living/carbon/C)
if(C.blood_volume < (BLOOD_VOLUME_NORMAL*C.blood_ratio))
- C.blood_volume += 0.5
+ C.blood_volume += 0.01 //we'll have synthetics from medbay.
..()
/datum/reagent/iron/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
@@ -961,6 +1117,17 @@
M.reagents.add_reagent("toxin", reac_volume)
..()
+/datum/reagent/iron/overdose_start(mob/living/M)
+ to_chat(M, "You start feeling your guts twisting painfully!")
+ SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[id]_overdose", /datum/mood_event/overdose, name)
+
+/datum/reagent/iron/overdose_process(mob/living/carbon/C)
+ if(prob(20))
+ var/obj/item/organ/liver/L = C.getorganslot(ORGAN_SLOT_LIVER)
+ if (istype(L))
+ C.applyLiverDamage(2) //mild until the fabled med rework comes out. the organ damage galore
+ ..()
+
/datum/reagent/gold
name = "Gold"
id = "gold"
@@ -1077,17 +1244,19 @@
pH = 5.5
/datum/reagent/space_cleaner/reaction_obj(obj/O, reac_volume)
- if(istype(O, /obj/effect/decal/cleanable))
+ if(istype(O, /obj/effect/decal/cleanable) || istype(O, /obj/item/projectile/bullet/reusable/foam_dart) || istype(O, /obj/item/ammo_casing/caseless/foam_dart))
qdel(O)
else
if(O)
O.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(O, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ O.clean_blood()
/datum/reagent/space_cleaner/reaction_turf(turf/T, reac_volume)
if(reac_volume >= 1)
T.remove_atom_colour(WASHABLE_COLOUR_PRIORITY)
- SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(T, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ T.clean_blood()
for(var/obj/effect/decal/cleanable/C in T)
qdel(C)
@@ -1105,26 +1274,33 @@
H.lip_style = null
H.update_body()
for(var/obj/item/I in C.held_items)
- SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(I, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ I.clean_blood()
if(C.wear_mask)
- if(SEND_SIGNAL(C.wear_mask, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ SEND_SIGNAL(C.wear_mask, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ if(C.wear_mask.clean_blood())
C.update_inv_wear_mask()
if(ishuman(M))
var/mob/living/carbon/human/H = C
if(H.head)
- if(SEND_SIGNAL(H.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ SEND_SIGNAL(H.head, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ if(H.head.clean_blood())
H.update_inv_head()
if(H.wear_suit)
- if(SEND_SIGNAL(H.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ SEND_SIGNAL(H.wear_suit, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ if(H.wear_suit.clean_blood())
H.update_inv_wear_suit()
else if(H.w_uniform)
- if(SEND_SIGNAL(H.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ SEND_SIGNAL(H.w_uniform, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ if(H.w_uniform.clean_blood())
H.update_inv_w_uniform()
if(H.shoes)
- if(SEND_SIGNAL(H.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD))
+ SEND_SIGNAL(H.shoes, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ if(H.shoes.clean_blood())
H.update_inv_shoes()
H.wash_cream()
- SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_STRENGTH_BLOOD)
+ SEND_SIGNAL(M, COMSIG_COMPONENT_CLEAN_ACT, CLEAN_WEAK)
+ M.clean_blood()
/datum/reagent/space_cleaner/ez_clean
name = "EZ Clean"
@@ -1353,10 +1529,10 @@
/datum/reagent/nitryl/on_mob_metabolize(mob/living/L)
..()
- ADD_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.add_movespeed_modifier(id, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
/datum/reagent/nitryl/on_mob_end_metabolize(mob/living/L)
- REMOVE_TRAIT(L, TRAIT_GOTTAGOFAST, id)
+ L.remove_movespeed_modifier(id)
..()
/////////////////////////Coloured Crayon Powder////////////////////////////
@@ -2089,24 +2265,6 @@
M.emote("nya")
..()
-//Kept for legacy, I think it will break everything if you enable it.
-/datum/reagent/penis_enlargement
- name = "Penis Enlargement"
- id = "penis_enlargement"
- description = "A patented chemical forumula by Doctor Ronald Hyatt that is guaranteed to bring maximum GROWTH and LENGTH to your penis, today!"
- color = "#888888"
- taste_description = "chinese dragon powder"
- metabolization_rate = INFINITY //So it instantly removes all of itself. Don't want to put strain on the system.
-
-/datum/reagent/penis_enlargement/on_mob_life(mob/living/carbon/C)
- var/obj/item/organ/genital/penis/P = C.getorganslot(ORGAN_SLOT_PENIS)
- if(P)
- var/added_length = round(volume/30,0.01) //Every 30u gives an extra inch. Rounded to the nearest 0.01 so float fuckery doesn't occur with the division by 30.
- if(added_length >= 0.20) //Only add the length if it's greater than or equal to 0.2. This is to prevent people from smoking the reagents and causing the penis to update constantly.
- P.length += added_length
- P.update()
- ..()
-
/datum/reagent/changeling_string
name = "UNKNOWN"
id = "changeling_sting_real"
@@ -2119,26 +2277,22 @@
chemical_flags = REAGENT_INVISIBLE
/datum/reagent/changeling_string/on_mob_metabolize(mob/living/carbon/C)
- if(C && C.dna && data["desired_dna"])
+ if(ishuman(C) && C.dna && data["desired_dna"])
original_dna = new C.dna.type
C.dna.copy_dna(original_dna)
var/datum/dna/new_dna = data["desired_dna"]
- new_dna.copy_dna(C.dna)
+ new_dna.transfer_identity(C, TRUE)
C.real_name = new_dna.real_name
- C.updateappearance(mutcolor_update=1)
- C.update_body()
+ C.updateappearance(mutcolor_update = TRUE)
C.domutcheck()
- C.regenerate_icons()
..()
/datum/reagent/changeling_string/on_mob_end_metabolize(mob/living/carbon/C)
if(original_dna)
- original_dna.copy_dna(C.dna)
+ original_dna.transfer_identity(C, TRUE)
C.real_name = original_dna.real_name
- C.updateappearance(mutcolor_update=1)
- C.update_body()
+ C.updateappearance(mutcolor_update = TRUE)
C.domutcheck()
- C.regenerate_icons()
..()
/datum/reagent/changeling_string/Destroy()
diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm
index 2ed9a31107..374f7715bb 100644
--- a/code/modules/reagents/chemistry/recipes/medicine.dm
+++ b/code/modules/reagents/chemistry/recipes/medicine.dm
@@ -283,6 +283,12 @@
results = list("regen_jelly" = 2)
required_reagents = list("tricordrazine" = 1, "slimejelly" = 1)
+/datum/chemical_reaction/jelly_convert
+ name = "Blood Jelly Conversion"
+ id = "blood_jelly"
+ results = list("slimejelly" = 1)
+ required_reagents = list("toxin" = 1, "jellyblood" = 1)
+
/datum/chemical_reaction/corazone
name = "Corazone"
id = "corazone"
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index b3f9591f64..d475b118b2 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -26,7 +26,7 @@
create_reagents(volume, reagent_flags)
if(spawned_disease)
var/datum/disease/F = new spawned_disease()
- var/list/data = list("viruses"= list(F))
+ var/list/data = list("blood_DNA" = "UNKNOWN DNA", "blood_type" = "SY","viruses"= list(F))
reagents.add_reagent("blood", disease_amount, data)
add_initial_reagents()
diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm
index 3e555f385f..fe35981bfe 100644
--- a/code/modules/reagents/reagent_containers/blood_pack.dm
+++ b/code/modules/reagents/reagent_containers/blood_pack.dm
@@ -4,13 +4,16 @@
icon = 'icons/obj/bloodpack.dmi'
icon_state = "bloodpack"
volume = 200
+ reagent_flags = DRAINABLE
var/blood_type = null
var/labelled = 0
+ var/color_to_apply = "#FFFFFF"
+ var/mutable_appearance/fill_overlay
/obj/item/reagent_containers/blood/Initialize()
. = ..()
if(blood_type != null)
- reagents.add_reagent("blood", 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=blood_type,"resistances"=null,"trace_chem"=null))
+ reagents.add_reagent("blood", 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_colour"=color, "blood_type"=blood_type,"resistances"=null,"trace_chem"=null))
update_icon()
/obj/item/reagent_containers/blood/on_reagent_change(changetype)
@@ -18,6 +21,7 @@
var/datum/reagent/blood/B = reagents.has_reagent("blood")
if(B && B.data && B.data["blood_type"])
blood_type = B.data["blood_type"]
+ color_to_apply = bloodtype_to_color(blood_type)
else
blood_type = null
update_pack_name()
@@ -45,7 +49,7 @@
/obj/item/reagent_containers/blood/random/Initialize()
icon_state = "bloodpack"
- blood_type = pick("A+", "A-", "B+", "B-", "O+", "O-", "L")
+ blood_type = pick("A+", "A-", "B+", "B-", "O+", "O-", "L", "SY", "HF", "GEL", "BUG")
return ..()
/obj/item/reagent_containers/blood/APlus
@@ -72,6 +76,18 @@
/obj/item/reagent_containers/blood/universal
blood_type = "U"
+/obj/item/reagent_containers/blood/synthetics
+ blood_type = "SY"
+
+/obj/item/reagent_containers/blood/oilblood
+ blood_type = "HF"
+
+/obj/item/reagent_containers/blood/jellyblood
+ blood_type = "GEL"
+
+/obj/item/reagent_containers/blood/insect
+ blood_type = "BUG"
+
/obj/item/reagent_containers/blood/attackby(obj/item/I, mob/user, params)
if (istype(I, /obj/item/pen) || istype(I, /obj/item/toy/crayon))
if(!user.is_literate())
diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm
index 257106aaa7..3ed505c360 100644
--- a/code/modules/reagents/reagent_containers/glass.dm
+++ b/code/modules/reagents/reagent_containers/glass.dm
@@ -89,7 +89,7 @@
reagents.clear_reagents()
/obj/item/reagent_containers/glass/attackby(obj/item/I, mob/user, params)
- var/hotness = I.is_hot()
+ var/hotness = I.get_temperature()
if(hotness && reagents)
reagents.expose_temperature(hotness)
to_chat(user, "You heat [name] with [I]!")
diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm
index a96ba006c9..432b9289dd 100644
--- a/code/modules/reagents/reagent_containers/hypospray.dm
+++ b/code/modules/reagents/reagent_containers/hypospray.dm
@@ -196,3 +196,318 @@
volume = 250
list_reagents = list("holywater" = 150, "tiresolution" = 50, "dizzysolution" = 50)
amount_per_transfer_from_this = 50
+
+#define HYPO_SPRAY 0
+#define HYPO_INJECT 1
+
+#define WAIT_SPRAY 25
+#define WAIT_INJECT 25
+#define SELF_SPRAY 15
+#define SELF_INJECT 15
+
+#define DELUXE_WAIT_SPRAY 20
+#define DELUXE_WAIT_INJECT 20
+#define DELUXE_SELF_SPRAY 10
+#define DELUXE_SELF_INJECT 10
+
+#define COMBAT_WAIT_SPRAY 0
+#define COMBAT_WAIT_INJECT 0
+#define COMBAT_SELF_SPRAY 0
+#define COMBAT_SELF_INJECT 0
+
+//A vial-loaded hypospray. Cartridge-based!
+/obj/item/hypospray/mkii
+ name = "hypospray mk.II"
+ icon_state = "hypo2"
+ icon = 'icons/obj/syringe.dmi'
+ desc = "A new development from DeForest Medical, this hypospray takes 30-unit vials as the drug supply for easy swapping."
+ w_class = WEIGHT_CLASS_TINY
+ var/list/allowed_containers = list(/obj/item/reagent_containers/glass/bottle/vial/tiny, /obj/item/reagent_containers/glass/bottle/vial/small)
+ var/mode = HYPO_INJECT
+ var/obj/item/reagent_containers/glass/bottle/vial/vial
+ var/start_vial = /obj/item/reagent_containers/glass/bottle/vial/small
+ var/spawnwithvial = TRUE
+ var/inject_wait = WAIT_INJECT
+ var/spray_wait = WAIT_SPRAY
+ var/spray_self = SELF_SPRAY
+ var/inject_self = SELF_INJECT
+ var/quickload = FALSE
+ var/penetrates = FALSE
+
+/obj/item/hypospray/mkii/brute
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/bicaridine
+
+/obj/item/hypospray/mkii/toxin
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/antitoxin
+
+/obj/item/hypospray/mkii/oxygen
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/dexalin
+
+/obj/item/hypospray/mkii/burn
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/kelotane
+
+/obj/item/hypospray/mkii/tricord
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/tricord
+
+/obj/item/hypospray/mkii/enlarge
+ spawnwithvial = FALSE
+
+/obj/item/hypospray/mkii/CMO
+ name = "hypospray mk.II deluxe"
+ allowed_containers = list(/obj/item/reagent_containers/glass/bottle/vial/tiny, /obj/item/reagent_containers/glass/bottle/vial/small, /obj/item/reagent_containers/glass/bottle/vial/large)
+ icon_state = "cmo2"
+ desc = "The Deluxe Hypospray can take larger-size vials. It also acts faster and delivers more reagents per spray."
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/CMO
+ inject_wait = DELUXE_WAIT_INJECT
+ spray_wait = DELUXE_WAIT_SPRAY
+ spray_self = DELUXE_SELF_SPRAY
+ inject_self = DELUXE_SELF_INJECT
+
+/obj/item/hypospray/mkii/CMO/combat
+ name = "combat hypospray mk.II"
+ desc = "A combat-ready deluxe hypospray that acts almost instantly. It can be tactically reloaded by using a vial on it."
+ icon_state = "combat2"
+ start_vial = /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/combat
+ inject_wait = COMBAT_WAIT_INJECT
+ spray_wait = COMBAT_WAIT_SPRAY
+ spray_self = COMBAT_SELF_SPRAY
+ inject_self = COMBAT_SELF_INJECT
+ quickload = TRUE
+ penetrates = TRUE
+
+/obj/item/hypospray/mkii/Initialize()
+ . = ..()
+ if(!spawnwithvial)
+ update_icon()
+ return
+ if(start_vial)
+ vial = new start_vial
+ update_icon()
+
+/obj/item/hypospray/mkii/update_icon()
+ ..()
+ icon_state = "[initial(icon_state)][vial ? "" : "-e"]"
+ if(ismob(loc))
+ var/mob/M = loc
+ M.update_inv_hands()
+ return
+
+/obj/item/hypospray/mkii/examine(mob/user)
+ . = ..()
+ if(vial)
+ to_chat(user, "[vial] has [vial.reagents.total_volume]u remaining.")
+ else
+ to_chat(user, "It has no vial loaded in.")
+ to_chat(user, "[src] is set to [mode ? "Inject" : "Spray"] contents on application.")
+
+/obj/item/hypospray/mkii/proc/unload_hypo(obj/item/I, mob/user)
+ if((istype(I, /obj/item/reagent_containers/glass/bottle/vial)))
+ var/obj/item/reagent_containers/glass/bottle/vial/V = I
+ V.forceMove(user.loc)
+ user.put_in_hands(V)
+ to_chat(user, "You remove [vial] from [src].")
+ vial = null
+ update_icon()
+ playsound(loc, 'sound/weapons/empty.ogg', 50, 1)
+ else
+ to_chat(user, "This hypo isn't loaded!")
+ return
+
+/obj/item/hypospray/mkii/attackby(obj/item/I, mob/living/user)
+ if((istype(I, /obj/item/reagent_containers/glass/bottle/vial) && vial != null))
+ if(!quickload)
+ to_chat(user, "[src] can not hold more than one vial!")
+ return FALSE
+ unload_hypo(vial, user)
+ if((istype(I, /obj/item/reagent_containers/glass/bottle/vial)))
+ var/obj/item/reagent_containers/glass/bottle/vial/V = I
+ if(!is_type_in_list(V, allowed_containers))
+ to_chat(user, "[src] doesn't accept this type of vial.")
+ return FALSE
+ if(!user.transferItemToLoc(V,src))
+ return FALSE
+ vial = V
+ user.visible_message("[user] has loaded a vial into [src].","You have loaded [vial] into [src].")
+ update_icon()
+ playsound(loc, 'sound/weapons/autoguninsert.ogg', 35, 1)
+ return TRUE
+ else
+ to_chat(user, "This doesn't fit in [src].")
+ return FALSE
+ return FALSE
+
+/obj/item/hypospray/mkii/AltClick(mob/user)
+ if(vial)
+ vial.attack_self(user)
+
+// Gunna allow this for now, still really don't approve - Pooj
+/obj/item/hypospray/mkii/emag_act(mob/user)
+ . = ..()
+ if(obj_flags & EMAGGED)
+ to_chat(user, "[src] happens to be already overcharged.")
+ return
+ inject_wait = COMBAT_WAIT_INJECT
+ spray_wait = COMBAT_WAIT_SPRAY
+ spray_self = COMBAT_SELF_INJECT
+ inject_self = COMBAT_SELF_SPRAY
+ penetrates = TRUE
+ to_chat(user, "You overcharge [src]'s control circuit.")
+ obj_flags |= EMAGGED
+ return TRUE
+
+/obj/item/hypospray/mkii/attack_hand(mob/user)
+ . = ..() //Don't bother changing this or removing it from containers will break.
+
+/obj/item/hypospray/mkii/attack(obj/item/I, mob/user, params)
+ return
+
+/obj/item/hypospray/mkii/afterattack(atom/target, mob/user, proximity)
+ if(!vial)
+ return
+
+ if(!proximity)
+ return
+
+ if(!ismob(target))
+ return
+
+ var/mob/living/L
+ if(isliving(target))
+ L = target
+ if(!penetrates && !L.can_inject(user, 1)) //This check appears another four times, since otherwise the penetrating sprays will break in do_mob.
+ return
+
+ if(!L && !target.is_injectable()) //only checks on non-living mobs, due to how can_inject() handles
+ to_chat(user, "You cannot directly fill [target]!")
+ return
+
+ if(target.reagents.total_volume >= target.reagents.maximum_volume)
+ to_chat(user, "[target] is full.")
+ return
+
+ if(ishuman(L))
+ var/obj/item/bodypart/affecting = L.get_bodypart(check_zone(user.zone_selected))
+ if(!affecting)
+ to_chat(user, "The limb is missing!")
+ return
+ if(affecting.status != BODYPART_ORGANIC)
+ to_chat(user, "Medicine won't work on a robotic limb!")
+ return
+
+ var/contained = vial.reagents.log_list()
+ log_combat(user, L, "attemped to inject", src, addition="which had [contained]")
+//Always log attemped injections for admins
+ if(vial != null)
+ switch(mode)
+ if(HYPO_INJECT)
+ if(L) //living mob
+ if(L != user)
+ L.visible_message("[user] is trying to inject [L] with [src]!", \
+ "[user] is trying to inject [L] with [src]!")
+ if(!do_mob(user, L, inject_wait))
+ return
+ if(!penetrates && !L.can_inject(user, 1))
+ return
+ if(!vial.reagents.total_volume)
+ return
+ if(L.reagents.total_volume >= L.reagents.maximum_volume)
+ return
+ L.visible_message("[user] uses the [src] on [L]!", \
+ "[user] uses the [src] on [L]!")
+ else
+ if(!do_mob(user, L, inject_self))
+ return
+ if(!penetrates && !L.can_inject(user, 1))
+ return
+ if(!vial.reagents.total_volume)
+ return
+ if(L.reagents.total_volume >= L.reagents.maximum_volume)
+ return
+ log_attack("[user.name] ([user.ckey]) applied [src] to [L.name] ([L.ckey]), which had [contained] (INTENT: [uppertext(user.a_intent)]) (MODE: [src.mode])")
+ L.log_message("applied [src] to themselves ([contained]).", INDIVIDUAL_ATTACK_LOG)
+
+ var/fraction = min(vial.amount_per_transfer_from_this/vial.reagents.total_volume, 1)
+ vial.reagents.reaction(L, INJECT, fraction)
+ vial.reagents.trans_to(target, vial.amount_per_transfer_from_this)
+ if(vial.amount_per_transfer_from_this >= 15)
+ playsound(loc,'sound/items/hypospray_long.ogg',50, 1, -1)
+ if(vial.amount_per_transfer_from_this < 15)
+ playsound(loc, pick('sound/items/hypospray.ogg','sound/items/hypospray2.ogg'), 50, 1, -1)
+ to_chat(user, "You inject [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.")
+
+ if(HYPO_SPRAY)
+ if(L) //living mob
+ if(L != user)
+ L.visible_message("[user] is trying to spray [L] with [src]!", \
+ "[user] is trying to spray [L] with [src]!")
+ if(!do_mob(user, L, spray_wait))
+ return
+ if(!penetrates && !L.can_inject(user, 1))
+ return
+ if(!vial.reagents.total_volume)
+ return
+ if(L.reagents.total_volume >= L.reagents.maximum_volume)
+ return
+ L.visible_message("[user] uses the [src] on [L]!", \
+ "[user] uses the [src] on [L]!")
+ else
+ if(!do_mob(user, L, spray_self))
+ return
+ if(!penetrates && !L.can_inject(user, 1))
+ return
+ if(!vial.reagents.total_volume)
+ return
+ if(L.reagents.total_volume >= L.reagents.maximum_volume)
+ return
+ log_attack("[user.name] ([user.ckey]) applied [src] to [L.name] ([L.ckey]), which had [contained] (INTENT: [uppertext(user.a_intent)]) (MODE: [src.mode])")
+ L.log_message("applied [src] to themselves ([contained]).", INDIVIDUAL_ATTACK_LOG)
+ var/fraction = min(vial.amount_per_transfer_from_this/vial.reagents.total_volume, 1)
+ vial.reagents.reaction(L, PATCH, fraction)
+ vial.reagents.trans_to(target, vial.amount_per_transfer_from_this)
+ if(vial.amount_per_transfer_from_this >= 15)
+ playsound(loc,'sound/items/hypospray_long.ogg',50, 1, -1)
+ if(vial.amount_per_transfer_from_this < 15)
+ playsound(loc, pick('sound/items/hypospray.ogg','sound/items/hypospray2.ogg'), 50, 1, -1)
+ to_chat(user, "You spray [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.")
+ else
+ to_chat(user, "[src] doesn't work here!")
+ return
+
+/obj/item/hypospray/mkii/attack_self(mob/living/user)
+ if(user)
+ if(user.incapacitated())
+ return
+ else if(!vial)
+ to_chat(user, "This Hypo needs to be loaded first!")
+ return
+ else
+ unload_hypo(vial,user)
+
+/obj/item/hypospray/mkii/verb/modes()
+ set name = "Toggle Application Mode"
+ set category = "Object"
+ set src in usr
+ var/mob/M = usr
+ switch(mode)
+ if(HYPO_SPRAY)
+ mode = HYPO_INJECT
+ to_chat(M, "[src] is now set to inject contents on application.")
+ if(HYPO_INJECT)
+ mode = HYPO_SPRAY
+ to_chat(M, "[src] is now set to spray contents on application.")
+
+#undef HYPO_SPRAY
+#undef HYPO_INJECT
+#undef WAIT_SPRAY
+#undef WAIT_INJECT
+#undef SELF_SPRAY
+#undef SELF_INJECT
+#undef DELUXE_WAIT_SPRAY
+#undef DELUXE_WAIT_INJECT
+#undef DELUXE_SELF_SPRAY
+#undef DELUXE_SELF_INJECT
+#undef COMBAT_WAIT_SPRAY
+#undef COMBAT_WAIT_INJECT
+#undef COMBAT_SELF_SPRAY
+#undef COMBAT_SELF_INJECT
diff --git a/modular_citadel/code/modules/reagents/reagent container/hypovial.dm b/code/modules/reagents/reagent_containers/hypovial.dm
old mode 100755
new mode 100644
similarity index 96%
rename from modular_citadel/code/modules/reagents/reagent container/hypovial.dm
rename to code/modules/reagents/reagent_containers/hypovial.dm
index c1e0d6ff01..ba5ce48a4a
--- a/modular_citadel/code/modules/reagents/reagent container/hypovial.dm
+++ b/code/modules/reagents/reagent_containers/hypovial.dm
@@ -1,7 +1,8 @@
+//hypovials used with the MkII hypospray. See hypospray.dm.
+
/obj/item/reagent_containers/glass/bottle/vial
name = "broken hypovial"
desc = "A hypovial compatible with most hyposprays."
- icon = 'modular_citadel/icons/obj/vial.dmi'
icon_state = "hypovial"
spillable = FALSE
var/comes_with = list() //Easy way of doing this.
@@ -34,7 +35,7 @@
/obj/item/reagent_containers/glass/bottle/vial/update_icon()
cut_overlays()
if(reagents.total_volume)
- var/mutable_appearance/filling = mutable_appearance('modular_citadel/icons/obj/vial.dmi', "hypovial10")
+ var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "hypovial10")
var/percent = round((reagents.total_volume / volume) * 100)
switch(percent)
@@ -86,7 +87,7 @@
/obj/item/reagent_containers/glass/bottle/vial/large/update_icon()
cut_overlays()
if(reagents.total_volume)
- var/mutable_appearance/filling = mutable_appearance('modular_citadel/icons/obj/vial.dmi', "hypoviallarge10")
+ var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "hypoviallarge10")
var/percent = round((reagents.total_volume / volume) * 100)
switch(percent)
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index 38880f669f..d4880aa085 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -186,7 +186,6 @@
/obj/item/reagent_containers/pill/antirad_plus
name = "prussian blue pill"
desc = "Used to treat heavy radition poisoning."
- icon = 'modular_citadel/icons/obj/modularpills.dmi'
icon_state = "prussian_blue"
list_reagents = list("prussian_blue" = 25, "water" = 10)
roundstart = 1
@@ -194,7 +193,6 @@
/obj/item/reagent_containers/pill/mutarad
name = "radiation treatment deluxe pill"
desc = "Used to treat heavy radition poisoning and genetic defects."
- icon = 'modular_citadel/icons/obj/modularpills.dmi'
icon_state = "anit_rad_fixgene"
list_reagents = list("prussian_blue" = 15, "potass_iodide" = 15, "mutadone" = 15, "water" = 5)
roundstart = 1
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index d2e3f95bdc..424d7b9ed0 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -125,7 +125,7 @@
to_chat(user, "You switch the nozzle setting to [stream_mode ? "\"stream\"":"\"spray\""]. You'll now use [amount_per_transfer_from_this] units per use.")
/obj/item/reagent_containers/spray/attackby(obj/item/I, mob/user, params)
- var/hotness = I.is_hot()
+ var/hotness = I.get_temperature()
if(hotness && reagents)
reagents.expose_temperature(hotness)
to_chat(user, "You heat [name] with [I]!")
diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm
index cc83eb28f6..6bdae6225a 100644
--- a/code/modules/reagents/reagent_containers/syringes.dm
+++ b/code/modules/reagents/reagent_containers/syringes.dm
@@ -104,7 +104,7 @@
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this) // transfer from, transfer to - who cares?
to_chat(user, "You fill [src] with [trans] units of the solution. It now contains [reagents.total_volume] units.")
- if (reagents.total_volume >= reagents.maximum_volume)
+ if (round(reagents.total_volume, 0.1) >= reagents.maximum_volume)
mode=!mode
update_icon()
@@ -307,7 +307,7 @@
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
to_chat(user, "You soak the [src] with [trans] units of the solution. It now contains [reagents.total_volume] units.")
- if (reagents.total_volume >= reagents.maximum_volume)
+ if (round(reagents.total_volume,1) >= reagents.maximum_volume)
mode=!mode
update_icon()
@@ -323,8 +323,9 @@
rounded_vol = "empty"
if(reagents && reagents.total_volume)
- if(volume/reagents.total_volume == 1)
+ if(volume/round(reagents.total_volume, 1) == 1)
rounded_vol="full"
+ mode = SYRINGE_INJECT
icon_state = "[rounded_vol]"
item_state = "syringe_[rounded_vol]"
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index a4a6a7d473..5edddd64c2 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -283,7 +283,7 @@
/obj/machinery/disposal/bin/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/storage/bag/trash)) //Not doing component overrides because this is a specific type.
var/obj/item/storage/bag/trash/T = I
- GET_COMPONENT_FROM(STR, /datum/component/storage, T)
+ var/datum/component/storage/STR = T.GetComponent(/datum/component/storage)
to_chat(user, "You empty the bag.")
for(var/obj/item/O in T.contents)
STR.remove_from_storage(O,src)
diff --git a/code/modules/recycling/disposal/construction.dm b/code/modules/recycling/disposal/construction.dm
index 624d5e0e05..348e687e03 100644
--- a/code/modules/recycling/disposal/construction.dm
+++ b/code/modules/recycling/disposal/construction.dm
@@ -29,7 +29,7 @@
pipename = initial(pipe_type.name)
if(flip)
- GET_COMPONENT(rotcomp,/datum/component/simple_rotation)
+ var/datum/component/simple_rotation/rotcomp = GetComponent(/datum/component/simple_rotation)
rotcomp.BaseRot(null,ROTATION_FLIP)
update_icon()
diff --git a/code/modules/research/designs/electronics_designs.dm b/code/modules/research/designs/electronics_designs.dm
index 552976824d..818e80beea 100644
--- a/code/modules/research/designs/electronics_designs.dm
+++ b/code/modules/research/designs/electronics_designs.dm
@@ -131,3 +131,30 @@
category = list("Misc")
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
+/datum/design/xenobio_upgrade
+ name = "owo"
+ desc = "someone's bussin"
+ build_type = PROTOLATHE
+ materials = list(MAT_METAL = 300, MAT_GLASS = 100)
+ category = list("Electronics")
+ departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
+
+/datum/design/xenobio_upgrade/xenobiomonkeys
+ name = "Xenobiology console monkey upgrade disk"
+ desc = "This disk will add the ability to remotely recycle monkeys via the Xenobiology console."
+ id = "xenobio_monkeys"
+ build_path = /obj/item/disk/xenobio_console_upgrade/monkey
+
+/datum/design/xenobio_upgrade/xenobioslimebasic
+ name = "Xenobiology console basic slime upgrade disk"
+ desc = "This disk will add the ability to remotely manipulate slimes via the Xenobiology console."
+ id = "xenobio_slimebasic"
+ build_path = /obj/item/disk/xenobio_console_upgrade/slimebasic
+
+/datum/design/xenobio_upgrade/xenobioslimeadv
+ name = "Xenobiology console advanced slime upgrade disk"
+ desc = "This disk will add the ability to remotely feed slimes potions via the Xenobiology console, and lift the restrictions on the number of slimes that can be stored inside the Xenobiology console. This includes the contents of the basic slime upgrade disk."
+ id = "xenobio_slimeadv"
+ build_path = /obj/item/disk/xenobio_console_upgrade/slimeadv
+
+
diff --git a/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm b/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm
index 31723cde07..b4d67315ba 100644
--- a/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm
+++ b/code/modules/research/designs/machine_desings/machine_designs_all_misc.dm
@@ -98,3 +98,11 @@
build_path = /obj/item/circuitboard/machine/vr_sleeper
departmental_flags = DEPARTMENTAL_FLAG_ALL
category = list ("Medical Machinery")
+
+/datum/design/board/autoylathe
+ name = "Machine Design (Autoylathe)"
+ desc = "The circuit board for an autoylathe."
+ id = "autoylathe"
+ build_path = /obj/item/circuitboard/machine/autoylathe
+ departmental_flags = DEPARTMENTAL_FLAG_ALL
+ category = list("Misc. Machinery")
diff --git a/code/modules/research/designs/machine_desings/machine_designs_medical.dm b/code/modules/research/designs/machine_desings/machine_designs_medical.dm
index 65b3d74f71..2f95954e01 100644
--- a/code/modules/research/designs/machine_desings/machine_designs_medical.dm
+++ b/code/modules/research/designs/machine_desings/machine_designs_medical.dm
@@ -89,3 +89,11 @@
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_ENGINEERING
build_path = /obj/item/circuitboard/machine/clonescanner
category = list("Medical Machinery")
+
+/datum/design/board/bloodbankgen
+ name = "Machine Design (Blood Bank Generator Board)"
+ desc = "The circuit board for a blood bank generator."
+ id = "bloodbankgen"
+ build_path = /obj/item/circuitboard/machine/bloodbankgen
+ departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
+ category = list ("Medical Machinery")
diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm
index ae01b75dd9..e70362553c 100644
--- a/code/modules/research/designs/medical_designs.dm
+++ b/code/modules/research/designs/medical_designs.dm
@@ -729,12 +729,22 @@
var/surgery
/datum/design/surgery/experimental_dissection
- name = "Experimental Dissection"
- desc = "A surgical procedure which deeply analyzes the biology of a corpse, and automatically adds new findings to the research database."
- id = "surgery_exp_dissection"
- surgery = /datum/surgery/advanced/bioware/experimental_dissection
+ name = "Advanced Dissection"
+ desc = "A surgical procedure which analyzes the biology of a corpse, and automatically adds new findings to the research database."
+ id = "surgery_adv_dissection"
+ surgery = /datum/surgery/advanced/experimental_dissection/adv
research_icon_state = "surgery_chest"
+/datum/design/surgery/experimental_dissection/exp
+ name = "Experimental Dissection"
+ id = "surgery_exp_dissection"
+ surgery = /datum/surgery/advanced/experimental_dissection/exp
+
+/datum/design/surgery/experimental_dissection/ext
+ name = "Extraterrestrial Dissection"
+ id = "surgery_ext_dissection"
+ surgery = /datum/surgery/advanced/experimental_dissection/alien
+
/datum/design/surgery/lobotomy
name = "Lobotomy"
desc = "An invasive surgical procedure which guarantees removal of almost all brain traumas, but might cause another permanent trauma in return."
@@ -756,13 +766,49 @@
surgery = /datum/surgery/advanced/viral_bonding
research_icon_state = "surgery_chest"
-/datum/design/surgery/reconstruction
- name = "Reconstruction"
- desc = "A surgical procedure that gradually repairs damage done to a body without the assistance of chemicals. Unlike classic medicine, it is effective on corpses."
- id = "surgery_reconstruction"
- surgery = /datum/surgery/advanced/reconstruction
+/datum/design/surgery/healing
+ name = "Tend Wounds"
+ desc = "An upgraded version of the original surgery."
+ id = "surgery_healing_base" //holder because travis cries otherwise. Not used in techweb unlocks.
research_icon_state = "surgery_chest"
+/datum/design/surgery/healing/brute_upgrade
+ name = "Tend Wounds (Brute) Upgrade"
+ surgery = /datum/surgery/healing/brute/upgraded
+ id = "surgery_heal_brute_upgrade"
+
+/datum/design/surgery/healing/brute_upgrade_2
+ name = "Tend Wounds (Brute) Upgrade"
+ surgery = /datum/surgery/healing/brute/upgraded/femto
+ id = "surgery_heal_brute_upgrade_femto"
+
+/datum/design/surgery/healing/burn_upgrade
+ name = "Tend Wounds (Burn) Upgrade"
+ surgery = /datum/surgery/healing/burn/upgraded
+ id = "surgery_heal_burn_upgrade"
+
+/datum/design/surgery/healing/burn_upgrade_2
+ name = "Tend Wounds (Burn) Upgrade"
+ surgery = /datum/surgery/healing/brute/upgraded/femto
+ id = "surgery_heal_burn_upgrade_femto"
+
+/datum/design/surgery/healing/combo
+ name = "Tend Wounds (Mixture)"
+ desc = "A surgical procedure that repairs both bruises and burns. Repair efficiency is not as high as the individual surgeries but it is faster."
+ surgery = /datum/surgery/healing/combo
+ id = "surgery_heal_combo"
+
+/datum/design/surgery/healing/combo_upgrade
+ name = "Tend Wounds (Mixture) Upgrade"
+ surgery = /datum/surgery/healing/combo/upgraded
+ id = "surgery_heal_combo_upgrade"
+
+/datum/design/surgery/healing/combo_upgrade_2
+ name = "Tend Wounds (Mixture) Upgrade"
+ desc = "A surgical procedure that repairs both bruises and burns faster than their individual counterparts. It is more effective than both the individual surgeries."
+ surgery = /datum/surgery/healing/combo/upgraded/femto
+ id = "surgery_heal_combo_upgrade_femto"
+
/datum/design/surgery/surgery_toxinhealing
name = "Body Rejuvenation"
desc = "A surgical procedure that helps deal with oxygen deprecation, and treat toxic damaged. Works on corpses and alive alike without chemicals."
@@ -805,6 +851,13 @@
surgery = /datum/surgery/advanced/bioware/vein_threading
research_icon_state = "surgery_chest"
+/datum/design/surgery/muscled_veins
+ name = "Vein Muscle Membrane"
+ desc = "A surgical procedure which adds a muscled membrane to blood vessels, allowing them to pump blood without a heart."
+ id = "surgery_muscled_veins"
+ surgery = /datum/surgery/advanced/bioware/muscled_veins
+ research_icon_state = "surgery_chest"
+
/datum/design/surgery/ligament_hook
name = "Ligament Hook"
desc = "A surgical procedure which reshapes the connections between torso and limbs, making it so limbs can be attached manually if severed. \
diff --git a/code/modules/research/designs/stock_parts_designs.dm b/code/modules/research/designs/stock_parts_designs.dm
index ea67fad434..6526599179 100644
--- a/code/modules/research/designs/stock_parts_designs.dm
+++ b/code/modules/research/designs/stock_parts_designs.dm
@@ -288,7 +288,7 @@
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/subspace_analyzer
- name = "Subspace Analyzer"
+ name = "Subspace Wavelength Analyzer"
desc = "A sophisticated analyzer capable of analyzing cryptic subspace wavelengths."
id = "s-analyzer"
build_type = PROTOLATHE
diff --git a/code/modules/research/designs/weapon_designs.dm b/code/modules/research/designs/weapon_designs.dm
index 11bc31bedc..d69dda37ca 100644
--- a/code/modules/research/designs/weapon_designs.dm
+++ b/code/modules/research/designs/weapon_designs.dm
@@ -67,6 +67,12 @@
//Ammo Shells/
//////////////
+/datum/design/beanbag_slug/sec
+ id = "sec_beanbag"
+ build_type = PROTOLATHE
+ category = list("Ammo")
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY
+
/datum/design/rubbershot/sec
id = "sec_rshot"
build_type = PROTOLATHE
@@ -105,7 +111,7 @@
materials = list(MAT_METAL = 200)
build_path = /obj/item/ammo_casing/shotgun/stunslug
category = list("Ammo")
- departmental_flags = DEPARTMENTAL_FLAG_SECURITY
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/techshell
name = "Unloaded Technological Shotshell"
@@ -139,7 +145,7 @@
materials = list(MAT_METAL = 500, MAT_GLASS = 300)
build_path = /obj/item/firing_pin/test_range
category = list("Firing Pins")
- departmental_flags = DEPARTMENTAL_FLAG_SECURITY
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/pin_mindshield
name = "Mindshield Firing Pin"
@@ -235,7 +241,7 @@
reagents_list = list("radium" = 20)
build_path = /obj/item/gun/energy/floragun
category = list("Weapons")
- departmental_flags = DEPARTMENTAL_FLAG_SERVICE
+ departmental_flags = DEPARTMENTAL_FLAG_SERVICE | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/xray
name = "X-ray Laser Gun"
@@ -309,7 +315,7 @@
materials = list(MAT_METAL = 2000, MAT_PLASMA = 500)
build_path = /obj/item/grenade/chem_grenade/pyro
category = list("Weapons")
- departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_MEDICAL
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/cryo_grenade
name = "Cryo Grenade"
@@ -319,7 +325,7 @@
materials = list(MAT_METAL = 2000, MAT_SILVER = 500)
build_path = /obj/item/grenade/chem_grenade/cryo
category = list("Weapons")
- departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_MEDICAL
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
/datum/design/adv_grenade
name = "Advanced Release Grenade"
@@ -329,7 +335,7 @@
materials = list(MAT_METAL = 3000, MAT_GLASS = 500)
build_path = /obj/item/grenade/chem_grenade/adv_release
category = list("Weapons")
- departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_MEDICAL
+ departmental_flags = DEPARTMENTAL_FLAG_SECURITY | DEPARTMENTAL_FLAG_MEDICAL | DEPARTMENTAL_FLAG_SCIENCE
//////////
//MISC////
diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm
index e56350a280..0bcd0c5984 100644
--- a/code/modules/research/experimentor.dm
+++ b/code/modules/research/experimentor.dm
@@ -422,7 +422,7 @@
if(exp == SCANTYPE_OBLITERATE)
visible_message("[exp_on] activates the crushing mechanism, [exp_on] is destroyed!")
if(linked_console.linked_lathe)
- GET_COMPONENT_FROM(linked_materials, /datum/component/material_container, linked_console.linked_lathe)
+ var/datum/component/material_container/linked_materials = linked_console.linked_lathe.GetComponent(/datum/component/material_container)
for(var/material in exp_on.materials)
linked_materials.insert_amount( min((linked_materials.max_amount - linked_materials.total_amount), (exp_on.materials[material])), material)
if(prob(EFFECT_PROB_LOW) && criticalReaction)
diff --git a/code/modules/research/research_disk.dm b/code/modules/research/research_disk.dm
index 2ec2398d88..02865dc5bb 100644
--- a/code/modules/research/research_disk.dm
+++ b/code/modules/research/research_disk.dm
@@ -29,3 +29,12 @@
/obj/item/disk/tech_disk/illegal/Initialize()
. = ..()
stored_research = new /datum/techweb/syndicate
+
+/obj/item/disk/tech_disk/abductor
+ name = "Gray technology disk"
+ desc = "You feel like it's not Gray because of its color."
+ materials = list()
+
+/obj/item/disk/tech_disk/abductor/Initialize()
+ . = ..()
+ stored_research = new /datum/techweb/abductor
diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm
index 3cd296f866..12fe64463d 100644
--- a/code/modules/research/stock_parts.dm
+++ b/code/modules/research/stock_parts.dm
@@ -43,7 +43,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
/obj/item/storage/part_replacer/bluespace
name = "bluespace rapid part exchange device"
- desc = "A version of the RPED that allows for replacement of parts and scanning from a distance, along with higher capacity for parts."
+ desc = "A version of the RPED that allows for replacement of parts and scanning from a distance, along with higher capacity for parts. Definitely not just a BSRPED painted orange."
icon_state = "BS_RPED"
w_class = WEIGHT_CLASS_NORMAL
works_from_distance = TRUE
@@ -52,12 +52,10 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
component_type = /datum/component/storage/concrete/bluespace/rped
/obj/item/storage/part_replacer/cyborg
- name = "rapid part exchange device"
- desc = "Special mechanical module made to store, sort, and apply standard machine parts."
icon_state = "borgrped"
- item_state = "RPED"
- lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
- righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
+
+/obj/item/storage/part_replacer/bluespace/cyborg
+ icon_state = "borg_BS_RPED"
/proc/cmp_rped_sort(obj/item/A, obj/item/B)
return B.get_part_rating() - A.get_part_rating()
diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm
index cd5a190fd6..1e554f112f 100644
--- a/code/modules/research/techweb/_techweb.dm
+++ b/code/modules/research/techweb/_techweb.dm
@@ -49,6 +49,14 @@
var/datum/techweb_node/syndicate_basic/Node = new()
research_node(Node, TRUE)
+/datum/techweb/abductor
+ id = "ABDUCTOR"
+ organization = "Aliens"
+
+/datum/techweb/abductor/New()
+ var/datum/techweb_node/alientech/Node = new()
+ research_node(Node, TRUE)
+
/datum/techweb/science //Global science techweb for RND consoles.
id = "SCIENCE"
organization = "Nanotrasen"
@@ -364,3 +372,7 @@
/datum/techweb/specialized/autounlocking/exofab
allowed_buildtypes = MECHFAB
+
+/datum/techweb/specialized/autounlocking/autoylathe
+ design_autounlock_buildtypes = AUTOYLATHE
+ allowed_buildtypes = AUTOYLATHE
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index 477bfbe1a1..fdf887d259 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -10,7 +10,7 @@
// Default research tech, prevents bricking
design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani",
"destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab",
- "space_heater", "xlarge_beaker", "sec_rshot", "sec_bshot", "sec_slug", "sec_Islug", "sec_dart", "sec_38", "sec_38lethal",
+ "space_heater", "xlarge_beaker", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_Islug", "sec_dart", "sec_38", "sec_38lethal",
"rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass")
/datum/techweb_node/mmi
@@ -60,7 +60,7 @@
display_name = "Biological Technology"
description = "What makes us tick." //the MC, silly!
prereq_ids = list("base")
- design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag")
+ design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -110,12 +110,21 @@
export_price = 5000
/////////////////////////Advanced Surgery/////////////////////////
+/datum/techweb_node/imp_wt_surgery
+ id = "imp_wt_surgery"
+ display_name = "Improved Wound-Tending Surgery"
+ description = "Who would have known being more gentle with a hemostat decreases patient pain?"
+ prereq_ids = list("biotech")
+ design_ids = list("surgery_heal_brute_upgrade","surgery_heal_burn_upgrade")
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000)
+ export_price = 1000
+
/datum/techweb_node/adv_surgery
id = "adv_surgery"
display_name = "Advanced Surgery"
description = "When simple medicine doesn't cut it."
- prereq_ids = list("adv_biotech")
- design_ids = list("surgery_lobotomy", "surgery_reconstruction", "surgery_toxinhealing", "organbox", "surgery_exp_dissection")
+ prereq_ids = list("imp_wt_surgery")
+ design_ids = list("surgery_revival", "surgery_lobotomy", "surgery_heal_brute_upgrade_femto","surgery_heal_burn_upgrade_femto", "surgery_heal_combo", "surgery_toxinhealing", "organbox", "surgery_adv_dissection")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -124,7 +133,7 @@
display_name = "Experimental Surgery"
description = "When evolution isn't fast enough."
prereq_ids = list("adv_surgery")
- design_ids = list("surgery_revival","surgery_pacify","surgery_vein_thread","surgery_nerve_splice","surgery_nerve_ground","surgery_ligament_hook","surgery_ligament_reinforcement","surgery_viral_bond")
+ design_ids = list("surgery_pacify","surgery_vein_thread","surgery_muscled_veins","surgery_nerve_splice","surgery_nerve_ground","surgery_ligament_hook","surgery_ligament_reinforcement","surgery_viral_bond", "surgery_exp_dissection", "surgery_heal_combo_upgrade")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
export_price = 5000
@@ -133,7 +142,7 @@
display_name = "Alien Surgery"
description = "Abductors did nothing wrong."
prereq_ids = list("exp_surgery", "alientech")
- design_ids = list("surgery_brainwashing","surgery_zombie")
+ design_ids = list("surgery_brainwashing","surgery_zombie", "surgery_ext_dissection", "surgery_heal_combo_upgrade_femto")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 10000)
export_price = 5000
@@ -1018,26 +1027,19 @@
id = "alien_bio"
display_name = "Alien Biological Tools"
description = "Advanced biological tools."
- prereq_ids = list("alientech", "adv_biotech")
+ prereq_ids = list("alientech", "advance_surgerytools")
design_ids = list("alien_scalpel", "alien_hemostat", "alien_retractor", "alien_saw", "alien_drill", "alien_cautery")
- boost_item_paths = list(/obj/item/gun/energy/alien, /obj/item/scalpel/alien, /obj/item/hemostat/alien, /obj/item/retractor/alien, /obj/item/circular_saw/alien,
- /obj/item/cautery/alien, /obj/item/surgicaldrill/alien, /obj/item/screwdriver/abductor, /obj/item/wrench/abductor, /obj/item/crowbar/abductor, /obj/item/multitool/abductor, /obj/item/stock_parts/cell/infinite/abductor,
- /obj/item/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor_baton, /obj/item/abductor)
- research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
- export_price = 20000
- hidden = TRUE
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
+ export_price = 10000
/datum/techweb_node/alien_engi
id = "alien_engi"
display_name = "Alien Engineering"
description = "Alien engineering tools"
- prereq_ids = list("alientech", "adv_engi")
+ prereq_ids = list("alientech", "exp_tools")
design_ids = list("alien_wrench", "alien_wirecutters", "alien_screwdriver", "alien_crowbar", "alien_welder", "alien_multitool")
- boost_item_paths = list(/obj/item/screwdriver/abductor, /obj/item/wrench/abductor, /obj/item/crowbar/abductor, /obj/item/multitool/abductor, /obj/item/stock_parts/cell/infinite/abductor,
- /obj/item/weldingtool/abductor, /obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor, /obj/item/abductor_baton, /obj/item/abductor)
- research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
- export_price = 20000
- hidden = TRUE
+ research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
+ export_price = 10000
/datum/techweb_node/syndicate_basic
id = "syndicate_basic"
@@ -1097,4 +1099,4 @@
for(var/i in processing)
var/datum/techweb_node/TN = i
TW.add_point_list(TN.research_costs)
- return TW.printout_points()
\ No newline at end of file
+ return TW.printout_points()
diff --git a/code/modules/research/xenobiology/crossbreeding/_misc.dm b/code/modules/research/xenobiology/crossbreeding/_misc.dm
index b28f1676a1..0099fe143d 100644
--- a/code/modules/research/xenobiology/crossbreeding/_misc.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_misc.dm
@@ -58,9 +58,7 @@
var/mob/living/carbon/human/H = M
if(H.mind && !HAS_TRAIT(H, TRAIT_AGEUSIA))
to_chat(H,"That didn't taste very good...") //No disgust, though. It's just not good tasting.
- GET_COMPONENT_FROM(mood, /datum/component/mood, H)
- if(mood)
- mood.add_event(null,"gross_food", /datum/mood_event/gross_food)
+ SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "gross_food", /datum/mood_event/gross_food)
last_check_time = world.time
return
..()
diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
index b9e7122d07..9c9542ed17 100644
--- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
+++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm
@@ -64,10 +64,9 @@
var/interrupted = FALSE
var/mob/target
var/icon/bluespace
- var/datum/weakref/redirect_component
/datum/status_effect/slimerecall/on_apply()
- redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/resistField))))
+ RegisterSignal(owner, COMSIG_LIVING_RESIST, .proc/resistField)
to_chat(owner, "You feel a sudden tug from an unknown force, and feel a pull to bluespace!")
to_chat(owner, "Resist if you wish avoid the force!")
bluespace = icon('icons/effects/effects.dmi',"chronofield")
@@ -77,9 +76,9 @@
/datum/status_effect/slimerecall/proc/resistField()
interrupted = TRUE
owner.remove_status_effect(src)
+
/datum/status_effect/slimerecall/on_remove()
- qdel(redirect_component.resolve())
- redirect_component = null
+ UnregisterSignal(owner, COMSIG_LIVING_RESIST)
owner.cut_overlay(bluespace)
if(interrupted || !ismob(target))
to_chat(owner, "The bluespace tug fades away, and you feel that the force has passed you by.")
@@ -98,10 +97,9 @@
duration = -1 //Will remove self when block breaks.
alert_type = /obj/screen/alert/status_effect/freon/stasis
var/obj/structure/ice_stasis/cube
- var/datum/weakref/redirect_component
/datum/status_effect/frozenstasis/on_apply()
- redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/breakCube))))
+ RegisterSignal(owner, COMSIG_LIVING_RESIST, .proc/breakCube)
cube = new /obj/structure/ice_stasis(get_turf(owner))
owner.forceMove(cube)
owner.status_flags |= GODMODE
@@ -118,8 +116,7 @@
if(cube)
qdel(cube)
owner.status_flags &= ~GODMODE
- qdel(redirect_component.resolve())
- redirect_component = null
+ UnregisterSignal(owner, COMSIG_LIVING_RESIST)
/datum/status_effect/slime_clone
id = "slime_cloned"
@@ -375,15 +372,11 @@ datum/status_effect/rebreathing/tick()
duration = 30
/datum/status_effect/tarfoot/on_apply()
- var/mob/living/carbon/human/H = owner
- if(istype(H))
- H.physiology.speed_mod += 0.5
+ owner.add_movespeed_modifier(MOVESPEED_ID_TARFOOT, update=TRUE, priority=100, multiplicative_slowdown=0.5, blacklisted_movetypes=(FLYING|FLOATING))
return ..()
/datum/status_effect/tarfoot/on_remove()
- var/mob/living/carbon/human/H = owner
- if(istype(H))
- H.physiology.speed_mod -= 0.5
+ owner.remove_movespeed_modifier(MOVESPEED_ID_TARFOOT)
/datum/status_effect/spookcookie
id = "spookcookie"
@@ -570,7 +563,7 @@ datum/status_effect/stabilized/blue/on_remove()
name = "burning fingertips"
desc = "You shouldn't see this."
-/obj/item/hothands/is_hot()
+/obj/item/hothands/get_temperature()
return 290 //Below what's required to ignite plasma.
/datum/status_effect/stabilized/darkpurple
@@ -695,20 +688,15 @@ datum/status_effect/stabilized/blue/on_remove()
/datum/status_effect/stabilized/sepia/tick()
if(prob(50) && mod > -1)
mod--
- var/mob/living/carbon/human/H = owner
- if(istype(H))
- H.physiology.speed_mod--
+ owner.add_movespeed_modifier(MOVESPEED_ID_SEPIA, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
else if(mod < 1)
mod++
- var/mob/living/carbon/human/H = owner
- if(istype(H))
- H.physiology.speed_mod++
+ // yeah a value of 0 does nothing but replacing the trait in place is cheaper than removing and adding repeatedly
+ owner.add_movespeed_modifier(MOVESPEED_ID_SEPIA, update=TRUE, priority=100, multiplicative_slowdown=0, blacklisted_movetypes=(FLYING|FLOATING))
return ..()
/datum/status_effect/stabilized/sepia/on_remove()
- var/mob/living/carbon/human/H = owner
- if(istype(H))
- H.physiology.speed_mod += -mod //Reset the changes.
+ owner.remove_movespeed_modifier(MOVESPEED_ID_SEPIA)
/datum/status_effect/stabilized/cerulean
id = "stabilizedcerulean"
@@ -916,7 +904,7 @@ datum/status_effect/stabilized/blue/on_remove()
colour = "light pink"
/datum/status_effect/stabilized/lightpink/on_apply()
- ADD_TRAIT(owner, TRAIT_GOTTAGOFAST,"slimestatus")
+ owner.add_movespeed_modifier(MOVESPEED_ID_SLIME_STATUS, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
return ..()
/datum/status_effect/stabilized/lightpink/tick()
@@ -927,7 +915,7 @@ datum/status_effect/stabilized/blue/on_remove()
return ..()
/datum/status_effect/stabilized/lightpink/on_remove()
- REMOVE_TRAIT(owner, TRAIT_GOTTAGOFAST,"slimestatus")
+ owner.remove_movespeed_modifier(MOVESPEED_ID_SLIME_STATUS)
/datum/status_effect/stabilized/adamantine
id = "stabilizedadamantine"
diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm
index 5aebd1bafa..641b7e7dcb 100644
--- a/code/modules/research/xenobiology/xenobio_camera.dm
+++ b/code/modules/research/xenobiology/xenobio_camera.dm
@@ -29,12 +29,11 @@
var/datum/action/innate/slime_scan/scan_action
var/datum/action/innate/feed_potion/potion_action
- var/datum/component/redirect/listener
-
var/list/stored_slimes
var/obj/item/slimepotion/slime/current_potion
- var/max_slimes = 5
+ var/max_slimes = 1
var/monkeys = 0
+ var/upgradetier = 0
icon_screen = "slime_comp"
icon_keyboard = "rd_key"
@@ -50,7 +49,7 @@
scan_action = new
potion_action = new
stored_slimes = list()
- listener = AddComponent(/datum/component/redirect, list(COMSIG_ATOM_CONTENTS_DEL = CALLBACK(src, .proc/on_contents_del)))
+ RegisterSignal(src, COMSIG_ATOM_CONTENTS_DEL, .proc/on_contents_del)
/obj/machinery/computer/camera_advanced/xenobio/Destroy()
stored_slimes = null
@@ -108,6 +107,22 @@
stored_slimes -= deleted
/obj/machinery/computer/camera_advanced/xenobio/attackby(obj/item/O, mob/user, params)
+ if(istype(O, /obj/item/disk/xenobio_console_upgrade))
+ var/obj/item/disk/xenobio_console_upgrade/diskthing = O
+ var/successfulupgrade = FALSE
+ for(var/I in diskthing.upgradetypes)
+ if(upgradetier & I)
+ continue
+ else
+ upgradetier |= I
+ successfulupgrade = TRUE
+ if(I == XENOBIO_UPGRADE_SLIMEADV)
+ max_slimes = 10
+ if(successfulupgrade)
+ to_chat(user, "You have successfully upgraded [src] with [O].")
+ else
+ to_chat(user, "[src] already has the contents of [O] installed!")
+ return
if(istype(O, /obj/item/reagent_containers/food/snacks/monkeycube) && (upgradetier & XENOBIO_UPGRADE_MONKEYS)) //CIT CHANGE - makes monkey-related actions require XENOBIO_UPGRADE_MONKEYS
monkeys++
to_chat(user, "You feed [O] to [src]. It now has [monkeys] monkey cubes stored.")
@@ -266,3 +281,29 @@
break
else
to_chat(owner, "Target is not near a camera. Cannot proceed.")
+
+/obj/item/disk/xenobio_console_upgrade
+ name = "Xenobiology console upgrade disk"
+ desc = "Allan please add detail."
+ icon_state = "datadisk5"
+ var/list/upgradetypes = list()
+
+/obj/item/disk/xenobio_console_upgrade/admin
+ name = "Xenobio all access thing"
+ desc = "'the consoles are literally useless!!!!!!!!!!!!!!!'"
+ upgradetypes = list(XENOBIO_UPGRADE_SLIMEBASIC, XENOBIO_UPGRADE_SLIMEADV, XENOBIO_UPGRADE_MONKEYS)
+
+/obj/item/disk/xenobio_console_upgrade/monkey
+ name = "Xenobiology console monkey upgrade disk"
+ desc = "This disk will add the ability to remotely recycle monkeys via the Xenobiology console."
+ upgradetypes = list(XENOBIO_UPGRADE_MONKEYS)
+
+/obj/item/disk/xenobio_console_upgrade/slimebasic
+ name = "Xenobiology console basic slime upgrade disk"
+ desc = "This disk will add the ability to remotely manipulate slimes via the Xenobiology console."
+ upgradetypes = list(XENOBIO_UPGRADE_SLIMEBASIC)
+
+/obj/item/disk/xenobio_console_upgrade/slimeadv
+ name = "Xenobiology console advanced slime upgrade disk"
+ desc = "This disk will add the ability to remotely feed slimes potions via the Xenobiology console, and lift the restrictions on the number of slimes that can be stored inside the Xenobiology console. This includes the contents of the basic slime upgrade disk."
+ upgradetypes = list(XENOBIO_UPGRADE_SLIMEBASIC, XENOBIO_UPGRADE_SLIMEADV)
diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm
new file mode 100644
index 0000000000..0d4d2b6ad6
--- /dev/null
+++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm
@@ -0,0 +1,529 @@
+GLOBAL_VAR_INIT(hhStorageTurf, null)
+GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337)
+
+/obj/item/hilbertshotel
+ name = "Hilbert's Hotel"
+ desc = "A sphere of what appears to be an intricate network of bluespace. Observing it in detail seems to give you a headache as you try to comprehend the infinite amount of infinitesimally distinct points on its surface."
+ icon_state = "hilbertshotel"
+ w_class = WEIGHT_CLASS_SMALL
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ var/datum/map_template/hilbertshotel/hotelRoomTemp
+ var/datum/map_template/hilbertshotel/empty/hotelRoomTempEmpty
+ var/datum/map_template/hilbertshotel/lore/hotelRoomTempLore
+ var/list/activeRooms = list()
+ var/list/storedRooms = list()
+ var/storageTurf
+ //Lore Stuff
+ var/ruinSpawned = FALSE
+ var/mysteryRoom
+
+/obj/item/hilbertshotel/Initialize()
+ . = ..()
+ //Load templates
+ hotelRoomTemp = new()
+ hotelRoomTempEmpty = new()
+ hotelRoomTempLore = new()
+ var/area/currentArea = get_area(src)
+ if(currentArea.type == /area/ruin/space/has_grav/hilbertresearchfacility)
+ ruinSpawned = TRUE
+
+/obj/item/hilbertshotel/Destroy()
+ ejectRooms()
+ return ..()
+
+/obj/item/hilbertshotel/attack(mob/living/M, mob/living/user)
+ if(M.mind)
+ to_chat(user, "You invite [M] to the hotel.")
+ promptAndCheckIn(M)
+ else
+ to_chat(user, "[M] is not intelligent enough to understand how to use this device!")
+
+/obj/item/hilbertshotel/attack_self(mob/user)
+ . = ..()
+ promptAndCheckIn(user)
+
+/obj/item/hilbertshotel/proc/promptAndCheckIn(mob/user)
+ var/chosenRoomNumber = input(user, "What number room will you be checking into?", "Room Number") as null|num
+ if(!chosenRoomNumber)
+ return
+ if(chosenRoomNumber > SHORT_REAL_LIMIT)
+ to_chat(user, "You have to check out the first [SHORT_REAL_LIMIT] rooms before you can go to a higher numbered one!")
+ return
+ if((chosenRoomNumber < 1) || (chosenRoomNumber != round(chosenRoomNumber)))
+ to_chat(user, "That is not a valid room number!")
+ return
+ if(ismob(loc))
+ if(user == loc) //Not always the same as user
+ forceMove(get_turf(user))
+ if(!storageTurf) //Blame subsystems for not allowing this to be in Initialize
+ if(!GLOB.hhStorageTurf)
+ var/datum/map_template/hilbertshotelstorage/storageTemp = new()
+ var/datum/turf_reservation/storageReservation = SSmapping.RequestBlockReservation(3, 3)
+ storageTemp.load(locate(storageReservation.bottom_left_coords[1], storageReservation.bottom_left_coords[2], storageReservation.bottom_left_coords[3]))
+ GLOB.hhStorageTurf = locate(storageReservation.bottom_left_coords[1]+1, storageReservation.bottom_left_coords[2]+1, storageReservation.bottom_left_coords[3])
+ else
+ storageTurf = GLOB.hhStorageTurf
+ if(tryActiveRoom(chosenRoomNumber, user))
+ return
+ if(tryStoredRoom(chosenRoomNumber, user))
+ return
+ sendToNewRoom(chosenRoomNumber, user)
+
+
+/obj/item/hilbertshotel/proc/tryActiveRoom(var/roomNumber, var/mob/user)
+ if(activeRooms["[roomNumber]"])
+ var/datum/turf_reservation/roomReservation = activeRooms["[roomNumber]"]
+ do_sparks(3, FALSE, get_turf(user))
+ user.forceMove(locate(roomReservation.bottom_left_coords[1] + hotelRoomTemp.landingZoneRelativeX, roomReservation.bottom_left_coords[2] + hotelRoomTemp.landingZoneRelativeY, roomReservation.bottom_left_coords[3]))
+ return TRUE
+ else
+ return FALSE
+
+/obj/item/hilbertshotel/proc/tryStoredRoom(var/roomNumber, var/mob/user)
+ if(storedRooms["[roomNumber]"])
+ var/datum/turf_reservation/roomReservation = SSmapping.RequestBlockReservation(hotelRoomTemp.width, hotelRoomTemp.height)
+ hotelRoomTempEmpty.load(locate(roomReservation.bottom_left_coords[1], roomReservation.bottom_left_coords[2], roomReservation.bottom_left_coords[3]))
+ var/turfNumber = 1
+ for(var/i=0, iAs the sphere breaks apart, you're suddenly ejected into the depths of space!
")
+ var/max = world.maxx-TRANSITIONEDGE
+ var/min = 1+TRANSITIONEDGE
+ var/list/possible_transtitons = list()
+ for(var/AZ in SSmapping.z_list)
+ var/datum/space_level/D = AZ
+ if (D.linkage == CROSSLINKED)
+ possible_transtitons += D.z_value
+ var/_z = pick(possible_transtitons)
+ var/_x = rand(min,max)
+ var/_y = rand(min,max)
+ var/turf/T = locate(_x, _y, _z)
+ A.forceMove(T)
+ qdel(room)
+
+ if(storedRooms.len)
+ for(var/x in storedRooms)
+ var/list/atomList = storedRooms[x]
+ for(var/atom/movable/A in atomList)
+ var/max = world.maxx-TRANSITIONEDGE
+ var/min = 1+TRANSITIONEDGE
+ var/list/possible_transtitons = list()
+ for(var/AZ in SSmapping.z_list)
+ var/datum/space_level/D = AZ
+ if (D.linkage == CROSSLINKED)
+ possible_transtitons += D.z_value
+ var/_z = pick(possible_transtitons)
+ var/_x = rand(min,max)
+ var/_y = rand(min,max)
+ var/turf/T = locate(_x, _y, _z)
+ A.forceMove(T)
+
+//Template Stuff
+/datum/map_template/hilbertshotel
+ name = "Hilbert's Hotel Room"
+ mappath = '_maps/templates/hilbertshotel.dmm'
+ var/landingZoneRelativeX = 2
+ var/landingZoneRelativeY = 8
+
+/datum/map_template/hilbertshotel/empty
+ name = "Empty Hilbert's Hotel Room"
+ mappath = '_maps/templates/hilbertshotelempty.dmm'
+
+/datum/map_template/hilbertshotel/lore
+ name = "Doctor Hilbert's Deathbed"
+ mappath = '_maps/templates/hilbertshotellore.dmm'
+
+/datum/map_template/hilbertshotelstorage
+ name = "Hilbert's Hotel Storage"
+ mappath = '_maps/templates/hilbertshotelstorage.dmm'
+
+
+//Turfs and Areas
+/turf/closed/indestructible/hotelwall
+ name = "hotel wall"
+ desc = "A wall designed to protect the security of the hotel's guests."
+ icon_state = "hotelwall"
+ canSmoothWith = list(/turf/closed/indestructible/hotelwall)
+ explosion_block = INFINITY
+
+/turf/open/indestructible/hotelwood
+ desc = "Stylish dark wood with extra reinforcement. Secured firmly to the floor to prevent tampering."
+ icon_state = "wood"
+ footstep = FOOTSTEP_WOOD
+ tiled_dirt = FALSE
+
+/turf/open/indestructible/hoteltile
+ desc = "Smooth tile with extra reinforcement. Secured firmly to the floor to prevent tampering."
+ icon_state = "showroomfloor"
+ footstep = FOOTSTEP_FLOOR
+ tiled_dirt = FALSE
+
+/turf/open/space/bluespace
+ name = "\proper bluespace hyperzone"
+ icon_state = "bluespace"
+ baseturfs = /turf/open/space/bluespace
+ flags_1 = NOJAUNT_1
+ explosion_block = INFINITY
+ var/obj/item/hilbertshotel/parentSphere
+
+/turf/open/space/bluespace/Entered(atom/movable/A)
+ . = ..()
+ A.forceMove(get_turf(parentSphere))
+
+/turf/closed/indestructible/hoteldoor
+ name = "Hotel Door"
+ icon_state = "hoteldoor"
+ explosion_block = INFINITY
+ var/obj/item/hilbertshotel/parentSphere
+
+/turf/closed/indestructible/hoteldoor/proc/promptExit(mob/living/user)
+ if(!isliving(user))
+ return
+ if(!user.mind)
+ return
+ if(!parentSphere)
+ to_chat(user, "The door seems to be malfunctioning and refuses to operate!")
+ return
+ if(alert(user, "Hilbert's Hotel would like to remind you that while we will do everything we can to protect the belongings you leave behind, we make no guarantees of their safety while you're gone, especially that of the health of any living creatures. With that in mind, are you ready to leave?", "Exit", "Leave", "Stay") == "Leave")
+ if(!user.canmove || (get_dist(get_turf(src), get_turf(user)) > 1)) //no teleporting around if they're dead or moved away during the prompt.
+ return
+ user.forceMove(get_turf(parentSphere))
+ do_sparks(3, FALSE, get_turf(user))
+
+/turf/closed/indestructible/hoteldoor/attack_ghost(mob/dead/observer/user)
+ if(!isobserver(user) || !parentSphere)
+ return ..()
+ user.forceMove(get_turf(parentSphere))
+
+//If only this could be simplified...
+/turf/closed/indestructible/hoteldoor/attack_tk(mob/user)
+ return //need to be close.
+
+/turf/closed/indestructible/hoteldoor/attack_hand(mob/user)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/attack_animal(mob/user)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/attack_paw(mob/user)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/attack_hulk(mob/living/carbon/human/user, does_attack_animation)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/attack_larva(mob/user)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/attack_slime(mob/user)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/attack_robot(mob/user)
+ if(get_dist(get_turf(src), get_turf(user)) <= 1)
+ promptExit(user)
+
+/turf/closed/indestructible/hoteldoor/AltClick(mob/user)
+ . = ..()
+ if(get_dist(get_turf(src), get_turf(user)) <= 1)
+ to_chat(user, "You peak through the door's bluespace peephole...")
+ user.reset_perspective(parentSphere)
+ user.set_machine(src)
+ var/datum/action/peepholeCancel/PHC = new
+ user.overlay_fullscreen("remote_view", /obj/screen/fullscreen/impaired, 1)
+ PHC.Grant(user)
+
+/turf/closed/indestructible/hoteldoor/check_eye(mob/user)
+ if(get_dist(get_turf(src), get_turf(user)) >= 2)
+ user.unset_machine()
+ for(var/datum/action/peepholeCancel/PHC in user.actions)
+ PHC.Trigger()
+
+/datum/action/peepholeCancel
+ name = "Cancel View"
+ desc = "Stop looking through the bluespace peephole."
+ button_icon_state = "cancel_peephole"
+
+/datum/action/peepholeCancel/Trigger()
+ . = ..()
+ to_chat(owner, "You move away from the peephole.")
+ owner.reset_perspective()
+ owner.clear_fullscreen("remote_view", 0)
+ qdel(src)
+
+/area/hilbertshotel
+ name = "Hilbert's Hotel Room"
+ icon_state = "hilbertshotel"
+ requires_power = FALSE
+ has_gravity = TRUE
+ noteleport = TRUE
+ hidden = TRUE
+ unique = FALSE
+ dynamic_lighting = DYNAMIC_LIGHTING_FORCED
+ ambientsounds = list('sound/ambience/servicebell.ogg')
+ var/roomnumber = 0
+ var/obj/item/hilbertshotel/parentSphere
+ var/datum/turf_reservation/reservation
+ var/turf/storageTurf
+
+/area/hilbertshotel/Entered(atom/movable/AM)
+ . = ..()
+ if(istype(AM, /obj/item/hilbertshotel))
+ relocate(AM)
+ var/list/obj/item/hilbertshotel/hotels = AM.GetAllContents(/obj/item/hilbertshotel)
+ for(var/obj/item/hilbertshotel/H in hotels)
+ if(parentSphere == H)
+ relocate(H)
+
+/area/hilbertshotel/proc/relocate(obj/item/hilbertshotel/H)
+ if(prob(0.135685)) //Because screw you
+ qdel(H)
+ return
+ var/turf/targetturf = find_safe_turf()
+ if(!targetturf)
+ if(GLOB.blobstart.len > 0)
+ targetturf = get_turf(pick(GLOB.blobstart))
+ else
+ CRASH("Unable to find a blobstart landmark")
+ var/turf/T = get_turf(H)
+ var/area/A = T.loc
+ log_game("[H] entered itself. Moving it to [loc_name(targetturf)].")
+ message_admins("[H] entered itself. Moving it to [ADMIN_VERBOSEJMP(targetturf)].")
+ for(var/mob/M in A)
+ to_chat(M, "[H] almost implodes in upon itself, but quickly rebounds, shooting off into a random point in space!")
+ H.forceMove(targetturf)
+
+/area/hilbertshotel/Exited(atom/movable/AM)
+ . = ..()
+ if(ismob(AM))
+ var/mob/M = AM
+ if(M.mind)
+ var/stillPopulated = FALSE
+ var/list/currentLivingMobs = GetAllContents(/mob/living) //Got to catch anyone hiding in anything
+ for(var/mob/living/L in currentLivingMobs) //Check to see if theres any sentient mobs left.
+ if(L.mind)
+ stillPopulated = TRUE
+ break
+ if(!stillPopulated)
+ storeRoom()
+
+/area/hilbertshotel/proc/storeRoom()
+ var/roomSize = (reservation.top_right_coords[1]-reservation.bottom_left_coords[1]+1)*(reservation.top_right_coords[2]-reservation.bottom_left_coords[2]+1)
+ var/storage[roomSize]
+ var/turfNumber = 1
+ var/obj/item/abstracthotelstorage/storageObj = new(storageTurf)
+ storageObj.roomNumber = roomnumber
+ storageObj.parentSphere = parentSphere
+ storageObj.name = "Room [roomnumber] Storage"
+ for(var/i=0, iIt's to far away to scan!")
+ return
+ var/obj/item/hilbertshotel/sphere = target
+ if(sphere.activeRooms.len)
+ to_chat(user, "Currently Occupied Rooms:")
+ for(var/roomnumber in sphere.activeRooms)
+ to_chat(user, roomnumber)
+ else
+ to_chat(user, "No currenty occupied rooms.")
+ if(sphere.storedRooms.len)
+ to_chat(user, "Vacated Rooms:")
+ for(var/roomnumber in sphere.storedRooms)
+ to_chat(user, roomnumber)
+ else
+ to_chat(user, "No vacated rooms.")
+
+/obj/effect/mob_spawn/human/doctorhilbert
+ name = "Doctor Hilbert"
+ mob_name = "Doctor Hilbert"
+ mob_gender = "male"
+ assignedrole = null
+ ghost_usable = FALSE
+ oxy_damage = 500
+ mob_species = /datum/species/skeleton
+ id_job = "Head Researcher"
+ id_access = ACCESS_RESEARCH
+ id_access_list = list(ACCESS_AWAY_GENERIC3, ACCESS_RESEARCH)
+ instant = TRUE
+ id = /obj/item/card/id/silver
+ uniform = /obj/item/clothing/under/rank/research_director
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ back = /obj/item/storage/backpack/satchel/leather
+ suit = /obj/item/clothing/suit/toggle/labcoat
+
+/obj/item/paper/crumpled/docslogs
+ name = "Research Logs"
+
+/obj/item/paper/crumpled/docslogs/Initialize()
+ . = ..()
+ GLOB.hhmysteryRoomNumber = rand(1, SHORT_REAL_LIMIT)
+ info = {"
Research Logs
+ I might just be onto something here!
+ The strange space-warping properties of bluespace have been known about for awhile now, but I might be on the verge of discovering a new way of harnessing it.
+ It's too soon to say for sure, but this might be the start of something quite important!
+ I'll be sure to log any major future breakthroughs. This might be a lot more than I can manage on my own, perhaps I should hire that secretary after all...
+
Breakthrough!
+ I can't believe it, but I did it! Just when I was certain it couldn't be done, I made the final necessary breakthrough.
+ Exploiting the effects of space dilation caused by specific bluespace structures combined with a precise use of geometric calculus, I've discovered a way to correlate an infinite amount of space within a finite area!
+ While the potential applications are endless, I utilized it in quite a nifty way so far by designing a system that recursively constructs subspace rooms and spatially links them to any of the infinite infinitesimally distinct points on the spheres surface.
+ I call it: Hilbert's Hotel!
+
Goodbye
+ I can't take this anymore. I know what happens next, and the fear of what is coming leaves me unable to continue working.
+ Any fool in my field has heard the stories. It's not that I didn't believe them, it's just... I guess I underestimated the importance of my own research...
+ Robert has reported a further increase in frequency of the strange, prying visitors who ask questions they have no business asking. I've requested him to keep everything on strict lockdown and have permanently dismissed all other assistants.
+ I've also instructed him to use the encryption method we discussed for any important quantitative data. The poor lad... I don't think he truly understands what he's gotten himself into...
+ It's clear what happens now. One day they'll show up uninvited, and claim my research as their own, leaving me as nothing more than a bullet ridden corpse floating in space.
+ I can't stick around to the let that happen.
+ I'm escaping into the very thing that brought all this trouble to my doorstep in the first place - my hotel.
+ I'll be in [uppertext(num2hex(GLOB.hhmysteryRoomNumber, 0))] (That will make sense to anyone who should know)
+ I'm sorry that I must go like this. Maybe one day things will be different and it will be safe to return... maybe...
+ Goodbye
+
+ Doctor Hilbert"}
+
+/obj/item/paper/crumpled/robertsworkjournal
+ name = "Work Journal"
+ info = {"
First Week!
+ First week on the new job. It's a secretarial position, but hey, whatever pays the bills. Plus it seems like some interesting stuff goes on here.
+ Doc says its best that I don't openly talk about his research with others, I guess he doesn't want it getting out or something. I've caught myself slipping a few times when talking to others, it's hard not to brag about something this cool!
+ I'm not really sure why I'm choosing to journal this. Doc seems to log everything. He says it's incase he discovers anything important.
+ I guess that's why I'm doing it too, I've always wanted to be a part of something important.
+ Here's to a new job and to becoming a part of something important!
+
Weird times...
+ Things are starting to get a little strange around here. Just weeks after Doc's amazing breakthrough, weird visitors have began showing up unannounced, asking strange things about Doc's work.
+ I knew Doc wasn't a big fan of company, but even he seemed strangely unnerved when I told him about the visitors.
+ He said it's important that from here on out we keep tight security on everything, even other staff members.
+ He also said something about securing data, something about hexes. What's that mean? Some sort of curse? Doc never struck me as the magic type...
+ He often uses a lot of big sciencey words that I don't really understand, but I kinda dig it, it makes me feel like I'm witnessing something big.
+ I hope things go back to normal soon, but I guess that's the price you pay for being a part of something important.
+
Last day I guess?
+ Things are officially starting to get too strange for me.
+ The visitors have been coming a lot more often, and they all seem increasingly aggressive and nosey. I'm starting to see why they made Doc so nervous, they're certainly starting to creep me out too.
+ Awhile ago Doc started having me keep the place on strict lockdown and requested I refuse entry to anyone else, including previous staff.
+ But the weirdest part?
+ I haven't seen Doc in days. It's not unusual for him to work continuously for long periods of time in the lab, but when I took a peak in their yesterday - he was nowhere to be seen! I didn't risk prying much further, Doc had a habit of leaving the defense systems on these last few weeks.
+ I'm thinking it might be time to call it quits. Can't work much without a boss, plus things are starting to get kind of shady. I wanted to be a part of something important, but you gotta know when to play it safe.
+ As my dad always said, "The smart get famous, but the wise survive..."
+
+ Robert P."}
+
+/obj/item/paper/crumpled/bloody/docsdeathnote
+ name = "note"
+ info = {"This is it isn't it?
+ No one's coming to help, that much has become clear.
+ Sure, it's lonely, but do I have much choice? At least I brought the analyzer with me, they shouldn't be able to find me without it.
+ Who knows who's waiting for me out there. Its either die out there in their hands, or die a slower, slightly more comfortable death in here.
+ Everyday I can feel myself slipping away more and more, both physically and mentally. Who knows what happens now...
+ Heh, so it's true then, this must be the inescapable path of all great minds... so be it then.
+
+
+
+ Choose a room, and enter the sphere
+ Lay your head to rest, it soon becomes clear
+ There's always more room around every bend
+ Not all that's countable has an end..."}
diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm
index 119023d465..b581a54095 100644
--- a/code/modules/shuttle/emergency.dm
+++ b/code/modules/shuttle/emergency.dm
@@ -232,7 +232,7 @@
SSshuttle.emergencyLastCallLoc = null
if(!silent)
- priority_announce("The emergency shuttle has been called. [redAlert ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [timeLeft(600)] minutes.[reason][SSshuttle.emergencyLastCallLoc ? "\n\nCall signal traced. Results can be viewed on any communications console." : "" ]", null, 'sound/ai/shuttlecalled.ogg', "Priority")
+ priority_announce("The emergency shuttle has been called. [redAlert ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [timeLeft(600)] minutes.[reason][SSshuttle.emergencyLastCallLoc ? "\n\nCall signal traced. Results can be viewed on any communications console." : "" ]", null, "shuttlecalled", "Priority")
/obj/docking_port/mobile/emergency/cancel(area/signalOrigin)
if(mode != SHUTTLE_CALL)
@@ -247,7 +247,7 @@
SSshuttle.emergencyLastCallLoc = signalOrigin
else
SSshuttle.emergencyLastCallLoc = null
- priority_announce("The emergency shuttle has been recalled.[SSshuttle.emergencyLastCallLoc ? " Recall signal traced. Results can be viewed on any communications console." : "" ]", null, 'sound/ai/shuttlerecalled.ogg', "Priority")
+ priority_announce("The emergency shuttle has been recalled.[SSshuttle.emergencyLastCallLoc ? " Recall signal traced. Results can be viewed on any communications console." : "" ]", null, "shuttlerecalled", "Priority")
/obj/docking_port/mobile/emergency/proc/is_hijacked()
var/has_people = FALSE
@@ -319,7 +319,7 @@
mode = SHUTTLE_DOCKED
setTimer(SSshuttle.emergencyDockTime)
send2irc("Server", "The Emergency Shuttle has docked with the station.")
- priority_announce("The Emergency Shuttle has docked with the station. You have [timeLeft(600)] minutes to board the Emergency Shuttle.", null, 'sound/ai/shuttledock.ogg', "Priority")
+ priority_announce("The Emergency Shuttle has docked with the station. You have [timeLeft(600)] minutes to board the Emergency Shuttle.", null, "shuttledock", "Priority")
ShuttleDBStuff()
diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm
index dd2d7483e3..121ee2e07f 100644
--- a/code/modules/shuttle/on_move.dm
+++ b/code/modules/shuttle/on_move.dm
@@ -290,7 +290,7 @@ All ShuttleMove procs go here
// ignores the movement of the shuttle from the staging area on CentCom to
// the station as it is loaded in.
if (oldT && !is_centcom_level(oldT.z))
- GET_COMPONENT(STR, /datum/component/storage/concrete/emergency)
+ var/datum/component/storage/concrete/emergency/STR = GetComponent(/datum/component/storage/concrete/emergency)
STR?.unlock_me()
/************************************Mob move procs************************************/
diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm
index 9bea790957..ab08c162a1 100644
--- a/code/modules/shuttle/special.dm
+++ b/code/modules/shuttle/special.dm
@@ -187,7 +187,7 @@
var/mob/living/M = AM
var/throwtarget = get_edge_target_turf(src, boot_dir)
M.Knockdown(40)
- M.throw_at(throwtarget, 5, 1,src)
+ M.throw_at(throwtarget, 5, 1)
to_chat(M, "No climbing on the bar please.")
else
. = ..()
diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm
index 2249f5f10e..32c38451c5 100644
--- a/code/modules/shuttle/supply.dm
+++ b/code/modules/shuttle/supply.dm
@@ -24,7 +24,8 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list(
/obj/effect/portal,
/obj/item/shared_storage,
/obj/structure/extraction_point,
- /obj/machinery/syndicatebomb
+ /obj/machinery/syndicatebomb,
+ /obj/item/hilbertshotel
)))
/obj/docking_port/mobile/supply
diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm
index 98eb6f56bf..22dee60eb4 100644
--- a/code/modules/spells/spell.dm
+++ b/code/modules/spells/spell.dm
@@ -115,6 +115,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
var/nonabstract_req = 0 //spell can only be cast by mobs that are physical entities
var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells
var/phase_allowed = 0 // If true, the spell can be cast while phased, eg. blood crawling, ethereal jaunting
+ var/antimagic_allowed = TRUE // If false, the spell cannot be cast while under the effect of antimagic
var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell
var/invocation_emote_self = null
var/invocation_type = "none" //can be none, whisper, emote and shout
@@ -147,27 +148,36 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if(player_lock)
if(!user.mind || !(src in user.mind.spell_list) && !(src in user.mob_spell_list))
to_chat(user, "You shouldn't have this spell! Something's wrong.")
- return 0
+ return FALSE
else
if(!(src in user.mob_spell_list))
- return 0
+ return FALSE
var/turf/T = get_turf(user)
if(is_centcom_level(T.z) && !centcom_cancast) //Certain spells are not allowed on the centcom zlevel
to_chat(user, "You can't cast this spell here.")
- return 0
+ return FALSE
if(!skipcharge)
if(!charge_check(user))
- return 0
+ return FALSE
if(user.stat && !stat_allowed)
to_chat(user, "Not when you're incapacitated.")
- return 0
+ return FALSE
+
+ if(!antimagic_allowed)
+ var/antimagic = user.anti_magic_check(TRUE, FALSE, chargecost = 0, self = TRUE)
+ if(antimagic)
+ if(isitem(antimagic))
+ to_chat(user, "[antimagic] is interfering with your magic.")
+ else
+ to_chat(user, "Magic seems to flee from you, you can't gather enough power to cast this spell.")
+ return FALSE
if(!phase_allowed && istype(user.loc, /obj/effect/dummy))
to_chat(user, "[name] cannot be cast unless you are completely manifested in the material plane.")
- return 0
+ return FALSE
if(ishuman(user))
@@ -175,7 +185,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if((invocation_type == "whisper" || invocation_type == "shout") && !H.can_speak_vocal())
to_chat(user, "You can't get the words out!")
- return 0
+ return FALSE
var/list/casting_clothes = typecacheof(list(/obj/item/clothing/suit/wizrobe,
/obj/item/clothing/suit/space/hardsuit/wizard,
@@ -187,24 +197,24 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if(clothes_req) //clothes check
if(!is_type_in_typecache(H.wear_suit, casting_clothes))
to_chat(H, "I don't feel strong enough without my robe.")
- return 0
+ return FALSE
if(!is_type_in_typecache(H.head, casting_clothes))
to_chat(H, "I don't feel strong enough without my hat.")
- return 0
+ return FALSE
if(cult_req) //CULT_REQ CLOTHES CHECK
if(!istype(H.wear_suit, /obj/item/clothing/suit/magusred) && !istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit/cult))
to_chat(H, "I don't feel strong enough without my armor.")
- return 0
+ return FALSE
if(!istype(H.head, /obj/item/clothing/head/magus) && !istype(H.head, /obj/item/clothing/head/helmet/space/hardsuit/cult))
to_chat(H, "I don't feel strong enough without my helmet.")
- return 0
+ return FALSE
else
if(clothes_req || human_req)
to_chat(user, "This spell can only be cast by humans!")
- return 0
+ return FALSE
if(nonabstract_req && (isbrain(user) || ispAI(user)))
to_chat(user, "This spell can only be cast by physical beings!")
- return 0
+ return FALSE
if(!skipcharge)
@@ -499,6 +509,9 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
if(user.stat && !stat_allowed)
return FALSE
+ if(!antimagic_allowed && user.anti_magic_check(TRUE, FALSE, chargecost = 0, self = TRUE))
+ return FALSE
+
if(!ishuman(user))
if(clothes_req || human_req)
return FALSE
diff --git a/code/modules/spells/spell_types/construct_spells.dm b/code/modules/spells/spell_types/construct_spells.dm
index bb3cc1f7e3..0c0b20f0fc 100644
--- a/code/modules/spells/spell_types/construct_spells.dm
+++ b/code/modules/spells/spell_types/construct_spells.dm
@@ -146,7 +146,7 @@
clothes_req = 0
invocation = "none"
invocation_type = "none"
- proj_type = /obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile/lesser
+ proj_type = "/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile/lesser"
proj_lifespan = 10
max_targets = 6
action_icon_state = "magicm"
diff --git a/code/modules/spells/spell_types/forcewall.dm b/code/modules/spells/spell_types/forcewall.dm
index 47d6f71f9b..ed78e3315a 100644
--- a/code/modules/spells/spell_types/forcewall.dm
+++ b/code/modules/spells/spell_types/forcewall.dm
@@ -35,6 +35,6 @@
return TRUE
if(ismob(mover))
var/mob/M = mover
- if(M.anti_magic_check())
+ if(M.anti_magic_check(chargecost = 0))
return TRUE
return FALSE
diff --git a/code/modules/spells/spell_types/mind_transfer.dm b/code/modules/spells/spell_types/mind_transfer.dm
index 107f303049..d78b32c643 100644
--- a/code/modules/spells/spell_types/mind_transfer.dm
+++ b/code/modules/spells/spell_types/mind_transfer.dm
@@ -61,7 +61,7 @@ Also, you never added distance checking after target is selected. I've went ahea
return
var/datum/mind/TM = target.mind
- if((target.anti_magic_check() || TM.has_antag_datum(/datum/antagonist/wizard) || TM.has_antag_datum(/datum/antagonist/cult) || TM.has_antag_datum(/datum/antagonist/clockcult) || TM.has_antag_datum(/datum/antagonist/changeling) || TM.has_antag_datum(/datum/antagonist/rev)) || cmptext(copytext(target.key,1,2),"@"))
+ if((target.anti_magic_check(TRUE, FALSE) || TM.has_antag_datum(/datum/antagonist/wizard) || TM.has_antag_datum(/datum/antagonist/cult) || TM.has_antag_datum(/datum/antagonist/clockcult) || TM.has_antag_datum(/datum/antagonist/changeling) || TM.has_antag_datum(/datum/antagonist/rev)) || cmptext(copytext(target.key,1,2),"@"))
if(!silent)
to_chat(user, "[target.p_their(TRUE)] mind is resisting your spell!")
return
diff --git a/code/modules/spells/spell_types/shapeshift.dm b/code/modules/spells/spell_types/shapeshift.dm
index 1576c55326..46eb14013f 100644
--- a/code/modules/spells/spell_types/shapeshift.dm
+++ b/code/modules/spells/spell_types/shapeshift.dm
@@ -13,7 +13,7 @@
var/revert_on_death = TRUE
var/die_with_shapeshifted_form = TRUE
- var/convert_damage = FALSE //If you want to convert the caster's health to the shift, and vice versa.
+ var/convert_damage = TRUE //If you want to convert the caster's health to the shift, and vice versa.
var/convert_damage_type = BRUTE //Since simplemobs don't have advanced damagetypes, what to convert damage back into.
var/shapeshift_type
var/list/possible_shapes = list(/mob/living/simple_animal/mouse,\
@@ -101,8 +101,10 @@
stored.forceMove(src)
stored.notransform = TRUE
if(source.convert_damage)
- var/damapply = (stored.maxHealth - (stored.health + stored.maxHealth)/2) //Carbons go from -100 to 100 naturally, while simplemobs only go from 0 to 100. Can't do a direct conversion.
- shape.apply_damage(damapply, source.convert_damage_type)
+ var/damage_percent = (stored.maxHealth - stored.health)/stored.maxHealth;
+ var/damapply = damage_percent * shape.maxHealth;
+
+ shape.apply_damage(damapply, source.convert_damage_type, forced = TRUE);
slink = soullink(/datum/soullink/shapeshift, stored , shape)
slink.source = src
@@ -152,8 +154,10 @@
stored.death()
else if(source.convert_damage)
stored.revive(full_heal = TRUE)
- var/damapply = (shape.maxHealth - 2*shape.health) //Since we halved incoming damage, double outgoing.
- stored.apply_damage(damapply, source.convert_damage_type)
+ var/damage_percent = (shape.maxHealth - shape.health)/shape.maxHealth;
+ var/damapply = stored.maxHealth * damage_percent
+
+ stored.apply_damage(damapply, source.convert_damage_type, forced = TRUE)
qdel(shape)
qdel(src)
diff --git a/code/modules/spells/spell_types/spacetime_distortion.dm b/code/modules/spells/spell_types/spacetime_distortion.dm
index 7fd857dc51..7a19787675 100644
--- a/code/modules/spells/spell_types/spacetime_distortion.dm
+++ b/code/modules/spells/spell_types/spacetime_distortion.dm
@@ -86,7 +86,7 @@
/obj/effect/cross_action/spacetime_dist/proc/walk_link(atom/movable/AM)
if(ismob(AM))
var/mob/M = AM
- if(M.anti_magic_check())
+ if(M.anti_magic_check(chargecost = 0))
return
if(linked_dist && walks_left > 0)
flick("purplesparkles", src)
diff --git a/code/modules/spells/spell_types/summonitem.dm b/code/modules/spells/spell_types/summonitem.dm
index 6d46c53a9d..7d9823e29b 100644
--- a/code/modules/spells/spell_types/summonitem.dm
+++ b/code/modules/spells/spell_types/summonitem.dm
@@ -61,6 +61,10 @@
organ.Remove(organ.owner)
else
while(!isturf(item_to_retrieve.loc) && infinite_recursion < 10) //if it's in something you get the whole thing.
+ if(isitem(item_to_retrieve.loc))
+ var/obj/item/I = item_to_retrieve.loc
+ if(I.item_flags & ABSTRACT) //Being able to summon abstract things because your item happened to get placed there is a no-no
+ break
if(ismob(item_to_retrieve.loc)) //If its on someone, properly drop it
var/mob/M = item_to_retrieve.loc
diff --git a/code/modules/spells/spell_types/telepathy.dm b/code/modules/spells/spell_types/telepathy.dm
new file mode 100644
index 0000000000..34f100f753
--- /dev/null
+++ b/code/modules/spells/spell_types/telepathy.dm
@@ -0,0 +1,32 @@
+/obj/effect/proc_holder/spell/targeted/telepathy
+ name = "Telepathy"
+ desc = "Telepathically transmits a message to the target."
+ charge_max = 0
+ clothes_req = 0
+ range = 7
+ include_user = 0
+ action_icon = 'icons/mob/actions/actions_revenant.dmi'
+ action_icon_state = "r_transmit"
+ action_background_icon_state = "bg_spell"
+ var/notice = "notice"
+ var/boldnotice = "boldnotice"
+ var/magic_check = FALSE
+ var/holy_check = FALSE
+ var/tinfoil_check = TRUE
+
+/obj/effect/proc_holder/spell/targeted/telepathy/cast(list/targets, mob/living/user = usr)
+ for(var/mob/living/M in targets)
+ var/msg = stripped_input(usr, "What do you wish to tell [M]?", null, "")
+ if(!msg)
+ charge_counter = charge_max
+ return
+ log_directed_talk(user, M, msg, LOG_SAY, "[name]")
+ to_chat(user, "You transmit to [M]:[msg]")
+ if(!M.anti_magic_check(magic_check, holy_check, tinfoil_check, 0)) //hear no evil
+ to_chat(M, "You hear something behind you talking...[msg]")
+ for(var/ded in GLOB.dead_mob_list)
+ if(!isobserver(ded))
+ continue
+ var/follow_rev = FOLLOW_LINK(ded, user)
+ var/follow_whispee = FOLLOW_LINK(ded, M)
+ to_chat(ded, "[follow_rev] [user] [name]:\"[msg]\" to [follow_whispee] [M]")
diff --git a/code/modules/station_goals/dna_vault.dm b/code/modules/station_goals/dna_vault.dm
index 3073a6fcc3..2aae17b0f3 100644
--- a/code/modules/station_goals/dna_vault.dm
+++ b/code/modules/station_goals/dna_vault.dm
@@ -276,7 +276,7 @@
ADD_TRAIT(H, TRAIT_PIERCEIMMUNE, "dna_vault")
if(VAULT_SPEED)
to_chat(H, "Your legs feel faster.")
- ADD_TRAIT(H, TRAIT_GOTTAGOFAST, "dna_vault")
+ H.add_movespeed_modifier(MOVESPEED_ID_DNA_VAULT, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
if(VAULT_QUICK)
to_chat(H, "Your arms move as fast as lightning.")
H.next_move_modifier = 0.5
diff --git a/code/modules/station_goals/station_goal.dm b/code/modules/station_goals/station_goal.dm
index 88377455c6..b68fef3e2f 100644
--- a/code/modules/station_goals/station_goal.dm
+++ b/code/modules/station_goals/station_goal.dm
@@ -12,7 +12,7 @@
var/report_message = "Complete this goal."
/datum/station_goal/proc/send_report()
- priority_announce("Priority Nanotrasen directive received. Project \"[name]\" details inbound.", "Incoming Priority Message", 'sound/ai/commandreport.ogg')
+ priority_announce("Priority Nanotrasen directive received. Project \"[name]\" details inbound.", "Incoming Priority Message", "commandreport")
print_command_report(get_report(),"Nanotrasen Directive [pick(GLOB.phonetic_alphabet)] \Roman[rand(1,50)]", announce=FALSE)
on_report()
diff --git a/code/modules/surgery/advanced/bioware/bioware_surgery.dm b/code/modules/surgery/advanced/bioware/bioware_surgery.dm
index 86817b9b09..eb8f739193 100644
--- a/code/modules/surgery/advanced/bioware/bioware_surgery.dm
+++ b/code/modules/surgery/advanced/bioware/bioware_surgery.dm
@@ -5,6 +5,8 @@
/datum/surgery/advanced/bioware/can_start(mob/user, mob/living/carbon/human/target)
if(!..())
return FALSE
+ if(!istype(target))
+ return FALSE
for(var/X in target.bioware)
var/datum/bioware/B = X
if(B.mod_type == bioware_target)
diff --git a/code/modules/surgery/advanced/bioware/experimental_dissection.dm b/code/modules/surgery/advanced/bioware/experimental_dissection.dm
deleted file mode 100644
index 5dac3e744d..0000000000
--- a/code/modules/surgery/advanced/bioware/experimental_dissection.dm
+++ /dev/null
@@ -1,72 +0,0 @@
-/datum/surgery/advanced/bioware/experimental_dissection
- name = "Experimental Dissection"
- desc = "A surgical procedure which deeply analyzes the biology of a corpse, and automatically adds new findings to the research database."
- steps = list(/datum/surgery_step/incise,
- /datum/surgery_step/retract_skin,
- /datum/surgery_step/clamp_bleeders,
- /datum/surgery_step/incise,
- /datum/surgery_step/dissection,
- /datum/surgery_step/close)
- possible_locs = list(BODY_ZONE_CHEST)
- bioware_target = BIOWARE_DISSECTION
-
-/datum/surgery/advanced/bioware/experimental_dissection/can_start(mob/user, mob/living/carbon/target)
- . = ..()
- if(iscyborg(user))
- return FALSE //robots cannot be creative
- //(also this surgery shouldn't be consistently successful, and cyborgs have a 100% success rate on surgery)
- if(target.stat != DEAD)
- return FALSE
-
-/datum/surgery_step/dissection
- name = "dissection"
- implements = list(TOOL_SCALPEL = 60, /obj/item/kitchen/knife = 30, /obj/item/shard = 15)
- time = 125
-
-/datum/surgery_step/dissection/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
- display_results(user, target, "You start dissecting [target].",
- "[user] starts dissecting [target].",
- "[user] starts dissecting [target].")
-
-/datum/surgery_step/dissection/proc/check_value(mob/living/carbon/target)
- if(isalienroyal(target))
- return 10000
- else if(isalienadult(target))
- return 5000
- else if(ismonkey(target))
- return 1000
- else if(ishuman(target))
- var/mob/living/carbon/human/H = target
- if(H.dna && H.dna.species)
- if(isabductor(H))
- return 8000
- if(isgolem(H) || iszombie(H))
- return 4000
- if(isjellyperson(H) || ispodperson(H))
- return 3000
- return 2000
-
-/datum/surgery_step/dissection/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
- display_results(user, target, "You dissect [target], and add your discoveries to the research database!",
- "[user] dissects [target], adding [user.p_their()] discoveries to the research database!",
- "[user] dissects [target]!")
- SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = check_value(target)))
- var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST)
- target.apply_damage(80, BRUTE, L)
- new /datum/bioware/dissected(target)
- return TRUE
-
-/datum/surgery_step/dissection/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
- display_results(user, target, "You dissect [target], but do not find anything particularly interesting.",
- "[user] dissects [target], however it seems [user.p_they()] didn't find anything useful.",
- "[user] dissects [target], but looks a little dissapointed.")
- SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = (check_value(target) * 0.2)))
- var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST)
- target.apply_damage(80, BRUTE, L)
- new /datum/bioware/dissected(target)
- return TRUE
-
-/datum/bioware/dissected
- name = "Dissected"
- desc = "This body has been dissected and analyzed. It is no longer worth experimenting on."
- mod_type = BIOWARE_DISSECTION
\ No newline at end of file
diff --git a/code/modules/surgery/advanced/bioware/muscled_veins.dm b/code/modules/surgery/advanced/bioware/muscled_veins.dm
new file mode 100644
index 0000000000..81212019a8
--- /dev/null
+++ b/code/modules/surgery/advanced/bioware/muscled_veins.dm
@@ -0,0 +1,42 @@
+/datum/surgery/advanced/bioware/muscled_veins
+ name = "Vein Muscle Membrane"
+ desc = "A surgical procedure which adds a muscled membrane to blood vessels, allowing them to pump blood without a heart."
+ steps = list(/datum/surgery_step/incise,
+ /datum/surgery_step/retract_skin,
+ /datum/surgery_step/clamp_bleeders,
+ /datum/surgery_step/incise,
+ /datum/surgery_step/incise,
+ /datum/surgery_step/muscled_veins,
+ /datum/surgery_step/close)
+ possible_locs = list(BODY_ZONE_CHEST)
+ bioware_target = BIOWARE_CIRCULATION
+
+/datum/surgery_step/muscled_veins
+ name = "shape vein muscles"
+ accept_hand = TRUE
+ time = 125
+
+/datum/surgery_step/muscled_veins/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You start wrapping muscles around [target]'s circulatory system.",
+ "[user] starts wrapping muscles around [target]'s circulatory system.",
+ "[user] starts manipulating [target]'s circulatory system.")
+
+/datum/surgery_step/muscled_veins/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You reshape [target]'s circulatory system, adding a muscled membrane!",
+ "[user] reshapes [target]'s circulatory system, adding a muscled membrane!",
+ "[user] finishes manipulating [target]'s circulatory system.")
+ new /datum/bioware/muscled_veins(target)
+ return TRUE
+
+/datum/bioware/muscled_veins
+ name = "Threaded Veins"
+ desc = "The circulatory system is woven into a mesh, severely reducing the amount of blood lost from wounds."
+ mod_type = BIOWARE_CIRCULATION
+
+/datum/bioware/muscled_veins/on_gain()
+ ..()
+ ADD_TRAIT(owner, TRAIT_STABLEHEART, "muscled_veins")
+
+/datum/bioware/muscled_veins/on_lose()
+ ..()
+ REMOVE_TRAIT(owner, TRAIT_STABLEHEART, "muscled_veins")
\ No newline at end of file
diff --git a/code/modules/surgery/advanced/brainwashing.dm b/code/modules/surgery/advanced/brainwashing.dm
index 28d2f8fe28..b067cce56b 100644
--- a/code/modules/surgery/advanced/brainwashing.dm
+++ b/code/modules/surgery/advanced/brainwashing.dm
@@ -13,8 +13,9 @@
/datum/surgery_step/brainwash,
/datum/surgery_step/close)
- species = list(/mob/living/carbon/human)
+ target_mobtypes = list(/mob/living/carbon/human)
possible_locs = list(BODY_ZONE_HEAD)
+
/datum/surgery/advanced/brainwashing/can_start(mob/user, mob/living/carbon/target)
if(!..())
return FALSE
diff --git a/code/modules/surgery/advanced/lobotomy.dm b/code/modules/surgery/advanced/lobotomy.dm
index c8c699bfbd..0149fc6c27 100644
--- a/code/modules/surgery/advanced/lobotomy.dm
+++ b/code/modules/surgery/advanced/lobotomy.dm
@@ -9,7 +9,7 @@
/datum/surgery_step/lobotomize,
/datum/surgery_step/close)
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_HEAD)
requires_bodypart_type = 0
/datum/surgery/advanced/lobotomy/can_start(mob/user, mob/living/carbon/target)
@@ -25,7 +25,7 @@
/obj/item/shard = 25, /obj/item = 20)
time = 100
/datum/surgery_step/lobotomize/tool_check(mob/user, obj/item/tool)
- if(implement_type == /obj/item && !tool.is_sharp())
+ if(implement_type == /obj/item && !tool.get_sharpness())
return FALSE
return TRUE
diff --git a/code/modules/surgery/advanced/pacification.dm b/code/modules/surgery/advanced/pacification.dm
index 8a236709a4..866c85842b 100644
--- a/code/modules/surgery/advanced/pacification.dm
+++ b/code/modules/surgery/advanced/pacification.dm
@@ -7,7 +7,8 @@
/datum/surgery_step/clamp_bleeders,
/datum/surgery_step/pacify,
/datum/surgery_step/close)
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_HEAD)
requires_bodypart_type = 0
/datum/surgery/advanced/pacify/can_start(mob/user, mob/living/carbon/target)
diff --git a/code/modules/surgery/advanced/reconstruction.dm b/code/modules/surgery/advanced/reconstruction.dm
deleted file mode 100644
index b5369838d4..0000000000
--- a/code/modules/surgery/advanced/reconstruction.dm
+++ /dev/null
@@ -1,35 +0,0 @@
-/datum/surgery/advanced/reconstruction
- name = "Reconstruction"
- desc = "A surgical procedure that gradually repairs damage done to a body without the assistance of chemicals. Unlike classic medicine, it is effective on corpses."
- steps = list(/datum/surgery_step/incise,
- /datum/surgery_step/incise,
- /datum/surgery_step/retract_skin,
- /datum/surgery_step/incise,
- /datum/surgery_step/clamp_bleeders,
- /datum/surgery_step/incise,
- /datum/surgery_step/retract_skin,
- /datum/surgery_step/reconstruct,
- /datum/surgery_step/close)
-
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
- possible_locs = list(BODY_ZONE_CHEST)
- requires_bodypart_type = 0
-
-/datum/surgery_step/reconstruct
- name = "repair body"
- implements = list(TOOL_HEMOSTAT = 100, TOOL_SCREWDRIVER = 35, /obj/item/pen = 15)
- repeatable = TRUE
- time = 25
-
-/datum/surgery_step/reconstruct/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
- user.visible_message("[user] starts knitting some of [target]'s flesh back together.", "You start knitting some of [target]'s flesh back together.")
-
-/datum/surgery_step/reconstruct/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
- user.visible_message("[user] fixes some of [target]'s wounds.", "You succeed in fixing some of [target]'s wounds.")
- target.heal_bodypart_damage(10,10)
- return TRUE
-
-/datum/surgery_step/reconstruct/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
- user.visible_message("[user] screws up!", "You screwed up!")
- target.take_bodypart_damage(5,0)
- return FALSE
\ No newline at end of file
diff --git a/code/modules/surgery/advanced/revival.dm b/code/modules/surgery/advanced/revival.dm
index b31a7518bd..a2d5345ea4 100644
--- a/code/modules/surgery/advanced/revival.dm
+++ b/code/modules/surgery/advanced/revival.dm
@@ -8,7 +8,8 @@
/datum/surgery_step/incise,
/datum/surgery_step/revive,
/datum/surgery_step/close)
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_HEAD)
requires_bodypart_type = 0
/datum/surgery/advanced/revival/can_start(mob/user, mob/living/carbon/target)
diff --git a/code/modules/surgery/advanced/toxichealing.dm b/code/modules/surgery/advanced/toxichealing.dm
index 998ca47b45..bb28a0fb05 100644
--- a/code/modules/surgery/advanced/toxichealing.dm
+++ b/code/modules/surgery/advanced/toxichealing.dm
@@ -11,7 +11,7 @@
/datum/surgery_step/toxichealing,
/datum/surgery_step/close)
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_CHEST)
requires_bodypart_type = 0
diff --git a/code/modules/surgery/advanced/viral_bonding.dm b/code/modules/surgery/advanced/viral_bonding.dm
index bdfd0e1552..87e6a8a99f 100644
--- a/code/modules/surgery/advanced/viral_bonding.dm
+++ b/code/modules/surgery/advanced/viral_bonding.dm
@@ -7,7 +7,8 @@
/datum/surgery_step/incise,
/datum/surgery_step/viral_bond,
/datum/surgery_step/close)
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_CHEST)
/datum/surgery/advanced/viral_bonding/can_start(mob/user, mob/living/carbon/target)
if(!..())
@@ -23,7 +24,7 @@
/datum/surgery_step/viral_bond/tool_check(mob/user, obj/item/tool)
if(implement_type == TOOL_WELDER || implement_type == /obj/item)
- return tool.is_hot()
+ return tool.get_temperature()
return TRUE
/datum/surgery_step/viral_bond/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
diff --git a/code/modules/surgery/amputation.dm b/code/modules/surgery/amputation.dm
index 59493872e2..5c77532188 100644
--- a/code/modules/surgery/amputation.dm
+++ b/code/modules/surgery/amputation.dm
@@ -1,7 +1,7 @@
/datum/surgery/amputation
name = "Amputation"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/sever_limb)
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG, BODY_ZONE_HEAD)
requires_bodypart_type = 0
/datum/surgery_step/sever_limb
diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm
index dffb7bf355..9aa89dcaf5 100644
--- a/code/modules/surgery/bodyparts/bodyparts.dm
+++ b/code/modules/surgery/bodyparts/bodyparts.dm
@@ -13,8 +13,7 @@
var/needs_processing = FALSE
var/body_zone //BODY_ZONE_CHEST, BODY_ZONE_L_ARM, etc , used for def_zone
- var/aux_zone // used for hands
- var/aux_layer
+ var/list/aux_icons // associative list, currently used for hands
var/body_part = null //bitflag used to check which clothes cover this bodypart
var/use_digitigrade = NOT_DIGITIGRADE //Used for alternate legs, useless elsewhere
var/list/embedded_objects = list()
@@ -434,9 +433,9 @@
. += image(body_markings_icon, "[body_markings]_[digitigrade_type]_[use_digitigrade]_[body_zone]", -MARKING_LAYER, image_dir)
var/image/limb = image(layer = -BODYPARTS_LAYER, dir = image_dir)
- var/image/aux
+ var/list/aux = list()
var/image/marking
- var/image/auxmarking
+ var/list/auxmarking = list()
. += limb
@@ -502,13 +501,15 @@
// Citadel End
- if(aux_zone)
- aux = image(limb.icon, "[species_id]_[aux_zone]", -aux_layer, image_dir)
- if(!isnull(aux_marking))
- if(species_id == "husk")
- auxmarking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[aux_zone]", -aux_layer, image_dir)
- else
- auxmarking = image(body_markings_icon, "[body_markings]_[aux_zone]", -aux_layer, image_dir)
+ if(aux_icons)
+ for(var/I in aux_icons)
+ var/aux_layer = aux_icons[I]
+ aux += image(limb.icon, "[species_id]_[I]", -aux_layer, image_dir)
+ if(!isnull(aux_marking))
+ if(species_id == "husk")
+ auxmarking += image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[I]", -aux_layer, image_dir)
+ else
+ auxmarking += image(body_markings_icon, "[body_markings]_[I]", -aux_layer, image_dir)
. += aux
. += auxmarking
@@ -519,15 +520,17 @@
else
limb.icon_state = "[body_zone]"
- if(aux_zone)
- aux = image(limb.icon, "[aux_zone]", -aux_layer, image_dir)
+ if(aux_icons)
+ for(var/I in aux_icons)
+ var/aux_layer = aux_icons[I]
+ aux += image(limb.icon, "[I]", -aux_layer, image_dir)
+ if(!isnull(aux_marking))
+ if(species_id == "husk")
+ auxmarking += image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[I]", -aux_layer, image_dir)
+ else
+ auxmarking += image(body_markings_icon, "[body_markings]_[I]", -aux_layer, image_dir)
+ . += auxmarking
. += aux
- if(!isnull(aux_marking))
- if(species_id == "husk")
- auxmarking = image('modular_citadel/icons/mob/markings_notmammals.dmi', "husk_[aux_zone]", -aux_layer, image_dir)
- else
- auxmarking = image(body_markings_icon, "[body_markings]_[aux_zone]", -aux_layer, image_dir)
- . += auxmarking
if(!isnull(body_markings))
if(species_id == "husk")
@@ -549,13 +552,17 @@
var/draw_color = mutation_color || species_color || (skin_tone && skintone2hex(skin_tone))
if(draw_color)
limb.color = "#[draw_color]"
- if(aux_zone)
- aux.color = "#[draw_color]"
+ if(aux_icons)
+ for(var/a in aux)
+ var/image/I = a
+ I.color = "#[draw_color]"
if(!isnull(aux_marking))
- if(species_id == "husk")
- auxmarking.color = "#141414"
- else
- auxmarking.color = list(markings_color)
+ for(var/a in auxmarking)
+ var/image/I = a
+ if(species_id == "husk")
+ I.color = "#141414"
+ else
+ I.color = list(markings_color)
if(!isnull(body_markings))
if(species_id == "husk")
@@ -633,8 +640,7 @@
max_stamina_damage = 50
body_zone = BODY_ZONE_L_ARM
body_part = ARM_LEFT
- aux_zone = BODY_ZONE_PRECISE_L_HAND
- aux_layer = HANDS_PART_LAYER
+ aux_icons = list(BODY_ZONE_PRECISE_L_HAND = HANDS_PART_LAYER, "l_hand_behind" = BODY_BEHIND_LAYER)
body_damage_coeff = 0.75
held_index = 1
px_x = -6
@@ -697,8 +703,7 @@
max_damage = 50
body_zone = BODY_ZONE_R_ARM
body_part = ARM_RIGHT
- aux_zone = BODY_ZONE_PRECISE_R_HAND
- aux_layer = HANDS_PART_LAYER
+ aux_icons = list(BODY_ZONE_PRECISE_R_HAND = HANDS_PART_LAYER, "r_hand_behind" = BODY_BEHIND_LAYER)
body_damage_coeff = 0.75
held_index = 2
px_x = 6
@@ -768,6 +773,8 @@
px_y = 12
stam_heal_tick = 2
max_stamina_damage = 50
+ var/blood_state = BLOOD_STATE_NOT_BLOODY
+ var/list/bloody_legs = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
/obj/item/bodypart/l_leg/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_LEG))
@@ -828,6 +835,8 @@
px_y = 12
max_stamina_damage = 50
stam_heal_tick = 2
+ var/blood_state = BLOOD_STATE_NOT_BLOODY
+ var/list/bloody_legs = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
/obj/item/bodypart/r_leg/is_disabled()
if(HAS_TRAIT(owner, TRAIT_PARALYSIS_R_LEG))
diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm
index a2e8017956..704a377fa8 100644
--- a/code/modules/surgery/bodyparts/helpers.dm
+++ b/code/modules/surgery/bodyparts/helpers.dm
@@ -49,6 +49,27 @@
+/mob/proc/has_left_leg()
+ return TRUE
+
+/mob/living/carbon/has_left_leg()
+ var/obj/item/bodypart/l_leg = get_bodypart(BODY_ZONE_L_LEG)
+ if(l_leg)
+ return TRUE
+ else
+ return FALSE
+
+/mob/proc/has_right_leg()
+ return TRUE
+
+/mob/living/carbon/has_right_leg()
+ var/obj/item/bodypart/r_leg = get_bodypart(BODY_ZONE_R_LEG)
+ if(r_leg)
+ return TRUE
+ else
+ return FALSE
+
+
//Limb numbers
/mob/proc/get_num_arms(check_disabled = TRUE)
return 2
@@ -91,14 +112,14 @@
/mob/proc/get_leg_ignore()
return FALSE
-/mob/living/carbon/alien/larva/get_leg_ignore()
- return TRUE
-
-/mob/living/carbon/human/get_leg_ignore()
- if((movement_type & FLYING) || floating)
+/mob/living/carbon/get_leg_ignore()
+ if(movement_type & (FLYING|FLOATING))
return TRUE
return FALSE
+/mob/living/carbon/alien/larva/get_leg_ignore()
+ return TRUE
+
/mob/living/proc/get_missing_limbs()
return list()
diff --git a/code/modules/surgery/brain_surgery.dm b/code/modules/surgery/brain_surgery.dm
index 63a5f8c728..d86f5731c7 100644
--- a/code/modules/surgery/brain_surgery.dm
+++ b/code/modules/surgery/brain_surgery.dm
@@ -7,7 +7,8 @@
/datum/surgery_step/clamp_bleeders,
/datum/surgery_step/fix_brain,
/datum/surgery_step/close)
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_HEAD)
requires_bodypart_type = 0
/datum/surgery_step/fix_brain
diff --git a/code/modules/surgery/cavity_implant.dm b/code/modules/surgery/cavity_implant.dm
index 4c65b56962..200e33b5f8 100644
--- a/code/modules/surgery/cavity_implant.dm
+++ b/code/modules/surgery/cavity_implant.dm
@@ -1,7 +1,7 @@
/datum/surgery/cavity_implant
name = "Cavity implant"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/incise, /datum/surgery_step/handle_cavity, /datum/surgery_step/close)
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_CHEST)
//handle cavity
/datum/surgery_step/handle_cavity
@@ -15,7 +15,7 @@
/datum/surgery_step/handle_cavity/tool_check(mob/user, obj/item/tool)
if(istype(tool, /obj/item/cautery) || istype(tool, /obj/item/gun/energy/laser))
return FALSE
- return !tool.is_hot()
+ return !tool.get_temperature()
/datum/surgery_step/handle_cavity/preop(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/obj/item/bodypart/chest/CH = target.get_bodypart(BODY_ZONE_CHEST)
IC = CH.cavity_item
diff --git a/code/modules/surgery/core_removal.dm b/code/modules/surgery/core_removal.dm
index 1ded00da2b..3f36a8bb8c 100644
--- a/code/modules/surgery/core_removal.dm
+++ b/code/modules/surgery/core_removal.dm
@@ -1,8 +1,10 @@
/datum/surgery/core_removal
name = "Core removal"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/extract_core)
- species = list(/mob/living/simple_animal/slime)
+ target_mobtypes = list(/mob/living/simple_animal/slime)
possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
+ lying_required = FALSE
+ ignore_clothes = TRUE
/datum/surgery/core_removal/can_start(mob/user, mob/living/target)
if(target.stat == DEAD)
diff --git a/code/modules/surgery/coronary_bypass.dm b/code/modules/surgery/coronary_bypass.dm
index c620b83d1f..71a48ae68c 100644
--- a/code/modules/surgery/coronary_bypass.dm
+++ b/code/modules/surgery/coronary_bypass.dm
@@ -48,7 +48,7 @@
//grafts a coronary bypass onto the individual's heart, success chance is 90% base again
/datum/surgery_step/coronary_bypass
name = "graft coronary bypass"
- implements = list(/obj/item/hemostat = 90, TOOL_WIRECUTTER = 35, /obj/item/stack/packageWrap = 15, /obj/item/stack/cable_coil = 5)
+ implements = list(TOOL_HEMOSTAT = 90, TOOL_WIRECUTTER = 35, /obj/item/stack/packageWrap = 15, /obj/item/stack/cable_coil = 5)
time = 90
/datum/surgery_step/coronary_bypass/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
diff --git a/code/modules/surgery/embalming.dm b/code/modules/surgery/embalming.dm
index e1053374c7..b07c2b3179 100644
--- a/code/modules/surgery/embalming.dm
+++ b/code/modules/surgery/embalming.dm
@@ -5,7 +5,7 @@
/datum/surgery_step/embalming,
/datum/surgery_step/close)
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_CHEST)
requires_bodypart_type = 0
diff --git a/code/modules/surgery/experimental_dissection.dm b/code/modules/surgery/experimental_dissection.dm
new file mode 100644
index 0000000000..3172496146
--- /dev/null
+++ b/code/modules/surgery/experimental_dissection.dm
@@ -0,0 +1,113 @@
+#define BASE_HUMAN_REWARD 500
+
+/datum/surgery/advanced/experimental_dissection
+ name = "Dissection"
+ desc = "A surgical procedure which analyzes the biology of a corpse, and automatically adds new findings to the research database."
+ steps = list(/datum/surgery_step/incise,
+ /datum/surgery_step/retract_skin,
+ /datum/surgery_step/clamp_bleeders,
+ /datum/surgery_step/dissection,
+ /datum/surgery_step/clamp_bleeders,
+ /datum/surgery_step/close)
+ possible_locs = list(BODY_ZONE_CHEST)
+ target_mobtypes = list(/mob/living) //Feel free to dissect devils but they're magic.
+ replaced_by = /datum/surgery/advanced/experimental_dissection/adv
+ requires_tech = FALSE
+ var/value_multiplier = 1
+
+/datum/surgery/advanced/experimental_dissection/can_start(mob/user, mob/living/target)
+ . = ..()
+ if(HAS_TRAIT_FROM(target, TRAIT_DISSECTED,"[name]"))
+ return FALSE
+ if(target.stat != DEAD)
+ return FALSE
+
+/datum/surgery_step/dissection
+ name = "dissection"
+ implements = list(/obj/item/scalpel/augment = 75, /obj/item/scalpel/advanced = 60, /obj/item/scalpel = 45, /obj/item/kitchen/knife = 20, /obj/item/shard = 10)// special tools not only cut down time but also improve probability, doesn't use TOOL_SCALPEL because different scalpels have different probs
+ time = 125
+ silicons_obey_prob = TRUE
+ repeatable = TRUE
+
+/datum/surgery_step/dissection/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You start dissecting [target].",
+ "[user] starts dissecting [target].",
+ "[user] starts dissecting [target].")
+
+/datum/surgery_step/dissection/proc/check_value(mob/living/target, datum/surgery/advanced/experimental_dissection/ED)
+ var/cost = BASE_HUMAN_REWARD
+ var/multi_surgery_adjust = 0
+
+ //determine bonus applied
+ if(isalienroyal(target))
+ cost = (BASE_HUMAN_REWARD*10)
+ else if(isalienadult(target))
+ cost = (BASE_HUMAN_REWARD*5)
+ else if(ismonkey(target))
+ cost = (BASE_HUMAN_REWARD*0.5)
+ else if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ if(H?.dna?.species)
+ if(isabductor(H))
+ cost = (BASE_HUMAN_REWARD*4)
+ else if(isgolem(H) || iszombie(H))
+ cost = (BASE_HUMAN_REWARD*3)
+ /*else if(isjellyperson(H) || ispodperson(H)) CITADEL CHANGE: jelly and pod being available roundstart shouldn't give additional points
+ cost = (BASE_HUMAN_REWARD*2)*/
+ else
+ cost = (BASE_HUMAN_REWARD * 0.6)
+
+
+
+ //now we do math for surgeries already done (no double dipping!).
+ for(var/i in typesof(/datum/surgery/advanced/experimental_dissection))
+ var/datum/surgery/advanced/experimental_dissection/cringe = i
+ if(HAS_TRAIT_FROM(target,TRAIT_DISSECTED,"[initial(cringe.name)]"))
+ multi_surgery_adjust = max(multi_surgery_adjust,initial(cringe.value_multiplier)) - 1
+
+ multi_surgery_adjust *= cost
+
+ //multiply by multiplier in surgery
+ cost *= ED.value_multiplier
+ return (cost-multi_surgery_adjust)
+
+/datum/surgery_step/dissection/success(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/points_earned = check_value(target, surgery)
+ display_results(user, target, "You dissect [target], and add your [points_earned] point\s worth of discoveries to the research database!",
+ "[user] dissects [target], discovering [points_earned] point\s of data!",
+ "[user] dissects [target]!")
+ SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points_earned))
+ var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST)
+ target.apply_damage(80, BRUTE, L)
+ ADD_TRAIT(target, TRAIT_DISSECTED, "[surgery.name]")
+ repeatable = FALSE
+ return TRUE
+
+/datum/surgery_step/dissection/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You dissect [target], but do not find anything particularly interesting.",
+ "[user] dissects [target], however it seems [user.p_they()] didn't find anything useful.",
+ "[user] dissects [target], but looks a little dissapointed.")
+ SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = (round(check_value(target, surgery) * 0.01))))
+ var/obj/item/bodypart/L = target.get_bodypart(BODY_ZONE_CHEST)
+ target.apply_damage(80, BRUTE, L)
+ return TRUE
+
+/datum/surgery/advanced/experimental_dissection/adv
+ name = "Thorough Dissection"
+ value_multiplier = 2
+ replaced_by = /datum/surgery/advanced/experimental_dissection/exp
+ requires_tech = TRUE
+
+/datum/surgery/advanced/experimental_dissection/exp
+ name = "Experimental Dissection"
+ value_multiplier = 5
+ replaced_by = /datum/surgery/advanced/experimental_dissection/alien
+ requires_tech = TRUE
+
+/datum/surgery/advanced/experimental_dissection/alien
+ name = "Extraterrestrial Dissection"
+ value_multiplier = 10
+ requires_tech = TRUE
+ replaced_by = null
+
+#undef EXPDIS_FAIL_MSG
\ No newline at end of file
diff --git a/code/modules/surgery/eye_surgery.dm b/code/modules/surgery/eye_surgery.dm
index 3e0c9c4ec3..f7a06af388 100644
--- a/code/modules/surgery/eye_surgery.dm
+++ b/code/modules/surgery/eye_surgery.dm
@@ -1,7 +1,7 @@
/datum/surgery/eye_surgery
name = "Eye surgery"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/fix_eyes, /datum/surgery_step/close)
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_PRECISE_EYES)
requires_bodypart_type = 0
//fix eyes
diff --git a/code/modules/surgery/graft_synthtissue.dm b/code/modules/surgery/graft_synthtissue.dm
index d9b03ca47f..7540b2cd94 100644
--- a/code/modules/surgery/graft_synthtissue.dm
+++ b/code/modules/surgery/graft_synthtissue.dm
@@ -4,7 +4,7 @@
/datum/surgery/graft_synthtissue
name = "Graft synthtissue"
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN, BODY_ZONE_PRECISE_EYES)
steps = list(
/datum/surgery_step/incise,
diff --git a/code/modules/surgery/healing.dm b/code/modules/surgery/healing.dm
new file mode 100644
index 0000000000..d20d1d822a
--- /dev/null
+++ b/code/modules/surgery/healing.dm
@@ -0,0 +1,215 @@
+/datum/surgery/healing
+ steps = list(/datum/surgery_step/incise,
+ /datum/surgery_step/retract_skin,
+ /datum/surgery_step/incise,
+ /datum/surgery_step/clamp_bleeders,
+ /datum/surgery_step/heal,
+ /datum/surgery_step/close)
+
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ possible_locs = list(BODY_ZONE_CHEST)
+ requires_bodypart_type = FALSE
+ replaced_by = /datum/surgery
+ ignore_clothes = TRUE
+ var/healing_step_type
+ var/antispam = FALSE
+
+/datum/surgery/healing/New(surgery_target, surgery_location, surgery_bodypart)
+ ..()
+ if(healing_step_type)
+ steps = list(/datum/surgery_step/incise/nobleed,
+ healing_step_type, //hehe cheeky
+ /datum/surgery_step/close)
+
+/datum/surgery_step/heal
+ name = "repair body"
+ implements = list(TOOL_HEMOSTAT = 100, TOOL_SCREWDRIVER = 65, /obj/item/pen = 55)
+ repeatable = TRUE
+ time = 25
+ var/brutehealing = 0
+ var/burnhealing = 0
+ var/missinghpbonus = 0 //heals an extra point of damager per X missing damage of type (burn damage for burn healing, brute for brute). Smaller Number = More Healing!
+
+/datum/surgery_step/heal/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/woundtype
+ if(brutehealing && burnhealing)
+ woundtype = "wounds"
+ else if(brutehealing)
+ woundtype = "bruises"
+ else //why are you trying to 0,0...?
+ woundtype = "burns"
+ if(istype(surgery,/datum/surgery/healing))
+ var/datum/surgery/healing/the_surgery = surgery
+ if(!the_surgery.antispam)
+ display_results(user, target, "You attempt to patch some of [target]'s [woundtype].",
+ "[user] attempts to patch some of [target]'s [woundtype].",
+ "[user] attempts to patch some of [target]'s [woundtype].")
+
+/datum/surgery_step/heal/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
+ if(..())
+ while((brutehealing && target.getBruteLoss()) || (burnhealing && target.getFireLoss()))
+ if(!..())
+ break
+
+/datum/surgery_step/heal/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ var/umsg = "You succeed in fixing some of [target]'s wounds" //no period, add initial space to "addons"
+ var/tmsg = "[user] fixes some of [target]'s wounds" //see above
+ var/urhealedamt_brute = brutehealing
+ var/urhealedamt_burn = burnhealing
+ if(missinghpbonus)
+ if(target.stat != DEAD)
+ urhealedamt_brute += round((target.getBruteLoss()/ missinghpbonus),0.1)
+ urhealedamt_burn += round((target.getFireLoss()/ missinghpbonus),0.1)
+ else //less healing bonus for the dead since they're expected to have lots of damage to begin with (to make TW into defib not TOO simple)
+ urhealedamt_brute += round((target.getBruteLoss()/ (missinghpbonus*5)),0.1)
+ urhealedamt_burn += round((target.getFireLoss()/ (missinghpbonus*5)),0.1)
+ if(!get_location_accessible(target, target_zone))
+ urhealedamt_brute *= 0.55
+ urhealedamt_burn *= 0.55
+ umsg += " as best as you can while they have clothing on"
+ tmsg += " as best as they can while [target] has clothing on"
+ target.heal_bodypart_damage(urhealedamt_brute,urhealedamt_burn)
+ display_results(user, target, "[umsg].",
+ "[tmsg].",
+ "[tmsg].")
+ if(istype(surgery, /datum/surgery/healing))
+ var/datum/surgery/healing/the_surgery = surgery
+ the_surgery.antispam = TRUE
+ return TRUE
+
+/datum/surgery_step/heal/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You screwed up!",
+ "[user] screws up!",
+ "[user] fixes some of [target]'s wounds.", TRUE)
+ var/urdamageamt_burn = brutehealing * 0.8
+ var/urdamageamt_brute = burnhealing * 0.8
+ if(missinghpbonus)
+ urdamageamt_brute += round((target.getBruteLoss()/ (missinghpbonus*2)),0.1)
+ urdamageamt_burn += round((target.getFireLoss()/ (missinghpbonus*2)),0.1)
+
+ target.take_bodypart_damage(urdamageamt_brute, urdamageamt_burn)
+ return FALSE
+
+/***************************BRUTE***************************/
+/datum/surgery/healing/brute
+ name = "Tend Wounds (Bruises)"
+
+/datum/surgery/healing/brute/basic
+ name = "Tend Wounds (Bruises, Basic)"
+ replaced_by = /datum/surgery/healing/brute/upgraded
+ healing_step_type = /datum/surgery_step/heal/brute/basic
+ desc = "A surgical procedure that provides basic treatment for a patient's brute traumas. Heals slightly more when the patient is severely injured."
+
+/datum/surgery/healing/brute/upgraded
+ name = "Tend Wounds (Bruises, Adv.)"
+ replaced_by = /datum/surgery/healing/brute/upgraded/femto
+ requires_tech = TRUE
+ healing_step_type = /datum/surgery_step/heal/brute/upgraded
+ desc = "A surgical procedure that provides advanced treatment for a patient's brute traumas. Heals more when the patient is severely injured."
+
+/datum/surgery/healing/brute/upgraded/femto
+ name = "Tend Wounds (Bruises, Exp.)"
+ replaced_by = /datum/surgery/healing/combo/upgraded/femto
+ requires_tech = TRUE
+ healing_step_type = /datum/surgery_step/heal/brute/upgraded/femto
+ desc = "A surgical procedure that provides experimental treatment for a patient's brute traumas. Heals considerably more when the patient is severely injured."
+
+/********************BRUTE STEPS********************/
+/datum/surgery_step/heal/brute/basic
+ name = "tend bruises"
+ brutehealing = 5
+ missinghpbonus = 15
+
+/datum/surgery_step/heal/brute/upgraded
+ brutehealing = 5
+ missinghpbonus = 10
+
+/datum/surgery_step/heal/brute/upgraded/femto
+ brutehealing = 5
+ missinghpbonus = 5
+
+/***************************BURN***************************/
+/datum/surgery/healing/burn
+ name = "Tend Wounds (Burn)"
+
+/datum/surgery/healing/burn/basic
+ name = "Tend Wounds (Burn, Basic)"
+ replaced_by = /datum/surgery/healing/burn/upgraded
+ healing_step_type = /datum/surgery_step/heal/burn/basic
+ desc = "A surgical procedure that provides basic treatment for a patient's burns. Heals slightly more when the patient is severely injured."
+
+/datum/surgery/healing/burn/upgraded
+ name = "Tend Wounds (Burn, Adv.)"
+ replaced_by = /datum/surgery/healing/burn/upgraded/femto
+ requires_tech = TRUE
+ healing_step_type = /datum/surgery_step/heal/burn/upgraded
+ desc = "A surgical procedure that provides advanced treatment for a patient's burns. Heals more when the patient is severely injured."
+
+/datum/surgery/healing/burn/upgraded/femto
+ name = "Tend Wounds (Burn, Exp.)"
+ replaced_by = /datum/surgery/healing/combo/upgraded/femto
+ requires_tech = TRUE
+ healing_step_type = /datum/surgery_step/heal/burn/upgraded/femto
+ desc = "A surgical procedure that provides experimental treatment for a patient's burns. Heals considerably more when the patient is severely injured."
+
+/********************BURN STEPS********************/
+/datum/surgery_step/heal/burn/basic
+ name = "tend burn wounds"
+ burnhealing = 5
+ missinghpbonus = 15
+
+/datum/surgery_step/heal/burn/upgraded
+ burnhealing = 5
+ missinghpbonus = 10
+
+/datum/surgery_step/heal/burn/upgraded/femto
+ burnhealing = 5
+ missinghpbonus = 5
+
+/***************************COMBO***************************/
+/datum/surgery/healing/combo
+
+
+/datum/surgery/healing/combo
+ name = "Tend Wounds (Mixture, Basic)"
+ replaced_by = /datum/surgery/healing/combo/upgraded
+ requires_tech = TRUE
+ healing_step_type = /datum/surgery_step/heal/combo
+ desc = "A surgical procedure that provides basic treatment for a patient's burns and brute traumas. Heals slightly more when the patient is severely injured."
+
+/datum/surgery/healing/combo/upgraded
+ name = "Tend Wounds (Mixture, Adv.)"
+ replaced_by = /datum/surgery/healing/combo/upgraded/femto
+ healing_step_type = /datum/surgery_step/heal/combo/upgraded
+ desc = "A surgical procedure that provides advanced treatment for a patient's burns and brute traumas. Heals more when the patient is severely injured."
+
+
+/datum/surgery/healing/combo/upgraded/femto //no real reason to type it like this except consistency, don't worry you're not missing anything
+ name = "Tend Wounds (Mixture, Exp.)"
+ replaced_by = null
+ healing_step_type = /datum/surgery_step/heal/combo/upgraded/femto
+ desc = "A surgical procedure that provides experimental treatment for a patient's burns and brute traumas. Heals considerably more when the patient is severely injured."
+
+/********************COMBO STEPS********************/
+/datum/surgery_step/heal/combo
+ name = "tend physical wounds"
+ brutehealing = 3
+ burnhealing = 3
+ missinghpbonus = 15
+ time = 10
+
+/datum/surgery_step/heal/combo/upgraded
+ brutehealing = 3
+ burnhealing = 3
+ missinghpbonus = 10
+
+/datum/surgery_step/heal/combo/upgraded/femto
+ brutehealing = 1
+ burnhealing = 1
+ missinghpbonus = 2.5
+
+/datum/surgery_step/heal/combo/upgraded/femto/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You screwed up!",
+ "[user] screws up!",
+ "[user] fixes some of [target]'s wounds.", TRUE)
+ target.take_bodypart_damage(5,5)
\ No newline at end of file
diff --git a/code/modules/surgery/helpers.dm b/code/modules/surgery/helpers.dm
index 0419a4c73f..f52bf97147 100644
--- a/code/modules/surgery/helpers.dm
+++ b/code/modules/surgery/helpers.dm
@@ -10,9 +10,6 @@
C = M
affecting = C.get_bodypart(check_zone(selected_zone))
- if(!M.lying && !isslime(M)) //if they're prone or a slime
- return
-
var/datum/surgery/current_surgery
for(var/datum/surgery/S in M.surgeries)
@@ -35,13 +32,18 @@
continue
else if(C && S.requires_bodypart) //mob with no limb in surgery zone when we need a limb
continue
+ if(S.lying_required && !(M.lying))
+ continue
if(!S.can_start(user, M))
continue
- for(var/path in S.species)
+ for(var/path in S.target_mobtypes)
if(istype(M, path))
available_surgeries[S.name] = S
break
+ if(!available_surgeries.len)
+ return
+
var/P = input("Begin which procedure?", "Surgery", null, null) as null|anything in available_surgeries
if(P && user && user.Adjacent(M) && (I in user))
var/datum/surgery/S = available_surgeries[P]
@@ -60,6 +62,8 @@
return
else if(C && S.requires_bodypart)
return
+ if(S.lying_required && !(M.lying))
+ return
if(!S.can_start(user, M))
return
diff --git a/code/modules/surgery/implant_removal.dm b/code/modules/surgery/implant_removal.dm
index c7597b6858..3eb05c91c7 100644
--- a/code/modules/surgery/implant_removal.dm
+++ b/code/modules/surgery/implant_removal.dm
@@ -1,7 +1,7 @@
/datum/surgery/implant_removal
name = "implant removal"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/extract_implant, /datum/surgery_step/close)
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_CHEST)
//extract implant
/datum/surgery_step/extract_implant
diff --git a/code/modules/surgery/limb_augmentation.dm b/code/modules/surgery/limb_augmentation.dm
index e704485da4..b1d8990b48 100644
--- a/code/modules/surgery/limb_augmentation.dm
+++ b/code/modules/surgery/limb_augmentation.dm
@@ -38,7 +38,7 @@
/datum/surgery/augmentation
name = "Augmentation"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/replace, /datum/surgery_step/saw, /datum/surgery_step/replace_limb)
- species = list(/mob/living/carbon/human)
+ target_mobtypes = list(/mob/living/carbon/human)
possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD)
requires_real_bodypart = TRUE
//SURGERY STEP SUCCESSES
diff --git a/code/modules/surgery/lobectomy.dm b/code/modules/surgery/lobectomy.dm
index 7d8b8a53e8..297be175a0 100644
--- a/code/modules/surgery/lobectomy.dm
+++ b/code/modules/surgery/lobectomy.dm
@@ -15,7 +15,7 @@
//lobectomy, removes the most damaged lung lobe with a 95% base success chance
/datum/surgery_step/lobectomy
name = "excise damaged lung node"
- implements = list(/obj/item/scalpel = 95, /obj/item/melee/transforming/energy/sword = 65, /obj/item/kitchen/knife = 45,
+ implements = list(TOOL_SCALPEL = 95, /obj/item/melee/transforming/energy/sword = 65, /obj/item/kitchen/knife = 45,
/obj/item/shard = 35)
time = 42
diff --git a/code/modules/surgery/mechanic_steps.dm b/code/modules/surgery/mechanic_steps.dm
index 23f9c167a0..9366e585c3 100644
--- a/code/modules/surgery/mechanic_steps.dm
+++ b/code/modules/surgery/mechanic_steps.dm
@@ -14,7 +14,7 @@
"[user] begins to unscrew the shell of [target]'s [parse_zone(target_zone)].")
/datum/surgery_step/mechanic_incise/tool_check(mob/user, obj/item/tool)
- if(implement_type == /obj/item && !tool.is_sharp())
+ if(implement_type == /obj/item && !tool.get_sharpness())
return FALSE
return TRUE
//close shell
@@ -33,7 +33,7 @@
"[user] begins to screw the shell of [target]'s [parse_zone(target_zone)].")
/datum/surgery_step/mechanic_close/tool_check(mob/user, obj/item/tool)
- if(implement_type == /obj/item && !tool.is_sharp())
+ if(implement_type == /obj/item && !tool.get_sharpness())
return FALSE
return TRUE
//prepare electronics
diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm
index 42c049edd2..699b3f7f24 100644
--- a/code/modules/surgery/organ_manipulation.dm
+++ b/code/modules/surgery/organ_manipulation.dm
@@ -1,6 +1,6 @@
/datum/surgery/organ_manipulation
- name = "Organ manipulation"
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ name = "organ manipulation"
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD)
requires_real_bodypart = 1
steps = list(
@@ -26,7 +26,7 @@
/datum/surgery/organ_manipulation/alien
name = "Alien organ manipulation"
possible_locs = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD, BODY_ZONE_PRECISE_GROIN, BODY_ZONE_PRECISE_EYES, BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)
- species = list(/mob/living/carbon/alien/humanoid)
+ target_mobtypes = list(/mob/living/carbon/alien/humanoid)
steps = list(
/datum/surgery_step/saw,
/datum/surgery_step/incise,
diff --git a/code/modules/surgery/organic_steps.dm b/code/modules/surgery/organic_steps.dm
index 459a540f26..3b05873a0a 100644
--- a/code/modules/surgery/organic_steps.dm
+++ b/code/modules/surgery/organic_steps.dm
@@ -11,7 +11,7 @@
"[user] begins to make an incision in [target]'s [parse_zone(target_zone)].")
/datum/surgery_step/incise/tool_check(mob/user, obj/item/tool)
- if(implement_type == /obj/item && !tool.is_sharp())
+ if(implement_type == /obj/item && !tool.get_sharpness())
return FALSE
return TRUE
/datum/surgery_step/incise/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
@@ -24,6 +24,16 @@
H.bleed_rate += 3
return TRUE
+/datum/surgery_step/incise/nobleed //silly friendly!
+
+/datum/surgery_step/incise/nobleed/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ display_results(user, target, "You begin to carefully make an incision in [target]'s [parse_zone(target_zone)]...",
+ "[user] begins to carefully make an incision in [target]'s [parse_zone(target_zone)].",
+ "[user] begins to carefully make an incision in [target]'s [parse_zone(target_zone)].")
+
+/datum/surgery_step/incise/nobleed/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+ return TRUE
+
//clamp bleeders
/datum/surgery_step/clamp_bleeders
name = "clamp bleeders"
@@ -69,7 +79,7 @@
/datum/surgery_step/close/tool_check(mob/user, obj/item/tool)
if(implement_type == TOOL_WELDER || implement_type == /obj/item)
- return tool.is_hot()
+ return tool.get_temperature()
return TRUE
/datum/surgery_step/close/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(locate(/datum/surgery_step/saw) in surgery.steps)
diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm
index 7156b8180b..8af52abc47 100644
--- a/code/modules/surgery/organs/augments_chest.dm
+++ b/code/modules/surgery/organs/augments_chest.dm
@@ -129,7 +129,7 @@
var/datum/effect_system/trail_follow/ion/ion_trail
/obj/item/organ/cyberimp/chest/thrusters/Insert(mob/living/carbon/M, special = 0)
- ..()
+ . = ..()
if(!ion_trail)
ion_trail = new
ion_trail.set_up(M)
@@ -151,10 +151,14 @@
on = TRUE
if(allow_thrust(0.01))
ion_trail.start()
+ RegisterSignal(owner, COMSIG_MOVABLE_MOVED, .proc/move_react)
+ owner.add_movespeed_modifier(MOVESPEED_ID_CYBER_THRUSTER, priority=100, multiplicative_slowdown=-2, movetypes=FLOATING, conflict=MOVE_CONFLICT_JETPACK)
if(!silent)
to_chat(owner, "You turn your thrusters set on.")
else
ion_trail.stop()
+ UnregisterSignal(owner, COMSIG_MOVABLE_MOVED)
+ owner.remove_movespeed_modifier(MOVESPEED_ID_CYBER_THRUSTER)
if(!silent)
to_chat(owner, "You turn your thrusters set off.")
on = FALSE
@@ -169,6 +173,9 @@
var/datum/action/A = X
A.UpdateButtonIcon()
+/obj/item/organ/cyberimp/chest/thrusters/proc/move_react()
+ allow_thrust(0.01)
+
/obj/item/organ/cyberimp/chest/thrusters/proc/allow_thrust(num)
if(!on || !owner)
return 0
diff --git a/code/modules/surgery/organs/augments_internal.dm b/code/modules/surgery/organs/augments_internal.dm
index 114b92f10d..f487e61d38 100644
--- a/code/modules/surgery/organs/augments_internal.dm
+++ b/code/modules/surgery/organs/augments_internal.dm
@@ -142,22 +142,3 @@
if(prob(60/severity))
to_chat(owner, "Your breathing tube suddenly closes!")
owner.losebreath += 2
-
-//BOX O' IMPLANTS
-
-/obj/item/storage/box/cyber_implants
- name = "boxed cybernetic implants"
- desc = "A sleek, sturdy box."
- icon_state = "cyber_implants"
- var/list/boxed = list(
- /obj/item/autosurgeon/thermal_eyes,
- /obj/item/autosurgeon/xray_eyes,
- /obj/item/autosurgeon/anti_stun,
- /obj/item/autosurgeon/reviver)
- var/amount = 5
-
-/obj/item/storage/box/cyber_implants/PopulateContents()
- var/implant
- while(contents.len <= amount)
- implant = pick(boxed)
- new implant(src)
diff --git a/code/modules/surgery/organs/autosurgeon.dm b/code/modules/surgery/organs/autosurgeon.dm
index 27bf575627..70959e6253 100644
--- a/code/modules/surgery/organs/autosurgeon.dm
+++ b/code/modules/surgery/organs/autosurgeon.dm
@@ -103,6 +103,26 @@
/obj/item/autosurgeon/anti_drop
starting_organ = /obj/item/organ/cyberimp/brain/anti_drop
+//BOX O' IMPLANTS
+
+/obj/item/storage/box/cyber_implants
+ name = "boxed cybernetic implants"
+ desc = "A sleek, sturdy box."
+ icon_state = "syndiebox"
+ illustration = "cyber_implants"
+ var/list/boxed = list(
+ /obj/item/autosurgeon/thermal_eyes,
+ /obj/item/autosurgeon/xray_eyes,
+ /obj/item/autosurgeon/anti_stun,
+ /obj/item/autosurgeon/reviver)
+ var/amount = 5
+
+/obj/item/storage/box/cyber_implants/PopulateContents()
+ var/implant
+ while(contents.len <= amount)
+ implant = pick(boxed)
+ new implant(src)
+
/obj/item/autosurgeon/penis
desc = "A single use autosurgeon that contains a penis. A screwdriver can be used to remove it, but implants can't be placed back in."
uses = 1
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index 95258c709a..d877af7451 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -227,7 +227,7 @@
terminate_effects()
. = ..()
-/obj/item/organ/eyes/robotic/glow/Remove()
+/obj/item/organ/eyes/robotic/glow/Remove(mob/living/carbon/M, special = FALSE)
terminate_effects()
. = ..()
@@ -338,7 +338,7 @@
/obj/item/organ/eyes/robotic/glow/proc/start_visuals()
if(!islist(eye_lighting))
regenerate_light_effects()
- if((eye_lighting.len < light_beam_distance) || !on_mob)
+ if((LAZYLEN(eye_lighting) < light_beam_distance) || !on_mob)
regenerate_light_effects()
sync_light_effects()
update_visuals()
diff --git a/code/modules/surgery/organs/heart.dm b/code/modules/surgery/organs/heart.dm
index 8e4caab436..82fbf932e9 100644
--- a/code/modules/surgery/organs/heart.dm
+++ b/code/modules/surgery/organs/heart.dm
@@ -57,7 +57,7 @@
/obj/item/organ/heart/prepare_eat()
var/obj/S = ..()
- S.icon_state = "heart-off"
+ S.icon_state = "[icon_base]-off"
return S
/obj/item/organ/heart/on_life()
@@ -90,6 +90,12 @@
owner.set_heartattack(TRUE)
failed = TRUE
+obj/item/organ/heart/slime
+ name = "slime heart"
+ desc = "It seems we've gotten to the slimy core of the matter."
+ icon_state = "heart-s-on"
+ icon_base = "heart-s"
+
/obj/item/organ/heart/cursed
name = "cursed heart"
desc = "A heart that, when inserted, will force you to pump it manually."
@@ -212,6 +218,19 @@ obj/item/organ/heart/cybernetic/upgraded/on_life()
+/obj/item/organ/heart/ipc
+ name = "IPC heart"
+ desc = "An electronic pump that regulates hydraulic functions, they have an auto-restart after EMPs."
+ icon_state = "heart-c"
+ organ_flags = ORGAN_SYNTHETIC
+
+/obj/item/organ/heart/ipc/emp_act()
+ . = ..()
+ if(. & EMP_PROTECT_SELF)
+ return
+ Stop()
+ addtimer(CALLBACK(src, .proc/Restart), 10)
+
/obj/item/organ/heart/freedom
name = "heart of freedom"
desc = "This heart pumps with the passion to give... something freedom."
diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm
index 593614372a..194a10f4c4 100644
--- a/code/modules/surgery/organs/organ_internal.dm
+++ b/code/modules/surgery/organs/organ_internal.dm
@@ -31,7 +31,7 @@
/obj/item/organ/proc/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
if(!iscarbon(M) || owner == M)
- return
+ return FALSE
var/obj/item/organ/replaced = M.getorganslot(slot)
if(replaced)
@@ -53,6 +53,8 @@
A.Grant(M)
STOP_PROCESSING(SSobj, src)
+ return TRUE
+
//Special is for instant replacement like autosurgeons
/obj/item/organ/proc/Remove(mob/living/carbon/M, special = FALSE)
owner = null
@@ -67,6 +69,8 @@
A.Remove(M)
START_PROCESSING(SSobj, src)
+ return TRUE
+
/obj/item/organ/proc/on_find(mob/living/finder)
return
@@ -184,7 +188,7 @@
if(owner)
// The special flag is important, because otherwise mobs can die
// while undergoing transformation into different mobs.
- Remove(owner, special=TRUE)
+ Remove(owner, TRUE)
return ..()
/obj/item/organ/attack(mob/living/carbon/M, mob/user)
diff --git a/code/modules/surgery/organs/tongue.dm b/code/modules/surgery/organs/tongue.dm
index cee20dddee..a9e2b331bb 100644
--- a/code/modules/surgery/organs/tongue.dm
+++ b/code/modules/surgery/organs/tongue.dm
@@ -233,7 +233,6 @@
name = "plasma bone \"tongue\""
desc = "Like animated skeletons, Plasmamen vibrate their teeth in order to produce speech."
icon_state = "tongueplasma"
- maxHealth = "alien"
modifies_speech = FALSE
/obj/item/organ/tongue/robot
diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm
index 009cfce0a5..a555010567 100644
--- a/code/modules/surgery/organs/vocal_cords.dm
+++ b/code/modules/surgery/organs/vocal_cords.dm
@@ -917,7 +917,7 @@
speaktrigger += "[(H.client?.prefs.lewdchem?"You are my whole world and all of my being belongs to you, ":"I cannot think of anything else but aiding your cause, ")] "//Redflags!!
//mood
- GET_COMPONENT_FROM(mood, /datum/component/mood, H)
+ var/datum/component/mood/mood = H.GetComponent(/datum/component/mood)
switch(mood.sanity)
if(SANITY_GREAT to INFINITY)
speaktrigger += "I'm beyond elated!! " //did you mean byond elated? hohoho
diff --git a/code/modules/surgery/prosthetic_replacement.dm b/code/modules/surgery/prosthetic_replacement.dm
index fdceb1fb1f..8efa40a70a 100644
--- a/code/modules/surgery/prosthetic_replacement.dm
+++ b/code/modules/surgery/prosthetic_replacement.dm
@@ -1,7 +1,7 @@
/datum/surgery/prosthetic_replacement
name = "Prosthetic replacement"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/clamp_bleeders, /datum/surgery_step/retract_skin, /datum/surgery_step/add_prosthetic)
- species = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
+ target_mobtypes = list(/mob/living/carbon/human, /mob/living/carbon/monkey)
possible_locs = list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG, BODY_ZONE_HEAD)
requires_bodypart = FALSE //need a missing limb
requires_bodypart_type = 0
diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm
index b013e7f252..a920ea765a 100644
--- a/code/modules/surgery/surgery.dm
+++ b/code/modules/surgery/surgery.dm
@@ -1,155 +1,172 @@
-/datum/surgery
- var/name = "surgery"
- var/desc = "surgery description"
- var/status = 1
- var/list/steps = list() //Steps in a surgery
- var/step_in_progress = 0 //Actively performing a Surgery
- var/can_cancel = 1 //Can cancel this surgery after step 1 with cautery
- var/list/species = list(/mob/living/carbon/human) //Acceptable Species
- var/location = BODY_ZONE_CHEST //Surgery location
- var/requires_bodypart_type = BODYPART_ORGANIC //Prevents you from performing an operation on incorrect limbs. 0 for any limb type
- var/list/possible_locs = list() //Multiple locations
- var/ignore_clothes = 0 //This surgery ignores clothes
- var/mob/living/carbon/target //Operation target mob
- var/obj/item/bodypart/operated_bodypart //Operable body part
- var/requires_bodypart = TRUE //Surgery available only when a bodypart is present, or only when it is missing.
- var/success_multiplier = 0 //Step success propability multiplier
- var/requires_real_bodypart = 0 //Some surgeries don't work on limbs that don't really exist
-
-/datum/surgery/New(surgery_target, surgery_location, surgery_bodypart)
- ..()
- if(surgery_target)
- target = surgery_target
- target.surgeries += src
- if(surgery_location)
- location = surgery_location
- if(surgery_bodypart)
- operated_bodypart = surgery_bodypart
-
-/datum/surgery/Destroy()
- if(target)
- target.surgeries -= src
- target = null
- operated_bodypart = null
- return ..()
-
-
-/datum/surgery/proc/can_start(mob/user, mob/living/carbon/target)
- // if 0 surgery wont show up in list
- // put special restrictions here
- return 1
-
-/datum/surgery/proc/next_step(mob/user, intent)
- if(step_in_progress)
- return 1
-
- var/try_to_fail = FALSE
- if(intent == INTENT_DISARM)
- try_to_fail = TRUE
-
- var/datum/surgery_step/S = get_surgery_step()
- if(S)
- var/obj/item/tool = user.get_active_held_item()
- if(S.try_op(user, target, user.zone_selected, tool, src, try_to_fail))
- return TRUE
- if(iscyborg(user) && user.a_intent != INTENT_HARM) //to save asimov borgs a LOT of heartache
- return TRUE
- if(tool.item_flags & SURGICAL_TOOL) //Just because you used the wrong tool it doesn't mean you meant to whack the patient with it
- to_chat(user, "This step requires a different tool!")
- return TRUE
-
-/datum/surgery/proc/get_surgery_step()
- var/step_type = steps[status]
- return new step_type
-
-/datum/surgery/proc/get_surgery_next_step()
- if(status < steps.len)
- var/step_type = steps[status + 1]
- return new step_type
- else
- return null
-
-/datum/surgery/proc/complete()
- SSblackbox.record_feedback("tally", "surgeries_completed", 1, type)
- qdel(src)
-
-/datum/surgery/proc/get_propability_multiplier()
- var/propability = 0.5
- var/turf/T = get_turf(target)
-
- if(locate(/obj/structure/table/optable, T))
- propability = 1
- else if(locate(/obj/structure/table, T))
- propability = 0.8
- else if(locate(/obj/structure/bed, T))
- propability = 0.7
-
- return propability + success_multiplier
-
-/datum/surgery/advanced
- name = "advanced surgery"
-
-/datum/surgery/advanced/can_start(mob/user, mob/living/carbon/target)
- if(!..())
- return FALSE
- //Abductor scientists need no instructions
- if(isabductor(user))
- var/mob/living/carbon/human/H = user
- var/datum/species/abductor/S = H.dna.species
- if(S.scientist)
- return TRUE
-
- if(iscyborg(user))
- var/mob/living/silicon/robot/R = user
- var/obj/item/surgical_processor/SP = locate() in R.module.modules
- if(!SP)
- return FALSE
- if(type in SP.advanced_surgeries)
- return TRUE
-
- var/turf/T = get_turf(target)
- var/obj/structure/table/optable/table = locate(/obj/structure/table/optable, T)
- if(!table || !table.computer)
- return FALSE
- if(table.computer.stat & (NOPOWER|BROKEN))
- return FALSE
- if(type in table.computer.advanced_surgeries)
- return TRUE
-
-/obj/item/disk/surgery
- name = "Surgery Procedure Disk"
- desc = "A disk that contains advanced surgery procedures, must be loaded into an Operating Console."
- icon_state = "datadisk1"
- materials = list(MAT_METAL=300, MAT_GLASS=100)
- var/list/surgeries
-
-/obj/item/disk/surgery/debug
- name = "Debug Surgery Disk"
- desc = "A disk that contains all existing surgery procedures."
- icon_state = "datadisk1"
- materials = list(MAT_METAL=300, MAT_GLASS=100)
-
-/obj/item/disk/surgery/debug/Initialize()
- . = ..()
- surgeries = subtypesof(/datum/surgery/advanced)
-
-//INFO
-//Check /mob/living/carbon/attackby for how surgery progresses, and also /mob/living/carbon/attack_hand.
-//As of Feb 21 2013 they are in code/modules/mob/living/carbon/carbon.dm, lines 459 and 51 respectively.
-//Other important variables are var/list/surgeries (/mob/living) and var/list/internal_organs (/mob/living/carbon)
-// var/list/bodyparts (/mob/living/carbon/human) is the LIMBS of a Mob.
-//Surgical procedures are initiated by attempt_initiate_surgery(), which is called by surgical drapes and bedsheets.
-
-
-//TODO
-//specific steps for some surgeries (fluff text)
-//more interesting failure options
-//randomised complications
-//more surgeries!
-//add a probability modifier for the state of the surgeon- health, twitching, etc. blindness, god forbid.
-//helper for converting a zone_sel.selecting to body part (for damage)
-
-
-//RESOLVED ISSUES //"Todo" jobs that have been completed
-//combine hands/feet into the arms - Hands/feet were removed - RR
-//surgeries (not steps) that can be initiated on any body part (corresponding with damage locations) - Call this one done, see possible_locs var - c0
+/datum/surgery
+ var/name = "surgery"
+ var/desc = "surgery description"
+ var/status = 1
+ var/list/steps = list() //Steps in a surgery
+ var/step_in_progress = 0 //Actively performing a Surgery
+ var/can_cancel = 1 //Can cancel this surgery after step 1 with cautery
+ var/list/target_mobtypes = list(/mob/living/carbon/human) //Acceptable Species
+ var/location = BODY_ZONE_CHEST //Surgery location
+ var/requires_bodypart_type = BODYPART_ORGANIC //Prevents you from performing an operation on incorrect limbs. 0 for any limb type
+ var/list/possible_locs = list() //Multiple locations
+ var/ignore_clothes = 0 //This surgery ignores clothes
+ var/mob/living/carbon/target //Operation target mob
+ var/obj/item/bodypart/operated_bodypart //Operable body part
+ var/requires_bodypart = TRUE //Surgery available only when a bodypart is present, or only when it is missing.
+ var/success_multiplier = 0 //Step success propability multiplier
+ var/requires_real_bodypart = 0 //Some surgeries don't work on limbs that don't really exist
+ var/lying_required = TRUE //Does the vicitm needs to be lying down.
+ var/requires_tech = FALSE
+ var/replaced_by
+
+/datum/surgery/New(surgery_target, surgery_location, surgery_bodypart)
+ ..()
+ if(surgery_target)
+ target = surgery_target
+ target.surgeries += src
+ if(surgery_location)
+ location = surgery_location
+ if(surgery_bodypart)
+ operated_bodypart = surgery_bodypart
+
+/datum/surgery/Destroy()
+ if(target)
+ target.surgeries -= src
+ target = null
+ operated_bodypart = null
+ return ..()
+
+
+/datum/surgery/proc/can_start(mob/user, mob/living/patient) //FALSE to not show in list
+ . = TRUE
+ if(replaced_by == /datum/surgery)
+ return FALSE
+
+ if(HAS_TRAIT(user, TRAIT_SURGEON) || HAS_TRAIT(user.mind, TRAIT_SURGEON))
+ if(replaced_by)
+ return FALSE
+ else
+ return TRUE
+
+ if(!requires_tech && !replaced_by)
+ return TRUE
+ // True surgeons (like abductor scientists) need no instructions
+
+ if(requires_tech)
+ . = FALSE
+
+ if(iscyborg(user))
+ var/mob/living/silicon/robot/R = user
+ var/obj/item/surgical_processor/SP = locate() in R.module.modules
+ if(SP)
+ if (replaced_by in SP.advanced_surgeries)
+ return .
+ if(type in SP.advanced_surgeries)
+ return TRUE
+
+
+ var/turf/T = get_turf(patient)
+ var/obj/structure/table/optable/table = locate(/obj/structure/table/optable, T)
+ if(table)
+ if(!table.computer)
+ return .
+ if(table.computer.stat & (NOPOWER|BROKEN))
+ return .
+ if(replaced_by in table.computer.advanced_surgeries)
+ return FALSE
+ if(type in table.computer.advanced_surgeries)
+ return TRUE
+
+/datum/surgery/proc/next_step(mob/user, intent)
+ if(step_in_progress)
+ return 1
+
+ var/try_to_fail = FALSE
+ if(intent == INTENT_DISARM)
+ try_to_fail = TRUE
+
+ var/datum/surgery_step/S = get_surgery_step()
+ if(S)
+ var/obj/item/tool = user.get_active_held_item()
+ if(S.try_op(user, target, user.zone_selected, tool, src, try_to_fail))
+ return TRUE
+ if(iscyborg(user) && user.a_intent != INTENT_HARM) //to save asimov borgs a LOT of heartache
+ return TRUE
+ if(tool && tool.item_flags & SURGICAL_TOOL) //Just because you used the wrong tool it doesn't mean you meant to whack the patient with it
+ to_chat(user, "This step requires a different tool!")
+ return TRUE
+
+/datum/surgery/proc/get_surgery_step()
+ var/step_type = steps[status]
+ return new step_type
+
+/datum/surgery/proc/get_surgery_next_step()
+ if(status < steps.len)
+ var/step_type = steps[status + 1]
+ return new step_type
+ else
+ return null
+
+/datum/surgery/proc/complete()
+ SSblackbox.record_feedback("tally", "surgeries_completed", 1, type)
+ qdel(src)
+
+/datum/surgery/proc/get_propability_multiplier()
+ var/propability = 0.5
+ var/turf/T = get_turf(target)
+
+ if(locate(/obj/structure/table/optable, T))
+ propability = 1
+ else if(locate(/obj/structure/table, T))
+ propability = 0.8
+ else if(locate(/obj/structure/bed, T))
+ propability = 0.7
+
+ return propability + success_multiplier
+
+/datum/surgery/advanced
+ name = "advanced surgery"
+ requires_tech = TRUE
+
+/obj/item/disk/surgery
+ name = "Surgery Procedure Disk"
+ desc = "A disk that contains advanced surgery procedures, must be loaded into an Operating Console."
+ icon_state = "datadisk1"
+ materials = list(MAT_METAL=300, MAT_GLASS=100)
+ var/list/surgeries
+
+/obj/item/disk/surgery/debug
+ name = "Debug Surgery Disk"
+ desc = "A disk that contains all existing surgery procedures."
+ icon_state = "datadisk1"
+ materials = list(MAT_METAL=300, MAT_GLASS=100)
+
+/obj/item/disk/surgery/debug/Initialize()
+ . = ..()
+ surgeries = list()
+ var/list/req_tech_surgeries = subtypesof(/datum/surgery)
+ for(var/i in req_tech_surgeries)
+ var/datum/surgery/beep = i
+ if(initial(beep.requires_tech))
+ surgeries += beep
+
+//INFO
+//Check /mob/living/carbon/attackby for how surgery progresses, and also /mob/living/carbon/attack_hand.
+//As of Feb 21 2013 they are in code/modules/mob/living/carbon/carbon.dm, lines 459 and 51 respectively.
+//Other important variables are var/list/surgeries (/mob/living) and var/list/internal_organs (/mob/living/carbon)
+// var/list/bodyparts (/mob/living/carbon/human) is the LIMBS of a Mob.
+//Surgical procedures are initiated by attempt_initiate_surgery(), which is called by surgical drapes and bedsheets.
+
+
+//TODO
+//specific steps for some surgeries (fluff text)
+//more interesting failure options
+//randomised complications
+//more surgeries!
+//add a probability modifier for the state of the surgeon- health, twitching, etc. blindness, god forbid.
+//helper for converting a zone_sel.selecting to body part (for damage)
+
+
+//RESOLVED ISSUES //"Todo" jobs that have been completed
+//combine hands/feet into the arms - Hands/feet were removed - RR
+//surgeries (not steps) that can be initiated on any body part (corresponding with damage locations) - Call this one done, see possible_locs var - c0
\ No newline at end of file
diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm
index c5a944fbb2..71f813a5b5 100644
--- a/code/modules/surgery/surgery_step.dm
+++ b/code/modules/surgery/surgery_step.dm
@@ -8,7 +8,9 @@
var/repeatable = FALSE //can this step be repeated? Make shure it isn't last step, or it used in surgery with `can_cancel = 1`. Or surgion will be stuck in the loop
var/list/chems_needed = list() //list of chems needed to complete the step. Even on success, the step will have no effect if there aren't the chems required in the mob.
var/require_all_chems = TRUE //any on the list or all on the list?
-/datum/surgery_step/proc/try_op(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
+ var/silicons_obey_prob = FALSE
+
+/datum/surgery_step/proc/try_op(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
var/success = FALSE
if(accept_hand)
if(!tool)
@@ -46,7 +48,8 @@
else
surgery.status--
return FALSE
-/datum/surgery_step/proc/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
+
+/datum/surgery_step/proc/initiate(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE)
surgery.step_in_progress = TRUE
var/speed_mod = 1
var/advance = FALSE
@@ -60,7 +63,8 @@
if(implement_type) //this means it isn't a require hand or any item step.
prob_chance = implements[implement_type]
prob_chance *= surgery.get_propability_multiplier()
- if((prob(prob_chance) || iscyborg(user)) && chem_check(target) && !try_to_fail)
+
+ if((prob(prob_chance) || (iscyborg(user) && !silicons_obey_prob)) && chem_check(target) && !try_to_fail)
if(success(user, target, target_zone, tool, surgery))
advance = TRUE
else
@@ -73,19 +77,18 @@
surgery.step_in_progress = FALSE
return advance
-
-/datum/surgery_step/proc/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+/datum/surgery_step/proc/preop(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, "You begin to perform surgery on [target]...",
"[user] begins to perform surgery on [target].",
"[user] begins to perform surgery on [target].")
-/datum/surgery_step/proc/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+/datum/surgery_step/proc/success(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, "You succeed.",
"[user] succeeds!",
"[user] finishes.")
return TRUE
-/datum/surgery_step/proc/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
+/datum/surgery_step/proc/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery)
display_results(user, target, "You screw up!",
"[user] screws up!",
"[user] finishes.", TRUE) //By default the patient will notice if the wrong thing has been cut
@@ -93,7 +96,8 @@
/datum/surgery_step/proc/tool_check(mob/user, obj/item/tool)
return TRUE
-/datum/surgery_step/proc/chem_check(mob/living/carbon/target)
+
+/datum/surgery_step/proc/chem_check(mob/living/target)
if(!LAZYLEN(chems_needed))
return TRUE
if(require_all_chems)
diff --git a/code/modules/tooltip/tooltip.html b/code/modules/tooltip/tooltip.html
index 3e2f26a09f..3cab68da6a 100644
--- a/code/modules/tooltip/tooltip.html
+++ b/code/modules/tooltip/tooltip.html
@@ -122,8 +122,8 @@
//Get the real icon size according to the client view
var mapWidth = map['view-size'].x,
mapHeight = map['view-size'].y,
- tilesShown = tooltip.client_view_w
- realIconSize = mapWidth / tilesShown,
+ tilesShown = tooltip.client_view_h
+ realIconSize = mapHeight / tilesShown,
resizeRatio = realIconSize / tooltip.tileSize,
//Calculate letterboxing offsets
leftOffset = (map.size.x - mapWidth) / 2,
diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm
index 8da5d7c113..642052026b 100644
--- a/code/modules/unit_tests/_unit_tests.dm
+++ b/code/modules/unit_tests/_unit_tests.dm
@@ -2,6 +2,7 @@
//Keep this sorted alphabetically
#ifdef UNIT_TESTS
+#include "component_tests.dm"
#include "reagent_id_typos.dm"
#include "reagent_recipe_collisions.dm"
#include "spawn_humans.dm"
diff --git a/code/modules/unit_tests/component_tests.dm b/code/modules/unit_tests/component_tests.dm
new file mode 100644
index 0000000000..409d7f4322
--- /dev/null
+++ b/code/modules/unit_tests/component_tests.dm
@@ -0,0 +1,12 @@
+/datum/unit_test/component_duping/Run()
+ var/list/bad_dms = list()
+ var/list/bad_dts = list()
+ for(var/t in typesof(/datum/component))
+ var/datum/component/comp = t
+ if(!isnum(initial(comp.dupe_mode)))
+ bad_dms += t
+ var/dupe_type = initial(comp.dupe_type)
+ if(dupe_type && !ispath(dupe_type))
+ bad_dts += t
+ if(length(bad_dms) || length(bad_dts))
+ Fail("Components with invalid dupe modes: ([bad_dms.Join(",")]) ||| Components with invalid dupe types: ([bad_dts.Join(",")])")
\ No newline at end of file
diff --git a/code/modules/uplink/uplink_devices.dm b/code/modules/uplink/uplink_devices.dm
index b008682745..5c47a2d342 100644
--- a/code/modules/uplink/uplink_devices.dm
+++ b/code/modules/uplink/uplink_devices.dm
@@ -25,18 +25,18 @@
/obj/item/uplink/nuclear/Initialize()
. = ..()
- GET_COMPONENT(hidden_uplink, /datum/component/uplink)
+ var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
/obj/item/uplink/nuclear_restricted/Initialize()
. = ..()
- GET_COMPONENT(hidden_uplink, /datum/component/uplink)
+ var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.allow_restricted = FALSE
hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
/obj/item/uplink/clownop/Initialize()
. = ..()
- GET_COMPONENT(hidden_uplink, /datum/component/uplink)
+ var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.set_gamemode(/datum/game_mode/nuclear/clown_ops)
/obj/item/uplink/old
@@ -45,7 +45,7 @@
/obj/item/uplink/old/Initialize(mapload, owner, tc_amount = 10)
. = ..()
- GET_COMPONENT(hidden_uplink, /datum/component/uplink)
+ var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.name = "dusty radio"
// Multitool uplink
diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm
index 61af0eaf78..280740688e 100644
--- a/code/modules/uplink/uplink_items.dm
+++ b/code/modules/uplink/uplink_items.dm
@@ -1711,12 +1711,20 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes
cost = 14 //High cost because of the potential for extreme damage in the hands of a skilled gas masked scientist.
restricted_roles = list("Research Director", "Scientist")
+/datum/uplink_item/role_restricted/alientech
+ name = "Alien Research Disk"
+ desc = "A technology disk holding a terabyte of highly confidential abductor technology. \
+ Simply insert into research console of choice and import the files from the disk. Because of its foreign nature, it may require multiple uploads to work properly."
+ item = /obj/item/disk/tech_disk/abductor
+ cost = 12
+ restricted_roles = list("Research Director", "Scientist", "Roboticist")
+
/datum/uplink_item/role_restricted/brainwash_disk
name = "Brainwashing Surgery Program"
desc = "A disk containing the procedure to perform a brainwashing surgery, allowing you to implant an objective onto a target. \
Insert into an Operating Console to enable the procedure."
item = /obj/item/disk/surgery/brainwashing
- restricted_roles = list("Medical Doctor")
+ restricted_roles = list("Medical Doctor", "Roboticist")
cost = 3
/datum/uplink_item/role_restricted/clown_bomb
@@ -1912,6 +1920,13 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes
Radio headset does not include encryption key. No gun included."
item = /obj/item/storage/box/syndie_kit/centcom_costume
+/datum/uplink_item/badass/claymore
+ name = "Claymore"
+ cost = 8
+ player_minimum = 25
+ desc = "A claymore. We don't know why you'd do this."
+ item = /obj/item/claymore
+
/datum/uplink_item/badass/costumes/clown
name = "Clown Costume"
desc = "Nothing is more terrifying than clowns with fully automatic weaponry."
diff --git a/code/modules/vehicles/secway.dm b/code/modules/vehicles/secway.dm
index 33f0d794c8..114a6373f4 100644
--- a/code/modules/vehicles/secway.dm
+++ b/code/modules/vehicles/secway.dm
@@ -4,9 +4,59 @@
desc = "A brave security cyborg gave its life to help you look like a complete tool."
icon_state = "secway"
key_type = /obj/item/key/security
+ var/chargemax = 150
+ var/chargerate = 0.35
+ var/charge = 150
+ var/chargespeed = 1
+ var/normalspeed = 2
+ var/last_tick = 0
+ var/list/progressbars_by_rider = list()
/obj/vehicle/ridden/secway/Initialize()
. = ..()
var/datum/component/riding/D = LoadComponent(/datum/component/riding)
D.vehicle_move_delay = 1
D.set_riding_offsets(RIDING_OFFSET_ALL, list(TEXT_NORTH = list(0, 4), TEXT_SOUTH = list(0, 4), TEXT_EAST = list(0, 4), TEXT_WEST = list( 0, 4)))
+ START_PROCESSING(SSfastprocess, src)
+
+/obj/vehicle/ridden/secway/process()
+ var/diff = world.time - last_tick
+ var/regen = chargerate * diff
+ charge = CLAMP(charge + regen, 0, chargemax)
+ last_tick = world.time
+
+/obj/vehicle/ridden/secway/relaymove(mob/user, direction)
+ var/new_speed = normalspeed
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ if(H.sprinting && charge)
+ charge--
+ new_speed = chargespeed
+ var/datum/component/riding/D = GetComponent(/datum/component/riding)
+ D.vehicle_move_delay = new_speed
+ for(var/i in progressbars_by_rider)
+ var/datum/progressbar/B = progressbars_by_rider[i]
+ B.update(charge)
+ return ..()
+
+/obj/vehicle/ridden/secway/buckle_mob(mob/living/M, force, check_loc)
+ . = ..(M, force, check_loc)
+ if(.)
+ if(progressbars_by_rider[M])
+ qdel(progressbars_by_rider[M])
+ var/datum/progressbar/D = new(M, chargemax, src)
+ D.update(charge)
+ progressbars_by_rider[M] = D
+
+/obj/vehicle/ridden/secway/unbuckle_mob(mob/living/M, force)
+ . = ..(M, force)
+ if(.)
+ qdel(progressbars_by_rider[M])
+ progressbars_by_rider -= M
+
+/obj/vehicle/ridden/secway/Destroy()
+ for(var/i in progressbars_by_rider)
+ qdel(progressbars_by_rider[i])
+ progressbars_by_rider.Cut()
+ STOP_PROCESSING(SSfastprocess, src)
+ return ..()
diff --git a/code/modules/vending/magivend.dm b/code/modules/vending/magivend.dm
index b414638be9..30c6ae6161 100644
--- a/code/modules/vending/magivend.dm
+++ b/code/modules/vending/magivend.dm
@@ -4,7 +4,7 @@
icon_state = "MagiVend"
product_slogans = "Sling spells the proper way with MagiVend!;Be your own Houdini! Use MagiVend!"
vend_reply = "Have an enchanted evening!"
- product_ads = "FJKLFJSD;AJKFLBJAKL;1234 LOONIES LOL!;>MFW;Kill them fuckers!;GET DAT FUKKEN DISK;HONK!;EI NATH;Destroy the station!;Admin conspiracies since forever!;Space-time bending hardware!"
+ product_ads = "EI NATH;Destroy the station!;Admin conspiracies since forever!;Space-time bending hardware!;Now-magic proofing venders!"
products = list(/obj/item/clothing/head/wizard = 1,
/obj/item/clothing/suit/wizrobe = 1,
/obj/item/clothing/head/wizard/red = 1,
@@ -14,5 +14,5 @@
/obj/item/clothing/shoes/sandal/magic = 1,
/obj/item/staff = 2)
contraband = list(/obj/item/reagent_containers/glass/bottle/wizarditis = 1) //No one can get to the machine to hack it anyways; for the lulz - Microwave
- armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
+ armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50, "magic" = 100)
resistance_flags = FIRE_PROOF
diff --git a/code/modules/vending/wardrobes.dm b/code/modules/vending/wardrobes.dm
index fbc7713f25..e64435accc 100644
--- a/code/modules/vending/wardrobes.dm
+++ b/code/modules/vending/wardrobes.dm
@@ -63,7 +63,7 @@
product_ads = "Guaranteed to protect your feet from industrial accidents!;Afraid of radiation? Then wear yellow!"
vend_reply = "Thank you for using the EngiDrobe!"
products = list(/obj/item/clothing/accessory/pocketprotector = 5,
- /obj/item/storage/backpack/duffelbag/engineering = 2,
+ /obj/item/storage/backpack/duffelbag/engineering = 3,
/obj/item/storage/backpack/industrial = 3,
/obj/item/storage/backpack/satchel/eng = 3,
/obj/item/clothing/suit/hooded/wintercoat/engineering = 3,
@@ -71,7 +71,8 @@
/obj/item/clothing/under/rank/engineer/skirt = 5,
/obj/item/clothing/suit/hazardvest = 5,
/obj/item/clothing/shoes/workboots = 5,
- /obj/item/clothing/head/hardhat = 5)
+ /obj/item/clothing/head/hardhat = 5,
+ /obj/item/clothing/head/hardhat/weldhat = 3)
refill_canister = /obj/item/vending_refill/wardrobe/engi_wardrobe
/obj/item/vending_refill/wardrobe/engi_wardrobe
@@ -87,7 +88,8 @@
/obj/item/storage/backpack/duffelbag/engineering = 3,
/obj/item/storage/backpack/satchel/eng = 3,
/obj/item/storage/backpack/industrial = 3,
- /obj/item/clothing/suit/hooded/wintercoat/engineering/atmos = 5,
+ /obj/item/clothing/head/hardhat/weldhat/dblue = 3,
+ /obj/item/clothing/suit/hooded/wintercoat/engineering/atmos = 3,
/obj/item/clothing/under/rank/atmospheric_technician = 5,
/obj/item/clothing/under/rank/atmospheric_technician/skirt = 5,
/obj/item/clothing/shoes/sneakers/black = 5)
diff --git a/modular_citadel/code/modules/vore/eating/belly_dat_vr.dm b/code/modules/vore/eating/belly_dat_vr.dm
similarity index 100%
rename from modular_citadel/code/modules/vore/eating/belly_dat_vr.dm
rename to code/modules/vore/eating/belly_dat_vr.dm
diff --git a/modular_citadel/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj.dm
similarity index 78%
rename from modular_citadel/code/modules/vore/eating/belly_obj_vr.dm
rename to code/modules/vore/eating/belly_obj.dm
index 1ad29c1af3..5c2b45dace 100644
--- a/modular_citadel/code/modules/vore/eating/belly_obj_vr.dm
+++ b/code/modules/vore/eating/belly_obj.dm
@@ -38,6 +38,7 @@
var/swallow_time = 10 SECONDS // for mob transfering automation
var/vore_capacity = 1 // simple animal nom capacity
var/is_wet = TRUE // Is this belly inside slimy parts?
+ var/wet_loop = TRUE // Does this belly have a slimy internal loop?
//I don't think we've ever altered these lists. making them static until someone actually overrides them somewhere.
var/tmp/static/list/digest_modes = list(DM_HOLD,DM_DIGEST,DM_HEAL,DM_NOISY,DM_ABSORB,DM_UNABSORB) // Possible digest modes
@@ -138,13 +139,17 @@
"digest_messages_prey",
"examine_messages",
"emote_lists",
- "is_wet"
+ "is_wet",
+ "wet_loop"
)
//ommitted list
// "shrink_grow_size",
-/obj/belly/New(var/newloc)
- . = ..(newloc)
+/obj/belly/Initialize()
+ . = ..()
+ take_ownership(src.loc)
+
+/obj/belly/proc/take_ownership(var/newloc)
//If not, we're probably just in a prefs list or something.
if(isliving(newloc))
owner = loc
@@ -152,13 +157,11 @@
SSbellies.belly_list += src
/obj/belly/Destroy()
- if(owner)
- Remove(owner)
- return ..()
-
-/obj/belly/proc/Remove(mob/living/owner)
- owner.vore_organs -= src
- owner = null
+ SSbellies.belly_list -= src
+ if(owner?.vore_organs)
+ owner.vore_organs -= src
+ owner = null
+ . = ..()
// Called whenever an atom enters this belly
/obj/belly/Entered(var/atom/movable/thing,var/atom/OldLoc)
@@ -169,13 +172,22 @@
to_chat(owner,"[thing] slides into your [lowertext(name)].")
//Sound w/ antispam flag setting
- if(is_wet && (world.time > recent_sound))
- var/turf/source = get_turf(owner)
- var/sound/eating = GLOB.vore_sounds[vore_sound]
- for(var/mob/living/M in get_hearers_in_view(3, source))
- if(M.client && M.client.prefs.cit_toggles & EATING_NOISES)
- SEND_SOUND(M, eating)
- recent_sound = (world.time + 20 SECONDS)
+ if(vore_sound && !recent_sound)
+ if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
+ LAZYCLEARLIST(hearing_mobs)
+ for(var/mob/living/H in get_hearers_in_view(3, owner))
+ if(!H.client || !(H.client.prefs.cit_toggles & EATING_NOISES))
+ continue
+ LAZYADD(hearing_mobs, H)
+ last_hearcheck = world.time
+ for(var/mob/living/H in hearing_mobs)
+ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
+ var/sound/eating = GLOB.pred_vore_sounds[vore_sound]
+ SEND_SOUND(H,eating)
+ else if(H && H in contents && H.client)
+ var/sound/eating = GLOB.prey_vore_sounds[vore_sound]
+ SEND_SOUND(H,eating)
+ recent_sound = TRUE
//Messages if it's a mob
if(isliving(thing))
@@ -187,7 +199,7 @@
// If that location is another mob, contents are transferred into whichever of its bellies the owning mob is in.
// Returns the number of mobs so released.
/obj/belly/proc/release_all_contents(var/include_absorbed = FALSE, var/silent = FALSE)
- var/atom/destination = drop_location()
+// var/atom/destination = drop_location()
//Don't bother if we don't have contents
if(!contents.len)
return FALSE
@@ -207,22 +219,30 @@
SEND_SIGNAL(L, COMSIG_CLEAR_MOOD_EVENT, "fedprey", /datum/mood_event/fedprey)
SEND_SIGNAL(OW, COMSIG_ADD_MOOD_EVENT, "emptypred", /datum/mood_event/emptypred)
SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "emptyprey", /datum/mood_event/emptyprey)
- AM.forceMove(destination) // Move the belly contents into the same location as belly's owner.
- count++
- for(var/mob/living/M in get_hearers_in_view(2, get_turf(owner)))
- if(M.client && (M.client.prefs.cit_toggles & EATING_NOISES))
- var/sound/releasement = GLOB.release_sounds[release_sound]
- SEND_SOUND(M, releasement)
+ count += release_specific_contents(AM, silent = TRUE)
//Clean up our own business
items_preserved.Cut()
- if(isanimal(owner))
- owner.update_icons()
+ owner.update_icons()
if(!silent)
+ if(release_sound && !recent_sound)
+ if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
+ LAZYCLEARLIST(hearing_mobs)
+ for(var/mob/living/H in get_hearers_in_view(3, owner))
+ if(!H.client || !(H.client.prefs.cit_toggles & EATING_NOISES))
+ continue
+ LAZYADD(hearing_mobs, H)
+ last_hearcheck = world.time
+ for(var/mob/living/H in hearing_mobs)
+ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
+ var/sound/releasement = GLOB.pred_release_sounds[release_sound]
+ SEND_SOUND(H,releasement)
+ else if(H && H in contents && H.client)
+ var/sound/releasement = GLOB.prey_release_sounds[release_sound]
+ SEND_SOUND(H,releasement)
+ recent_sound = TRUE
owner.visible_message("[owner] expels everything from their [lowertext(name)]!")
- items_preserved.Cut()
- owner.update_icons()
return count
@@ -235,16 +255,13 @@
M.forceMove(drop_location()) // Move the belly contents into the same location as belly's owner.
items_preserved -= M
- if(!silent)
- for(var/mob/living/H in get_hearers_in_view(2, get_turf(owner)))
- if(H.client && (H.client.prefs.cit_toggles & EATING_NOISES))
- var/sound/releasement = GLOB.release_sounds[release_sound]
- SEND_SOUND(H, releasement)
+
if(istype(M,/mob/living))
var/mob/living/ML = M
var/mob/living/OW = owner
- ML.stop_sound_channel(CHANNEL_PREYLOOP)
+ if(ML.client)
+ ML.stop_sound_channel(CHANNEL_PREYLOOP) //Stop the internal loop, it'll restart if the isbelly check on next tick anyway
ML.cure_blind("belly_[REF(src)]")
SEND_SIGNAL(OW, COMSIG_CLEAR_MOOD_EVENT, "fedpred", /datum/mood_event/fedpred)
SEND_SIGNAL(ML, COMSIG_CLEAR_MOOD_EVENT, "fedprey", /datum/mood_event/fedprey)
@@ -263,12 +280,27 @@
Pred.reagents.trans_to(Prey, Pred.reagents.total_volume / absorbed_count)
//Clean up our own business
- if(isanimal(owner))
- owner.update_icons()
+ owner.update_icons()
if(!silent)
+ if(release_sound && !recent_sound)
+ if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
+ LAZYCLEARLIST(hearing_mobs)
+ for(var/mob/living/H in get_hearers_in_view(3, owner))
+ if(!H.client || !(H.client.prefs.cit_toggles & EATING_NOISES))
+ continue
+ LAZYADD(hearing_mobs, H)
+ last_hearcheck = world.time
+ for(var/mob/living/H in hearing_mobs)
+ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
+ var/sound/releasement = GLOB.pred_release_sounds[release_sound]
+ SEND_SOUND(H,releasement)
+ else if(H && H in contents && H.client)
+ var/sound/releasement = GLOB.prey_release_sounds[release_sound]
+ SEND_SOUND(H,releasement)
+ recent_sound = TRUE
owner.visible_message("[owner] expels [M] from their [lowertext(name)]!")
- owner.update_icons()
+
return TRUE
// Actually perform the mechanics of devouring the tasty prey.
@@ -312,15 +344,26 @@
/obj/belly/proc/transfer_contents(var/atom/movable/content, var/obj/belly/target, silent = FALSE)
if(!(content in src) || !istype(target))
return
+ content.forceMove(target)
for(var/mob/living/M in contents)
M.cure_blind("belly_[REF(src)]")
- target.nom_mob(content, target.owner)
- if(!silent)
- var/turf/source = get_turf(owner)
- var/sound/eating = GLOB.vore_sounds[vore_sound]
- for(var/mob/living/M in get_hearers_in_view(3, source))
- if(M.client && M.client.prefs.cit_toggles & EATING_NOISES)
- SEND_SOUND(M, eating)
+// target.nom_mob(content, target.owner)
+ if(vore_sound && !recent_sound && !silent)
+ if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
+ LAZYCLEARLIST(hearing_mobs)
+ for(var/mob/living/H in get_hearers_in_view(3, owner))
+ if(!H.client || !(H.client.prefs.cit_toggles & EATING_NOISES))
+ continue
+ LAZYADD(hearing_mobs, H)
+ last_hearcheck = world.time
+ for(var/mob/living/H in hearing_mobs)
+ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
+ var/sound/eating = GLOB.pred_vore_sounds[vore_sound]
+ SEND_SOUND(H,eating)
+ else if(H && H in contents && H.client)
+ var/sound/eating = GLOB.prey_vore_sounds[vore_sound]
+ SEND_SOUND(H,eating)
+ recent_sound = TRUE
owner.updateVRPanel()
for(var/mob/living/M in contents)
@@ -424,9 +467,12 @@
if(!M.dropItemToGround(W))
qdel(W)
+ //Incase they have the loop going, let's double check to stop it.
+ M.stop_sound_channel(CHANNEL_PREYLOOP)
+
// Delete the digested mob
qdel(M)
- M.stop_sound_channel(CHANNEL_PREYLOOP)
+
//Update owner
owner.updateVRPanel()
@@ -470,7 +516,7 @@
/obj/belly/drop_location()
//Should be the case 99.99% of the time
if(owner)
- return owner.loc
+ return owner.drop_location()
//Sketchy fallback for safety, put them somewhere safe.
else if(ismob(src))
testing("[src] (\ref[src]) doesn't have an owner, and dropped someone at a latespawn point!")
@@ -525,24 +571,31 @@
struggle_outer_message = "" + struggle_outer_message + ""
struggle_user_message = "" + struggle_user_message + ""
- var/turf/source = get_turf(owner)
- var/sound/struggle_snuggle = sound(get_sfx("struggle_sound"))
+ var/sound/pred_struggle_snuggle = sound(get_sfx("struggle_sound"))
+ var/sound/prey_struggle_snuggle = sound(get_sfx("prey_struggle"))
var/sound/struggle_rustle = sound(get_sfx("rustle"))
+ LAZYCLEARLIST(hearing_mobs)
+ for(var/mob/living/H in get_hearers_in_view(3, owner))
+ if(!H.client || !(H.client.prefs.cit_toggles & EATING_NOISES))
+ continue
+ LAZYADD(hearing_mobs, H)
+
if(is_wet)
- for(var/mob/living/M in get_hearers_in_view(3, source))
- if(M.client && M.client.prefs.cit_toggles & EATING_NOISES)
- SEND_SOUND(M, struggle_snuggle)
+ for(var/mob/living/H in hearing_mobs)
+ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
+ SEND_SOUND(H,pred_struggle_snuggle)
+ else if(H && H in contents && H.client)
+ SEND_SOUND(H,prey_struggle_snuggle)
else
- for(var/mob/living/M in get_hearers_in_view(3, source))
- if(M.client && M.client.prefs.cit_toggles & EATING_NOISES)
- SEND_SOUND(M, struggle_rustle)
+ for(var/mob/living/H in hearing_mobs)
+ if(H && H.client)
+ SEND_SOUND(H, struggle_rustle)
- var/list/watching = hearers(3, owner)
- for(var/mob/living/M in watching)
- if(M.client && (M.client.prefs.cit_toggles & EATING_NOISES)) //Might as well censor the normies here too.
- M.show_message(struggle_outer_message, 1) // visible
+ for(var/mob/living/H in hearing_mobs)
+ if(H && H.client && (isturf(H.loc)))
+ H.show_message(struggle_outer_message, 1) // visible
to_chat(R,struggle_user_message)
@@ -551,8 +604,10 @@
to_chat(R,"You start to climb out of \the [lowertext(name)].")
to_chat(owner,"Someone is attempting to climb out of your [lowertext(name)]!")
if(do_after(R, escapetime))
- if((owner.stat || escapable) && (R.loc == src)) //Can still escape?
+ if((escapable) && (R.loc == src)) //Can still escape?
release_specific_contents(R)
+ to_chat(R,"You climb out of \the [lowertext(name)].")
+ to_chat(owner,"[R] climbs out of your [lowertext(name)]!")
return
else if(R.loc != src) //Aren't even in the belly. Quietly fail.
return
@@ -560,41 +615,41 @@
to_chat(R,"Your attempt to escape [lowertext(name)] has failed!")
to_chat(owner,"The attempt to escape from your [lowertext(name)] has failed!")
return
- else if(prob(transferchance) && transferlocation) //Next, let's have it see if they end up getting into an even bigger mess then when they started.
- var/obj/belly/dest_belly
- for(var/belly in owner.vore_organs)
- var/obj/belly/B = belly
- if(B.name == transferlocation)
- dest_belly = B
- break
+ else if(prob(transferchance) && transferlocation) //Next, let's have it see if they end up getting into an even bigger mess then when they started.
+ var/obj/belly/dest_belly
+ for(var/belly in owner.vore_organs)
+ var/obj/belly/B = belly
+ if(B.name == transferlocation)
+ dest_belly = B
+ break
- if(!dest_belly)
- to_chat(owner, "Something went wrong with your belly transfer settings. Your [lowertext(name)] has had it's transfer chance and transfer location cleared as a precaution.")
- transferchance = 0
- transferlocation = null
+ if(!dest_belly)
+ to_chat(owner, "Something went wrong with your belly transfer settings. Your [lowertext(name)] has had it's transfer chance and transfer location cleared as a precaution.")
+ transferchance = 0
+ transferlocation = null
+ return
+
+ to_chat(R,"Your attempt to escape [lowertext(name)] has failed and your struggles only results in you sliding into [owner]'s [transferlocation]!")
+ to_chat(owner,"Someone slid into your [transferlocation] due to their struggling inside your [lowertext(name)]!")
+ transfer_contents(R, dest_belly)
return
- to_chat(R,"Your attempt to escape [lowertext(name)] has failed and your struggles only results in you sliding into [owner]'s [transferlocation]!")
- to_chat(owner,"Someone slid into your [transferlocation] due to their struggling inside your [lowertext(name)]!")
- transfer_contents(R, dest_belly)
- return
+ else if(prob(absorbchance) && digest_mode != DM_ABSORB) //After that, let's have it run the absorb chance.
+ to_chat(R,"In response to your struggling, \the [lowertext(name)] begins to cling more tightly...")
+ to_chat(owner,"You feel your [lowertext(name)] start to cling onto its contents...")
+ digest_mode = DM_ABSORB
+ return
- else if(prob(absorbchance) && digest_mode != DM_ABSORB) //After that, let's have it run the absorb chance.
- to_chat(R,"In response to your struggling, \the [lowertext(name)] begins to cling more tightly...")
- to_chat(owner,"You feel your [lowertext(name)] start to cling onto its contents...")
- digest_mode = DM_ABSORB
- return
+ else if(prob(digestchance) && digest_mode != DM_DIGEST) //Finally, let's see if it should run the digest chance.
+ to_chat(R,"In response to your struggling, \the [lowertext(name)] begins to get more active...")
+ to_chat(owner,"You feel your [lowertext(name)] beginning to become active!")
+ digest_mode = DM_DIGEST
+ return
- else if(prob(digestchance) && digest_mode != DM_DIGEST) //Finally, let's see if it should run the digest chance.
- to_chat(R,"In response to your struggling, \the [lowertext(name)] begins to get more active...")
- to_chat(owner,"You feel your [lowertext(name)] beginning to become active!")
- digest_mode = DM_DIGEST
- return
-
- else //Nothing interesting happened.
- to_chat(R,"You make no progress in escaping [owner]'s [lowertext(name)].")
- to_chat(owner,"Your prey appears to be unable to make any progress in escaping your [lowertext(name)].")
- return
+ else //Nothing interesting happened.
+ to_chat(R,"You make no progress in escaping [owner]'s [lowertext(name)].")
+ to_chat(owner,"Your prey appears to be unable to make any progress in escaping your [lowertext(name)].")
+ return
/obj/belly/proc/get_mobs_and_objs_in_belly()
var/list/see = list()
@@ -641,6 +696,7 @@
dupe.swallow_time = swallow_time
dupe.vore_capacity = vore_capacity
dupe.is_wet = is_wet
+ dupe.wet_loop = wet_loop
//// Object-holding variables
//struggle_messages_outside - strings
diff --git a/modular_citadel/code/modules/vore/eating/bellymodes_vr.dm b/code/modules/vore/eating/bellymodes.dm
similarity index 76%
rename from modular_citadel/code/modules/vore/eating/bellymodes_vr.dm
rename to code/modules/vore/eating/bellymodes.dm
index da323f02e2..0ecaf49abc 100644
--- a/modular_citadel/code/modules/vore/eating/bellymodes_vr.dm
+++ b/code/modules/vore/eating/bellymodes.dm
@@ -18,27 +18,29 @@
return SSBELLIES_PROCESSED
next_process = times_fired + (6 SECONDS/wait) //Set up our next process time.
+ var/to_update = FALSE
/////////////////////////// Auto-Emotes ///////////////////////////
if(contents.len && next_emote <= times_fired)
next_emote = times_fired + round(emote_time/wait,1)
var/list/EL = emote_lists[digest_mode]
- for(var/mob/living/M in contents)
- if(M.digestable || !(digest_mode == DM_DIGEST)) // don't give digesty messages to indigestible people
- to_chat(M,"[pick(EL)]")
+ if(LAZYLEN(EL))
+ for(var/mob/living/M in contents)
+ if(M.digestable || !(digest_mode == DM_DIGEST)) // don't give digesty messages to indigestible people
+ to_chat(M,"[pick(EL)]")
///////////////////// Prey Loop Refresh/hack //////////////////////
for(var/mob/living/M in contents)
- if(isbelly(M.loc))
+ if(M && isbelly(M.loc))
if(world.time > M.next_preyloop)
- if(is_wet)
+ if(is_wet && wet_loop)
if(!M.client)
continue
M.stop_sound_channel(CHANNEL_PREYLOOP) // sanity just in case
if(M.client.prefs.cit_toggles & DIGESTION_NOISES)
- var/sound/preyloop = sound('sound/vore/prey/loop.ogg', repeat = TRUE)
+ var/sound/preyloop = sound('sound/vore/prey/loop.ogg')
M.playsound_local(get_turf(src),preyloop, 80,0, channel = CHANNEL_PREYLOOP)
- M.next_preyloop = (world.time + 52 SECONDS)
+ M.next_preyloop = (world.time + 51 SECONDS)
/////////////////////////// Exit Early ////////////////////////////
@@ -56,7 +58,6 @@
var/sound/prey_death = sound(get_sfx("death_prey"))
var/sound/pred_digest = sound(get_sfx("digest_pred"))
var/sound/pred_death = sound(get_sfx("death_pred"))
- var/turf/source = get_turf(owner)
///////////////////////////// DM_HOLD /////////////////////////////
if(digest_mode == DM_HOLD)
@@ -70,18 +71,18 @@
for (var/mob/living/M in contents)
if(prob(25))
- if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
+ if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, source))
+ for(var/mob/living/H in get_hearers_in_view(3, owner))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/living/H in hearing_mobs)
- if(!isbelly(H.loc))
- H.playsound_local(source, null, 45, falloff = 0, S = pred_digest)
- else if(H in contents)
- H.playsound_local(source, null, 65, falloff = 0, S = prey_digest)
+ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
+ SEND_SOUND(H,pred_digest)
+ else if(H && H in contents && H.client)
+ SEND_SOUND(H,prey_digest)
//Pref protection!
if (!M.digestable || M.absorbed)
@@ -107,21 +108,22 @@
M.visible_message("You watch as [owner]'s form loses its additions.")
owner.nutrition += 400 // so eating dead mobs gives you *something*.
- if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
+ if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, source))
+ for(var/mob/living/H in get_hearers_in_view(3, owner))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/living/H in hearing_mobs)
- if(!isbelly(H.loc))
- H.playsound_local(source, null, 45, falloff = 0, S = pred_death)
- else if(H in contents)
- H.playsound_local(source, null, 65, falloff = 0, S = prey_death)
+ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
+ SEND_SOUND(H,pred_death)
+ else if(H && H in contents && H.client)
+ SEND_SOUND(H,prey_death)
M.stop_sound_channel(CHANNEL_PREYLOOP)
digestion_death(M)
owner.update_icons()
+ to_update = TRUE
continue
@@ -136,48 +138,45 @@
if(istype(T,/obj/item/reagent_containers/food) || istype(T,/obj/item/organ))
digest_item(T)
- owner.updateVRPanel()
-
///////////////////////////// DM_HEAL /////////////////////////////
if(digest_mode == DM_HEAL)
for (var/mob/living/M in contents)
if(prob(25))
- if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
+ if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, source))
+ for(var/mob/living/H in get_hearers_in_view(3, owner))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/living/H in hearing_mobs)
- if(!isbelly(H.loc))
- H.playsound_local(source, null, 45, falloff = 0, S = pred_digest)
- else if(H in contents)
- H.playsound_local(source, null, 65, falloff = 0, S = prey_digest)
+ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
+ SEND_SOUND(H,pred_digest)
+ else if(H && H in contents && H.client)
+ SEND_SOUND(H,prey_digest)
if(M.stat != DEAD)
if(owner.nutrition >= NUTRITION_LEVEL_STARVING && (M.health < M.maxHealth))
M.adjustBruteLoss(-3)
M.adjustFireLoss(-3)
owner.nutrition -= 5
- return
////////////////////////// DM_NOISY /////////////////////////////////
//for when you just want people to squelch around
if(digest_mode == DM_NOISY)
if(prob(35))
- if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
+ if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, source))
+ for(var/mob/living/H in get_hearers_in_view(3, owner))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/living/H in hearing_mobs)
- if(!isbelly(H.loc))
- H.playsound_local(source, null, 45, falloff = 0, S = pred_digest)
- else if(H in contents)
- H.playsound_local(source, null, 65, falloff = 0, S = prey_digest)
+ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
+ SEND_SOUND(H,pred_digest)
+ else if(H && H in contents && H.client)
+ SEND_SOUND(H,prey_digest)
//////////////////////////// DM_ABSORB ////////////////////////////
@@ -186,18 +185,18 @@
for (var/mob/living/M in contents)
if(prob(10))//Less often than gurgles. People might leave this on forever.
- if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
+ if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, source))
+ for(var/mob/living/H in get_hearers_in_view(3, owner))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/living/H in hearing_mobs)
- if(!isbelly(H.loc))
- H.playsound_local(source, null, 45, falloff = 0, S = pred_digest)
- else if(H in contents)
- H.playsound_local(source, null, 65, falloff = 0, S = prey_digest)
+ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
+ SEND_SOUND(H,pred_digest)
+ else if(H && H in contents && H.client)
+ SEND_SOUND(H,prey_digest)
if(M.absorbed)
continue
@@ -208,16 +207,18 @@
owner.nutrition += oldnutrition
else if(M.nutrition < 100) //When they're finally drained.
absorb_living(M)
+ to_update = TRUE
//////////////////////////// DM_UNABSORB ////////////////////////////
else if(digest_mode == DM_UNABSORB)
for (var/mob/living/M in contents)
if(M.absorbed && owner.nutrition >= 100)
- M.absorbed = 0
+ M.absorbed = FALSE
to_chat(M,"You suddenly feel solid again ")
to_chat(owner,"You feel like a part of you is missing.")
owner.nutrition -= 100
+ to_update = TRUE
//////////////////////////DM_DRAGON /////////////////////////////////////
//because dragons need snowflake guts
@@ -228,18 +229,18 @@
for (var/mob/living/M in contents)
if(prob(55)) //if you're hearing this, you're a vore ho anyway.
- if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
+ if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, source))
+ for(var/mob/living/H in get_hearers_in_view(3, owner))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/living/H in hearing_mobs)
- if(!isbelly(H.loc))
- H.playsound_local(source, null, 45, falloff = 0, S = pred_digest)
- else if(H in contents)
- H.playsound_local(source, null, 65, falloff = 0, S = prey_digest)
+ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
+ SEND_SOUND(H,pred_digest)
+ else if(H && H in contents && H.client)
+ SEND_SOUND(H,prey_digest)
//No digestion protection for megafauna.
@@ -261,22 +262,23 @@
to_chat(owner, "[digest_alert_owner]")
to_chat(M, "[digest_alert_prey]")
M.visible_message("You watch as [owner]'s guts loudly rumble as it finishes off a meal.")
- if((world.time - NORMIE_HEARCHECK) > last_hearcheck)
+ if((world.time + NORMIE_HEARCHECK) > last_hearcheck)
LAZYCLEARLIST(hearing_mobs)
- for(var/mob/living/H in get_hearers_in_view(3, source))
+ for(var/mob/living/H in get_hearers_in_view(3, owner))
if(!H.client || !(H.client.prefs.cit_toggles & DIGESTION_NOISES))
continue
LAZYADD(hearing_mobs, H)
last_hearcheck = world.time
for(var/mob/living/H in hearing_mobs)
- if(!isbelly(H.loc))
- H.playsound_local(source, null, 45, falloff = 0, S = pred_death)
- else if(H in contents)
- H.playsound_local(source, null, 65, falloff = 0, S = prey_death)
+ if(H && H.client && (isturf(H.loc) || (H.loc != src.contents)))
+ SEND_SOUND(H,pred_death)
+ else if(H && H in contents && H.client)
+ SEND_SOUND(H,prey_death)
M.spill_organs(FALSE,TRUE,TRUE)
M.stop_sound_channel(CHANNEL_PREYLOOP)
digestion_death(M)
owner.update_icons()
+ to_update = TRUE
continue
@@ -291,4 +293,11 @@
if(istype(T,/obj/item/reagent_containers/food) || istype(T,/obj/item/organ))
digest_item(T)
- owner.updateVRPanel()
\ No newline at end of file
+ if(to_update)
+ for(var/mob/living/M in contents)
+ if(M.client)
+ M.updateVRPanel()
+ if(owner.client)
+ owner.updateVRPanel()
+
+ return SSBELLIES_PROCESSED
\ No newline at end of file
diff --git a/modular_citadel/code/modules/vore/eating/digest_act_vr.dm b/code/modules/vore/eating/digest_act.dm
similarity index 100%
rename from modular_citadel/code/modules/vore/eating/digest_act_vr.dm
rename to code/modules/vore/eating/digest_act.dm
diff --git a/modular_citadel/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living.dm
similarity index 93%
rename from modular_citadel/code/modules/vore/eating/living_vr.dm
rename to code/modules/vore/eating/living.dm
index d9adde04d1..9fdb7aa764 100644
--- a/modular_citadel/code/modules/vore/eating/living_vr.dm
+++ b/code/modules/vore/eating/living.dm
@@ -8,7 +8,7 @@
var/feeding = FALSE // Are we going to feed someone else?
var/vore_taste = null // What the character tastes like
var/no_vore = FALSE // If the character/mob can vore.
- var/openpanel = 0 // Is the vore panel open?
+ var/openpanel = FALSE // Is the vore panel open?
var/absorbed = FALSE //are we absorbed?
var/next_preyloop
var/vore_init = FALSE //Has this mob's vore been initialized yet?
@@ -23,16 +23,16 @@
M.verbs += /mob/living/proc/escapeOOC
if(M.no_vore) //If the mob isn't supposed to have a stomach, let's not give it an insidepanel so it can make one for itself, or a stomach.
- return 1
+ return TRUE
M.verbs += /mob/living/proc/insidePanel
//Tries to load prefs if a client is present otherwise gives freebie stomach
- spawn(10 SECONDS) // long delay because the server delays in its startup. just on the safe side.
+ spawn(2 SECONDS) // long delay because the server delays in its startup. just on the safe side.
if(M)
M.init_vore()
- //Return 1 to hook-caller
- return 1
+ //return TRUE to hook-caller
+ return TRUE
/mob/living/proc/init_vore()
vore_init = TRUE
@@ -54,10 +54,10 @@
LAZYINITLIST(vore_organs)
var/obj/belly/B = new /obj/belly(src)
vore_selected = B
- B.immutable = 1
+ B.immutable = TRUE
B.name = "Stomach"
B.desc = "It appears to be rather warm and wet. Makes sense, considering it's inside [name]."
- B.can_taste = 1
+ B.can_taste = TRUE
return TRUE
// Handle being clicked, perhaps with something to devour
@@ -84,7 +84,7 @@
return
feed_self_to_grabbed(user, pred)
- if(pred == user) //you click yourself
+ else if(pred == user) //you click yourself
if(!is_vore_predator(src))
to_chat(user, "You aren't voracious enough.")
return
@@ -126,7 +126,7 @@
//Sanity
if(!user || !prey || !pred || !istype(belly) || !(belly in pred.vore_organs))
testing("[user] attempted to feed [prey] to [pred], via [lowertext(belly.name)] but it went wrong.")
- return FALSE
+ return
if (!prey.devourable)
to_chat(user, "This can't be eaten!")
@@ -151,9 +151,14 @@
user.visible_message(attempt_msg)
// Now give the prey time to escape... return if they did
- var/swallow_time = delay || ishuman(prey) ? belly.human_prey_swallow_time : belly.nonhuman_prey_swallow_time
+ var/swallow_time
+ if(delay)
+ swallow_time = delay
+ else
+ swallow_time = istype(prey, /mob/living/carbon/human) ? belly.human_prey_swallow_time : belly.nonhuman_prey_swallow_time
- if(!do_mob(src, user, swallow_time))
+ //Timer and progress bar
+ if(!do_after(user, swallow_time, prey))
return FALSE // Prey escaped (or user disabled) before timer expired.
if(!prey.Adjacent(user)) //double check'd just in case they moved during the timer and the do_mob didn't fail for whatever reason
@@ -162,13 +167,6 @@
// If we got this far, nom successful! Announce it!
user.visible_message(success_msg)
- // incredibly contentious eating noises time
- var/turf/source = get_turf(user)
- var/sound/eating = GLOB.vore_sounds[belly.vore_sound]
- for(var/mob/living/M in get_hearers_in_view(3, source))
- if(M.client && M.client.prefs.cit_toggles & EATING_NOISES)
- SEND_SOUND(M, eating)
-
// Actually shove prey into the belly.
belly.nom_mob(prey, user)
stop_pulling()
@@ -183,7 +181,7 @@
if(prey.ckey)
prey_stat = prey.stat//only return this if they're not an unmonkey or whatever
if(!prey.client)//if they disconnected, tell us
- prey_braindead = 1
+ prey_braindead = TRUE
if (pred == user)
message_admins("[ADMIN_LOOKUPFLW(pred)] ate [ADMIN_LOOKUPFLW(prey)][!prey_braindead ? "" : " (BRAINDEAD)"][prey_stat ? " (DEAD/UNCONSCIOUS)" : ""].")
pred.log_message("[key_name(pred)] ate [key_name(prey)].", LOG_ATTACK)
@@ -212,15 +210,15 @@
//Other overridden resists go here
- return 0
+ return FALSE
// internal slimy button in case the loop stops playing but the player wants to hear it
/mob/living/proc/preyloop_refresh()
set name = "Internal loop refresh"
set category = "Vore"
+ src.stop_sound_channel(CHANNEL_PREYLOOP) // sanity just in case
if(isbelly(loc))
- src.stop_sound_channel(CHANNEL_PREYLOOP) // sanity just in case
- var/sound/preyloop = sound('sound/vore/prey/loop.ogg', repeat = TRUE)
+ var/sound/preyloop = sound('sound/vore/prey/loop.ogg')
SEND_SOUND(src, preyloop)
else
to_chat(src, "You aren't inside anything, you clod.")
@@ -265,28 +263,28 @@
//
/mob/living/proc/save_vore_prefs()
if(!client || !client.prefs_vr)
- return 0
+ return FALSE
if(!copy_to_prefs_vr())
- return 0
+ return FALSE
if(!client.prefs_vr.save_vore())
- return 0
+ return FALSE
- return 1
+ return TRUE
/mob/living/proc/apply_vore_prefs()
if(!client || !client.prefs_vr)
- return 0
+ return FALSE
if(!client.prefs_vr.load_vore())
- return 0
+ return FALSE
if(!copy_from_prefs_vr())
- return 0
+ return FALSE
- return 1
+ return TRUE
/mob/living/proc/copy_to_prefs_vr()
if(!client || !client.prefs_vr)
to_chat(src,"You attempted to save your vore prefs but somehow you're in this character without a client.prefs_vr variable. Tell a dev.")
- return 0
+ return FALSE
var/datum/vore_preferences/P = client.prefs_vr
@@ -302,7 +300,7 @@
P.belly_prefs = serialized
- return 1
+ return TRUE
//
// Proc for applying vore preferences, given bellies
@@ -310,7 +308,7 @@
/mob/living/proc/copy_from_prefs_vr()
if(!client || !client.prefs_vr)
to_chat(src,"You attempted to apply your vore prefs but somehow you're in this character without a client.prefs_vr variable. Tell a dev.")
- return 0
+ return FALSE
vorepref_init = TRUE
var/datum/vore_preferences/P = client.prefs_vr
@@ -325,7 +323,7 @@
for(var/entry in P.belly_prefs)
list_to_object(entry,src)
- return 1
+ return TRUE
//
// Release everything in every vore organ
diff --git a/modular_citadel/code/modules/vore/eating/vore_vr.dm b/code/modules/vore/eating/vore.dm
similarity index 94%
rename from modular_citadel/code/modules/vore/eating/vore_vr.dm
rename to code/modules/vore/eating/vore.dm
index dc813d70aa..a9b14dcdc8 100644
--- a/modular_citadel/code/modules/vore/eating/vore_vr.dm
+++ b/code/modules/vore/eating/vore.dm
@@ -84,22 +84,22 @@ GLOBAL_LIST_EMPTY(vore_preferences_datums)
/datum/vore_preferences/proc/load_vore()
if(!client || !client_ckey)
- return 0 //No client, how can we save?
+ return FALSE //No client, how can we save?
if(!client.prefs || !client.prefs.default_slot)
- return 0 //Need to know what character to load!
+ return FALSE //Need to know what character to load!
slot = client.prefs.default_slot
load_path(client_ckey,slot)
- if(!path) return 0 //Path couldn't be set?
+ if(!path) return FALSE //Path couldn't be set?
if(!fexists(path)) //Never saved before
save_vore() //Make the file first
- return 1
+ return TRUE
var/list/json_from_file = json_decode(file2text(path))
if(!json_from_file)
- return 0 //My concern grows
+ return FALSE //My concern grows
var/version = json_from_file["version"]
json_from_file = patch_version(json_from_file,version)
@@ -120,11 +120,11 @@ GLOBAL_LIST_EMPTY(vore_preferences_datums)
if(isnull(belly_prefs))
belly_prefs = list()
- return 1
+ return TRUE
/datum/vore_preferences/proc/save_vore()
if(!path)
- return 0
+ return FALSE
var/version = VORE_VERSION //For "good times" use in the future
var/list/settings_list = list(
@@ -140,7 +140,7 @@ GLOBAL_LIST_EMPTY(vore_preferences_datums)
var/json_to_file = json_encode(settings_list)
if(!json_to_file)
testing("Saving: [path] failed jsonencode")
- return 0
+ return FALSE
//Write it out
//#ifdef RUST_G
@@ -153,9 +153,9 @@ GLOBAL_LIST_EMPTY(vore_preferences_datums)
//#endif
if(!fexists(path))
testing("Saving: [path] failed file write")
- return 0
+ return FALSE
- return 1
+ return TRUE
/* commented out list things
"allowmobvore" = allowmobvore,
diff --git a/modular_citadel/code/modules/vore/eating/voreitems.dm b/code/modules/vore/eating/voreitems.dm
similarity index 100%
rename from modular_citadel/code/modules/vore/eating/voreitems.dm
rename to code/modules/vore/eating/voreitems.dm
diff --git a/modular_citadel/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel.dm
similarity index 92%
rename from modular_citadel/code/modules/vore/eating/vorepanel_vr.dm
rename to code/modules/vore/eating/vorepanel.dm
index ae7da895a6..962fe54af7 100644
--- a/modular_citadel/code/modules/vore/eating/vorepanel_vr.dm
+++ b/code/modules/vore/eating/vorepanel.dm
@@ -21,10 +21,10 @@
picker_holder.popup = new(src, "insidePanel","Vore Panel", 450, 700, picker_holder)
picker_holder.popup.set_content(dat)
picker_holder.popup.open()
- src.openpanel = 1
+ src.openpanel = TRUE
/mob/living/proc/updateVRPanel() //Panel popup update call from belly events.
- if(src.openpanel == 1)
+ if(src.openpanel == TRUE)
var/datum/vore_look/picker_holder = new()
picker_holder.loop = picker_holder
picker_holder.selected = vore_selected
@@ -40,7 +40,7 @@
//
/datum/vore_look
var/obj/belly/selected
- var/show_interacts = 0
+ var/show_interacts = FALSE
var/datum/browser/popup
var/loop = null; // Magic self-reference to stop the handler from being GC'd before user takes action.
@@ -163,6 +163,9 @@
//Belly Type button
dat += " Is Fleshy:"
dat += "[selected.is_wet ? "Yes" : "No"]"
+ if(selected.is_wet)
+ dat += " Internal loop for prey?:"
+ dat += "[selected.wet_loop ? "Yes" : "No"]"
//Digest Mode Button
dat += " Belly Mode:"
@@ -241,21 +244,19 @@
dat += ""
switch(user.digestable)
if(TRUE)
- dat += "Toggle Digestable (Currently: ON)"
+ dat += " Toggle Digestable (Currently: ON)"
if(FALSE)
- dat += "Toggle Digestable (Currently: OFF)"
-
+ dat += " Toggle Digestable (Currently: OFF)"
switch(user.devourable)
if(TRUE)
- dat += " Toggle Devourable (Currently: ON)"
+ dat += " Toggle Devourable (Currently: ON)"
if(FALSE)
- dat += " Toggle Devourable (Currently: OFF)"
-
+ dat += " Toggle Devourable (Currently: OFF)"
switch(user.feeding)
if(TRUE)
- dat += " Toggle Feeding (Currently: ON)"
+ dat += " Toggle Feeding (Currently: ON)"
if(FALSE)
- dat += " Toggle Feeding (Currently: OFF)"
+ dat += " Toggle Feeding (Currently: OFF)"
//Returns the dat html to the vore_look
return dat
@@ -266,12 +267,12 @@
if(href_list["close"])
qdel(src) // Cleanup
- user.openpanel = 0
+ user.openpanel = FALSE
return
if(href_list["show_int"])
show_interacts = !show_interacts
- return 1 //Force update
+ return TRUE //Force update
if(href_list["int_help"])
alert("These control how your belly responds to someone using 'resist' while inside you. The percent chance to trigger each is listed below, \
@@ -279,13 +280,13 @@
These only function as long as interactions are turned on in general. Keep in mind, the 'belly mode' interactions (digest/absorb) \
will affect all prey in that belly, if one resists and triggers digestion/absorption. If multiple trigger at the same time, \
only the first in the order of 'Escape > Transfer > Absorb > Digest' will occur.","Interactions Help")
- return 0 //Force update
+ return FALSE //Force update
if(href_list["outsidepick"])
var/atom/movable/tgt = locate(href_list["outsidepick"])
var/obj/belly/OB = locate(href_list["outsidebelly"])
if(!(tgt in OB)) //Aren't here anymore, need to update menu.
- return 1
+ return TRUE
var/intent = "Examine"
if(istype(tgt,/mob/living))
@@ -298,7 +299,7 @@
if("Help Out") //Help the inside-mob out
if(user.stat || user.absorbed || M.absorbed)
to_chat(user,"You can't do that in your state!")
- return 1
+ return TRUE
to_chat(user,"You begin to push [M] to freedom!")
to_chat(M,"[usr] begins to push you to freedom!")
@@ -317,11 +318,11 @@
if("Devour") //Eat the inside mob
if(user.absorbed || user.stat)
to_chat(user,"You can't do that in your state!")
- return 1
+ return TRUE
if(!user.vore_selected)
to_chat(user,"Pick a belly on yourself first!")
- return 1
+ return TRUE
var/obj/belly/TB = user.vore_selected
to_chat(user,"You begin to [lowertext(TB.vore_verb)] [M] into your [lowertext(TB.name)]!")
@@ -339,7 +340,7 @@
var/obj/item/T = tgt
if(!(tgt in OB))
//Doesn't exist anymore, update.
- return 1
+ return TRUE
intent = alert("What do you want to do to that?","Query","Examine","Use Hand")
switch(intent)
if("Examine")
@@ -348,7 +349,7 @@
if("Use Hand")
if(user.stat)
to_chat(user,"You can't do that in your state!")
- return 1
+ return TRUE
user.ClickOn(T)
sleep(5) //Seems to exit too fast for the panel to update
@@ -361,23 +362,23 @@
intent = alert("Eject all, Move all?","Query","Eject all","Cancel","Move all")
switch(intent)
if("Cancel")
- return 0
+ return FALSE
if("Eject all")
if(user.stat)
to_chat(user,"You can't do that in your state!")
- return 0
+ return FALSE
selected.release_all_contents()
if("Move all")
if(user.stat)
to_chat(user,"You can't do that in your state!")
- return 0
+ return FALSE
var/obj/belly/choice = input("Move all where?","Select Belly") as null|anything in user.vore_organs
if(!choice)
- return 0
+ return FALSE
for(var/atom/movable/tgt in selected)
to_chat(tgt,"You're squished from [user]'s [lowertext(selected)] to their [lowertext(choice.name)]!")
@@ -385,7 +386,7 @@
var/atom/movable/tgt = locate(href_list["insidepick"])
if(!(tgt in selected)) //Old menu, needs updating because they aren't really there.
- return 1 //Forces update
+ return TRUE //Forces update
intent = "Examine"
intent = alert("Examine, Eject, Move? Examine if you want to leave this box.","Query","Examine","Eject","Move")
switch(intent)
@@ -395,25 +396,25 @@
if("Eject")
if(user.stat)
to_chat(user,"You can't do that in your state!")
- return 0
+ return FALSE
selected.release_specific_contents(tgt)
if("Move")
if(user.stat)
to_chat(user,"You can't do that in your state!")
- return 0
+ return FALSE
var/obj/belly/choice = input("Move [tgt] where?","Select Belly") as null|anything in user.vore_organs
if(!choice || !(tgt in selected))
- return 0
+ return FALSE
to_chat(tgt,"You're squished from [user]'s [lowertext(selected.name)] to their [lowertext(choice.name)]!")
selected.transfer_contents(tgt, choice)
if(href_list["newbelly"])
if(user.vore_organs.len >= BELLIES_MAX)
- return 0
+ return FALSE
var/new_name = html_encode(input(usr,"New belly's name:","New Belly") as text|null)
@@ -430,7 +431,7 @@
if(failure_msg) //Something went wrong.
alert(user,failure_msg,"Error!")
- return 0
+ return FALSE
var/obj/belly/NB = new(user)
NB.name = new_name
@@ -459,19 +460,22 @@
if(failure_msg) //Something went wrong.
alert(user,failure_msg,"Error!")
- return 0
+ return FALSE
selected.name = new_name
if(href_list["b_wetness"])
selected.is_wet = !selected.is_wet
+ if(href_list["b_wetloop"])
+ selected.wet_loop = !selected.wet_loop
+
if(href_list["b_mode"])
var/list/menu_list = selected.digest_modes
var/new_mode = input("Choose Mode (currently [selected.digest_mode])") as null|anything in menu_list
if(!new_mode)
- return 0
+ return FALSE
selected.digest_mode = new_mode
if(href_list["b_desc"])
@@ -539,12 +543,12 @@
if(length(new_verb) > BELLIES_NAME_MAX || length(new_verb) < BELLIES_NAME_MIN)
alert("Entered verb length invalid (must be longer than [BELLIES_NAME_MIN], no longer than [BELLIES_NAME_MAX]).","Error")
- return 0
+ return FALSE
selected.vore_verb = new_verb
if(href_list["b_release"])
- var/choice = input(user,"Currently set to [selected.release_sound]","Select Sound") as null|anything in GLOB.release_sounds
+ var/choice = input(user,"Currently set to [selected.release_sound]","Select Sound") as null|anything in GLOB.pred_release_sounds
if(!choice)
return
@@ -552,12 +556,12 @@
selected.release_sound = choice
if(href_list["b_releasesoundtest"])
- var/sound/releasetest = GLOB.release_sounds[selected.release_sound]
+ var/sound/releasetest = GLOB.prey_release_sounds[selected.release_sound]
if(releasetest)
SEND_SOUND(user, releasetest)
if(href_list["b_sound"])
- var/choice = input(user,"Currently set to [selected.vore_sound]","Select Sound") as null|anything in GLOB.vore_sounds
+ var/choice = input(user,"Currently set to [selected.vore_sound]","Select Sound") as null|anything in GLOB.pred_vore_sounds
if(!choice)
return
@@ -565,7 +569,7 @@
selected.vore_sound = choice
if(href_list["b_soundtest"])
- var/sound/voretest = GLOB.vore_sounds[selected.vore_sound]
+ var/sound/voretest = GLOB.prey_vore_sounds[selected.vore_sound]
if(voretest)
SEND_SOUND(user, voretest)
@@ -586,17 +590,17 @@
selected.bulge_size = (new_bulge/100)
if(href_list["b_escapable"])
- if(selected.escapable == 0) //Possibly escapable and special interactions.
- selected.escapable = 1
+ if(selected.escapable == FALSE) //Possibly escapable and special interactions.
+ selected.escapable = TRUE
to_chat(usr,"Prey now have special interactions with your [lowertext(selected.name)] depending on your settings.")
- else if(selected.escapable == 1) //Never escapable.
- selected.escapable = 0
+ else if(selected.escapable == TRUE) //Never escapable.
+ selected.escapable = FALSE
to_chat(usr,"Prey will not be able to have special interactions with your [lowertext(selected.name)].")
- show_interacts = 0 //Force the hiding of the panel
+ show_interacts = FALSE //Force the hiding of the panel
else
alert("Something went wrong. Your stomach will now not have special interactions. Press the button enable them again and tell a dev.","Error") //If they somehow have a varable that's not 0 or 1
- selected.escapable = 0
- show_interacts = 0 //Force the hiding of the panel
+ selected.escapable = FALSE
+ show_interacts = FALSE //Force the hiding of the panel
if(href_list["b_escapechance"])
var/escape_chance_input = input(user, "Set prey escape chance on resist (as %)", "Prey Escape Chance") as num|null
@@ -617,7 +621,7 @@
var/obj/belly/choice = input("Where do you want your [lowertext(selected.name)] to lead if prey resists?","Select Belly") as null|anything in (user.vore_organs + "None - Remove" - selected)
if(!choice) //They cancelled, no changes
- return 0
+ return FALSE
else if(choice == "None - Remove")
selected.transferlocation = null
else
@@ -636,7 +640,7 @@
if(href_list["b_del"])
var/alert = alert("Are you sure you want to delete your [lowertext(selected.name)]?","Confirmation","Delete","Cancel")
if(!alert == "Delete")
- return 0
+ return FALSE
var/failure_msg = ""
@@ -657,7 +661,7 @@
if(failure_msg)
alert(user,failure_msg,"Error!")
- return 0
+ return FALSE
qdel(selected)
selected = user.vore_organs[1]
@@ -674,7 +678,7 @@
if(href_list["applyprefs"])
var/alert = alert("Are you sure you want to reload character slot preferences? This will remove your current vore organs and eject their contents.","Confirmation","Reload","Cancel")
if(!alert == "Reload")
- return 0
+ return FALSE
if(!user.apply_vore_prefs())
alert("ERROR: Vore preferences failed to apply!","Error")
else
@@ -683,19 +687,19 @@
if(href_list["setflavor"])
var/new_flavor = html_encode(input(usr,"What your character tastes like (40ch limit). This text will be printed to the pred after 'X tastes of...' so just put something like 'strawberries and cream':","Character Flavor",user.vore_taste) as text|null)
if(!new_flavor)
- return 0
+ return FALSE
new_flavor = readd_quotes(new_flavor)
if(length(new_flavor) > FLAVOR_MAX)
alert("Entered flavor/taste text too long. [FLAVOR_MAX] character limit.","Error!")
- return 0
+ return FALSE
user.vore_taste = new_flavor
if(href_list["toggledg"])
var/choice = alert(user, "This button is for those who don't like being digested. It can make you undigestable to all mobs. Digesting you is currently: [user.digestable ? "Allowed" : "Prevented"]", "", "Allow Digestion", "Cancel", "Prevent Digestion")
switch(choice)
if("Cancel")
- return 0
+ return FALSE
if("Allow Digestion")
user.digestable = TRUE
if("Prevent Digestion")
@@ -708,7 +712,7 @@
var/choice = alert(user, "This button is for those who don't like vore at all. Devouring you is currently: [user.devourable ? "Allowed" : "Prevented"]", "", "Allow Devourment", "Cancel", "Prevent Devourment")
switch(choice)
if("Cancel")
- return 0
+ return FALSE
if("Allow Devourment")
user.devourable = TRUE
if("Prevent Devourment")
@@ -721,7 +725,7 @@
var/choice = alert(user, "This button is to toggle your ability to be fed to others. Feeding predators is currently: [user.feeding ? "Allowed" : "Prevented"]", "", "Allow Feeding", "Cancel", "Prevent Feeding")
switch(choice)
if("Cancel")
- return 0
+ return FALSE
if("Allow Feeding")
user.feeding = TRUE
if("Prevent Feeding")
@@ -731,4 +735,4 @@
user.client.prefs_vr.feeding = user.feeding
//Refresh when interacted with, returning 1 makes vore_look.Topic update
- return 1
\ No newline at end of file
+ return TRUE
\ No newline at end of file
diff --git a/modular_citadel/code/modules/vore/hook-defs_vr.dm b/code/modules/vore/hook-defs.dm
similarity index 100%
rename from modular_citadel/code/modules/vore/hook-defs_vr.dm
rename to code/modules/vore/hook-defs.dm
diff --git a/modular_citadel/code/modules/vore/persistence.dm b/code/modules/vore/persistence.dm
similarity index 100%
rename from modular_citadel/code/modules/vore/persistence.dm
rename to code/modules/vore/persistence.dm
diff --git a/modular_citadel/code/modules/vore/resizing/grav_pull_vr.dm b/code/modules/vore/resizing/grav_pull_vr.dm
similarity index 100%
rename from modular_citadel/code/modules/vore/resizing/grav_pull_vr.dm
rename to code/modules/vore/resizing/grav_pull_vr.dm
diff --git a/modular_citadel/code/modules/vore/resizing/holder_micro_vr.dm b/code/modules/vore/resizing/holder_micro_vr.dm
similarity index 100%
rename from modular_citadel/code/modules/vore/resizing/holder_micro_vr.dm
rename to code/modules/vore/resizing/holder_micro_vr.dm
diff --git a/modular_citadel/code/modules/vore/resizing/resize_vr.dm b/code/modules/vore/resizing/resize_vr.dm
similarity index 100%
rename from modular_citadel/code/modules/vore/resizing/resize_vr.dm
rename to code/modules/vore/resizing/resize_vr.dm
diff --git a/modular_citadel/code/modules/vore/resizing/sizechemicals.dm b/code/modules/vore/resizing/sizechemicals.dm
similarity index 100%
rename from modular_citadel/code/modules/vore/resizing/sizechemicals.dm
rename to code/modules/vore/resizing/sizechemicals.dm
diff --git a/modular_citadel/code/modules/vore/resizing/sizegun_vr.dm b/code/modules/vore/resizing/sizegun_vr.dm
similarity index 100%
rename from modular_citadel/code/modules/vore/resizing/sizegun_vr.dm
rename to code/modules/vore/resizing/sizegun_vr.dm
diff --git a/modular_citadel/code/modules/vore/trycatch_vr.dm b/code/modules/vore/trycatch.dm
similarity index 100%
rename from modular_citadel/code/modules/vore/trycatch_vr.dm
rename to code/modules/vore/trycatch.dm
diff --git a/config/game_options.txt b/config/game_options.txt
index ca07d4e744..93fd00446b 100644
--- a/config/game_options.txt
+++ b/config/game_options.txt
@@ -255,6 +255,147 @@ EVENTS_MIN_TIME_MUL 1
EVENTS_MIN_PLAYERS_MUL 1
+
+### DYNAMIC MODE ###
+
+## Injection delays: how long (in minutes) will pass before a midround or latejoin antag is injected.
+DYNAMIC_MIDROUND_DELAY_MIN 15
+DYNAMIC_MIDROUND_DELAY_MAX 35
+DYNAMIC_LATEJOIN_DELAY_MIN 5
+DYNAMIC_LATEJOIN_DELAY_MAX 25
+
+## How many roundstart players required for high population override to take effect.
+DYNAMIC_HIGH_POP_LIMIT 55
+
+## Pop range per requirement.
+## If the value is five the range is:
+## 0-4, 5-9, 10-14, 15-19, 20-24, 25-29, 30-34, 35-39, 40-54, 45+
+## If it is six the range is:
+## 0-5, 6-11, 12-17, 18-23, 24-29, 30-35, 36-41, 42-47, 48-53, 54+
+## If it is seven the range is:
+## 0-6, 7-13, 14-20, 21-27, 28-34, 35-41, 42-48, 49-55, 56-62, 63+
+## Options outside this range can be used, of course.
+DYNAMIC_POP_PER_REQUIREMENT 6
+
+## 1 -> 9, probability for this rule to be picked against other rules.
+## Note that requirements must also be met, and some requirements are impossible to meet.
+DYNAMIC_WEIGHT TRAITOR 5
+DYNAMIC_WEIGHT TRAITORBRO 4
+DYNAMIC_WEIGHT CHANGELING 3
+DYNAMIC_WEIGHT WIZARD 1
+DYNAMIC_WEIGHT CULT 3
+DYNAMIC_WEIGHT NUCLEAR 3
+DYNAMIC_WEIGHT REVOLUTION 2
+# All below are impossible-by-default
+DYNAMIC_WEIGHT EXTENDED 3
+DYNAMIC_WEIGHT CLOCKWORK_CULT 3
+DYNAMIC_WEIGHT CLOWNOPS 3
+DYNAMIC_WEIGHT DEVIL 3
+DYNAMIC_WEIGHT MONKEY 3
+DYNAMIC_WEIGHT METEOR 3
+
+## Midround antags
+DYNAMIC_WEIGHT MIDROUND_TRAITOR 7
+DYNAMIC_WEIGHT MALF_AI 3
+DYNAMIC_WEIGHT MIDROUND_WIZARD 1
+DYNAMIC_WEIGHT MIDROUND_NUCLEAR 5
+DYNAMIC_WEIGHT BLOB 4
+DYNAMIC_WEIGHT XENOS 3
+DYNAMIC_WEIGHT NIGHTMARE 3
+
+## Latejoin antags
+DYNAMIC_WEIGHT LATEJOIN_TRAITOR 7
+DYNAMIC_WEIGHT LATEJOIN_REVOLUTION 2
+
+## Threat cost. This is decreased from the mode's threat when the rule is executed.
+DYNAMIC_COST TRAITOR 10
+DYNAMIC_COST TRAITORBRO 10
+DYNAMIC_COST CHANGELING 30
+DYNAMIC_COST WIZARD 30
+DYNAMIC_COST CULT 30
+DYNAMIC_COST NUCLEAR 40
+DYNAMIC_COST REVOLUTION 35
+# All below are impossible-by-default
+DYNAMIC_COST EXTENDED 0
+DYNAMIC_COST CLOCKWORK_CULT 0
+DYNAMIC_COST CLOWNOPS 40
+DYNAMIC_COST DEVIL 0
+DYNAMIC_COST MONKEY 0
+DYNAMIC_COST METEOR 0
+
+## Midround antags
+DYNAMIC_COST MIDROUND_TRAITOR 10
+DYNAMIC_COST MALF_AI 35
+DYNAMIC_COST MIDROUND_WIZARD 20
+DYNAMIC_COST MIDROUND_NUCLEAR 35
+DYNAMIC_COST BLOB 10
+DYNAMIC_COST XENOS 10
+DYNAMIC_COST NIGHTMARE 10
+
+## Latejoin antags
+DYNAMIC_COST LATEJOIN_TRAITOR 5
+DYNAMIC_COST LATEJOIN_REVOLUTION 20
+
+## Rule will not be generated with threat levels below requirement at a pop value. Pop values are determined by dynamic's pop-per-requirement.
+## By default it's 0-5, 6-11, 12-17, 18-23, 24-29, 30-35, 36-41, 42-47, 48-53, 54+.
+## This means that 40 30 30 20 20 20 15 15 15 10 will not generate below 40 at 0-5, 30 at 6-11 etc.
+DYNAMIC_REQUIREMENTS TRAITOR 10 10 10 10 10 10 10 10 10 10
+DYNAMIC_REQUIREMENTS TRAITORBRO 40 30 30 20 20 15 15 15 10 10
+DYNAMIC_REQUIREMENTS CHANGELING 80 70 60 50 40 20 20 10 10 10
+DYNAMIC_REQUIREMENTS WIZARD 90 90 70 40 30 20 10 10 10 10
+DYNAMIC_REQUIREMENTS CULT 100 90 80 60 40 30 10 10 10 10
+DYNAMIC_REQUIREMENTS NUCLEAR 90 90 90 80 60 40 30 20 10 10
+DYNAMIC_REQUIREMENTS REVOLUTION 101 101 70 40 30 20 10 10 10 10
+# All below are impossible-by-default
+DYNAMIC_REQUIREMENTS EXTENDED 101 101 101 101 101 101 101 101 101 101
+DYNAMIC_REQUIREMENTS CLOCKWORK_CULT 101 101 101 101 101 101 101 101 101 101
+DYNAMIC_REQUIREMENTS CLOWNOPS 101 101 101 101 101 101 101 101 101 101
+DYNAMIC_REQUIREMENTS DEVIL 101 101 101 101 101 101 101 101 101 101
+DYNAMIC_REQUIREMENTS MONKEY 101 101 101 101 101 101 101 101 101 101
+DYNAMIC_REQUIREMENTS METEOR 101 101 101 101 101 101 101 101 101 101
+
+## Midround antags
+DYNAMIC_REQUIREMENTS MIDROUND_TRAITOR 50 40 30 20 10 10 10 10 10 10
+DYNAMIC_REQUIREMENTS MALF_AI 101 101 80 70 60 60 50 50 40 40
+DYNAMIC_REQUIREMENTS MIDROUND_WIZARD 90 90 70 40 30 20 10 10 10 10
+DYNAMIC_REQUIREMENTS MIDROUND_NUCLEAR 90 90 90 80 60 40 30 20 10 10
+DYNAMIC_REQUIREMENTS BLOB 101 101 101 80 60 50 30 20 10 10
+DYNAMIC_REQUIREMENTS XENOS 101 101 101 70 50 40 20 15 10 10
+DYNAMIC_REQUIREMENTS NIGHTMARE 101 101 101 70 50 40 20 15 10 10
+
+## Latejoin antags
+DYNAMIC_REQUIREMENTS LATEJOIN_TRAITOR 40 30 20 10 10 10 10 10 10 10
+DYNAMIC_REQUIREMENTS LATEJOIN_REVOLUTION 101 101 70 40 30 20 20 20 20 20
+
+## An alternative, static requirement used instead when pop is over mode's high_pop_limit.
+DYNAMIC_HIGH_POPULATION_REQUIREMENT TRAITOR 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT TRAITORBRO 15
+DYNAMIC_HIGH_POPULATION_REQUIREMENT CHANGELING 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT WIZARD 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT CULT 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT NUCLEAR 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT REVOLUTION 10
+# All below are impossible-by-default
+DYNAMIC_HIGH_POPULATION_REQUIREMENT EXTENDED 101
+DYNAMIC_HIGH_POPULATION_REQUIREMENT CLOCKWORK_CULT 101
+DYNAMIC_HIGH_POPULATION_REQUIREMENT CLOWNOPS 101
+DYNAMIC_HIGH_POPULATION_REQUIREMENT DEVIL 101
+DYNAMIC_HIGH_POPULATION_REQUIREMENT MONKEY 101
+DYNAMIC_HIGH_POPULATION_REQUIREMENT METEOR 101
+
+## Midround antags
+DYNAMIC_HIGH_POPULATION_REQUIREMENT MIDROUND_TRAITOR 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT MALF_AI 35
+DYNAMIC_HIGH_POPULATION_REQUIREMENT MIDROUND_WIZARD 50
+DYNAMIC_HIGH_POPULATION_REQUIREMENT MIDROUND_NUCLEAR 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT BLOB 50
+DYNAMIC_HIGH_POPULATION_REQUIREMENT XENOS 50
+DYNAMIC_HIGH_POPULATION_REQUIREMENT NIGHTMARE 50
+
+## Latejoin antags
+DYNAMIC_HIGH_POPULATION_REQUIREMENT LATEJOIN_TRAITOR 10
+DYNAMIC_HIGH_POPULATION_REQUIREMENT LATEJOIN_REVOLUTION 50
+
## AI ###
## Allow the AI job to be picked.
@@ -263,10 +404,21 @@ ALLOW_AI
## Allow the AI Multicamera feature to be used by AI players
ALLOW_AI_MULTICAM
+## CYBORG ##
+## Uncomment to disable the ability for cyborg flashes to knock down carbon targets
+#DISABLE_BORG_FLASH_KNOCKDOWN
+
## Secborg ###
+## Uncomment to bring secborgs and K-9s back in line with the rest of the modules available. This is strongly recommended if you have secborgs configured to be available at all times.
+#WEAKEN_SECBORG
+
## Uncomment to prevent the security cyborg module from being chosen
#DISABLE_SECBORG
+## Determines the minimum alert level for the security cyborg model to be chosen
+## 0: Green, 1:Blue, 2:Amber, 3:Red, 4:Delta
+MINIMUM_SECBORG_ALERT 3
+
## Peacekeeper Borg ###
## Uncomment to prevent the peacekeeper cyborg module from being chosen
#DISABLE_PEACEBORG
diff --git a/config/maps.txt b/config/maps.txt
index 99a4543853..87e86a0800 100644
--- a/config/maps.txt
+++ b/config/maps.txt
@@ -10,6 +10,8 @@ Format:
maxplayers [number] (0 or less disables this requirement)
default (The last map with this defined will get all votes of players who have not explicitly voted for a map)
voteweight [number] (How much to count each player vote as, defaults to 1, setting to 0.5 counts each vote as half a vote, 2 as double, etc, Setting to 0 disables the map but allows players to still pick it)
+ max_round_search_span [number] (If this is nonzero, then if this map has been played more than a specified amount of times within this number of rounds, the map won't show up in votes. Max for this value determined by a define in persistence.dm)
+ max_rounds_played [number] (This determines how many times a map can be played within the above number of rounds before it's forbidden from votes.)
disabled (disables the map)
endmap
diff --git a/config/spaceRuinBlacklist.txt b/config/spaceRuinBlacklist.txt
index deafa47969..4ea7611937 100644
--- a/config/spaceRuinBlacklist.txt
+++ b/config/spaceRuinBlacklist.txt
@@ -27,6 +27,7 @@
#_maps/RandomRuins/SpaceRuins/emptyshell.dmm
#_maps/RandomRuins/SpaceRuins/gasthelizards.dmm
#_maps/RandomRuins/SpaceRuins/gondolaasteroid.dmm
+#_maps/RandomRuins/SpaceRuins/hilbertshoteltestingsite.dmm
#_maps/RandomRuins/SpaceRuins/intactemptyship.dmm
#_maps/RandomRuins/SpaceRuins/listeningstation.dmm
#_maps/RandomRuins/SpaceRuins/mechtransport.dmm
diff --git a/goon/browserassets/css/browserOutput.css b/goon/browserassets/css/browserOutput.css
deleted file mode 100644
index 174aa8a22f..0000000000
--- a/goon/browserassets/css/browserOutput.css
+++ /dev/null
@@ -1,877 +0,0 @@
-/*****************************************
-*
-* GLOBAL STYLES
-*
-******************************************/
-html, body {
- padding: 0;
- margin: 0;
- height: 100%;
- color: #000000;
-}
-body {
- background: #E0E0E0; /*CIT CHANGE - darkens chatbox a lil*/
- font-family: Verdana, sans-serif;
- font-size: 9pt;
- line-height: 1.2;
- overflow-x: hidden;
- overflow-y: scroll;
- word-wrap: break-word;
-}
-
-em {
- font-style: normal;
- font-weight: bold;
-}
-
-img {
- margin: 0;
- padding: 0;
- line-height: 1;
- -ms-interpolation-mode: nearest-neighbor;
- image-rendering: pixelated;
-}
-img.icon {
- height: 1em;
- min-height: 16px;
- width: auto;
- vertical-align: bottom;
-}
-
-
-.r:before { /* "repeated" badge class for combined messages */
- content: 'x';
-}
-.r {
- display: inline-block;
- min-width: 0.5em;
- font-size: 0.7em;
- padding: 0.2em 0.3em;
- line-height: 1;
- color: white;
- text-align: center;
- white-space: nowrap;
- vertical-align: middle;
- background-color: crimson;
- border-radius: 10px;
-}
-
-a {color: #0000ff;}
-a.visited {color: #ff00ff;}
-a:visited {color: #ff00ff;}
-a.popt {text-decoration: none;}
-
-/*****************************************
-*
-* OUTPUT NOT RELATED TO ACTUAL MESSAGES
-*
-******************************************/
-#loading {
- position: fixed;
- width: 300px;
- height: 150px;
- text-align: center;
- left: 50%;
- top: 50%;
- margin: -75px 0 0 -150px;
-}
-#loading i {display: block; padding-bottom: 3px;}
-
-#messages {
- font-size: 13px;
- padding: 3px;
- margin: 0;
- word-wrap: break-word;
-}
-#newMessages {
- position: fixed;
- display: block;
- bottom: 0;
- right: 0;
- padding: 8px;
- background: #ddd;
- text-decoration: none;
- font-variant: small-caps;
- font-size: 1.1em;
- font-weight: bold;
- color: #333;
-}
-#newMessages:hover {background: #ccc;}
-#newMessages i {vertical-align: middle; padding-left: 3px;}
-#ping {
- position: fixed;
- top: 0;
- right: 80px;
- width: 45px;
- background: #ddd;
- height: 30px;
- padding: 8px 0 2px 0;
-}
-#ping i {display: block; text-align: center;}
-#ping .ms {
- display: block;
- text-align: center;
- font-size: 8pt;
- padding-top: 2px;
-}
-#userBar {
- position: fixed;
- top: 0;
- right: 0;
-}
-#userBar .subCell {
- background: #ddd;
- height: 30px;
- padding: 5px 0;
- display: block;
- color: #333;
- text-decoration: none;
- line-height: 28px;
- border-top: 1px solid #b4b4b4;
-}
-#userBar .subCell:hover {background: #ccc;}
-#userBar .toggle {
- width: 40px;
- background: #ccc;
- border-top: 0;
- float: right;
- text-align: center;
-}
-#userBar .sub {clear: both; display: none; width: 160px;}
-#userBar .sub.scroll {overflow-y: scroll;}
-#userBar .sub.subCell {padding: 3px 0 3px 8px; line-height: 30px; font-size: 0.9em; clear: both;}
-#userBar .sub span {
- display: block;
- line-height: 30px;
- float: left;
-}
-#userBar .sub i {
- display: block;
- padding: 0 5px;
- font-size: 1.1em;
- width: 22px;
- text-align: center;
- line-height: 30px;
- float: right;
-}
-#userBar .sub input {
- position: absolute;
- padding: 7px 5px;
- width: 121px;
- line-height: 30px;
- float: left;
-}
-#userBar .topCell {border-top: 0;}
-
-/* POPUPS */
-.popup {
- position: fixed;
- top: 50%;
- left: 50%;
- background: #ddd;
-}
-.popup .close {
- position: absolute;
- background: #aaa;
- top: 0;
- right: 0;
- color: #333;
- text-decoration: none;
- z-index: 2;
- padding: 0 10px;
- height: 30px;
- line-height: 30px;
-}
-.popup .close:hover {background: #999;}
-.popup .head {
- background: #999;
- color: #ddd;
- padding: 0 10px;
- height: 30px;
- line-height: 30px;
- text-transform: uppercase;
- font-size: 0.9em;
- font-weight: bold;
- border-bottom: 2px solid green;
-}
-.popup input {border: 1px solid #999; background: #fff; margin: 0; padding: 5px; outline: none; color: #333;}
-.popup input[type=text]:hover, .popup input[type=text]:active, .popup input[type=text]:focus {border-color: green;}
-.popup input[type=submit] {padding: 5px 10px; background: #999; color: #ddd; text-transform: uppercase; font-size: 0.9em; font-weight: bold;}
-.popup input[type=submit]:hover, .popup input[type=submit]:focus, .popup input[type=submit]:active {background: #aaa; cursor: pointer;}
-
-.changeFont {padding: 10px;}
-.changeFont a {display: block; text-decoration: none; padding: 3px; color: #333;}
-.changeFont a:hover {background: #ccc;}
-
-.highlightPopup {padding: 10px; text-align: center;}
-.highlightPopup input[type=text] {display: block; width: 215px; text-align: left; margin-top: 5px;}
-.highlightPopup input.highlightColor {background-color: #FFFF00;}
-.highlightPopup input.highlightTermSubmit {margin-top: 5px;}
-
-/* ADMIN CONTEXT MENU */
-.contextMenu {
- background-color: #ddd;
- position: fixed;
- margin: 2px;
- width: 150px;
-}
-.contextMenu a {
- display: block;
- padding: 2px 5px;
- text-decoration: none;
- color: #333;
-}
-
-.contextMenu a:hover {
- background-color: #ccc;
-}
-
-/* ADMIN FILTER MESSAGES MENU */
-.filterMessages {padding: 5px;}
-.filterMessages div {padding: 2px 0;}
-.filterMessages input {}
-.filterMessages label {}
-
-.icon-stack {height: 1em; line-height: 1em; width: 1em; vertical-align: middle; margin-top: -2px;}
-
-
-/*****************************************
-*
-* OUTPUT ACTUALLY RELATED TO MESSAGES
-*
-******************************************/
-
-/* MOTD */
-.motd {color: #638500; font-family: Verdana, sans-serif;}
-.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 {color: #638500; text-decoration: underline;}
-.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover {color: #638500;}
-
-/* ADD HERE FOR BOLD */
-.bold, .name, .prefix, .ooc, .looc, .adminooc, .admin, .medal, .yell {font-weight: bold;}
-
-/* ADD HERE FOR ITALIC */
-.italic, .italics, .emote {font-style: italic;}
-
-/* OUTPUT COLORS */
-.highlight {background: yellow;}
-
-h1, h2, h3, h4, h5, h6 {color: #0000ff;font-family: Georgia, Verdana, sans-serif;}
-h1.alert, h2.alert {color: #000000;}
-
-em {font-style: normal; font-weight: bold;}
-
-.ooc { font-weight: bold;}
-.adminobserverooc {color: #0099cc; font-weight: bold;}
-.adminooc {color: #700038; font-weight: bold;}
-
-.adminobserver {color: #996600; font-weight: bold;}
-.admin {color: #386aff; font-weight: bold;}
-
-.name { font-weight: bold;}
-
-.say {}
-.deadsay {color: #5c00e6;}
-.binarysay {color: #20c20e; background-color: #000000; display: block;}
-.binarysay a {color: #00ff00;}
-.binarysay a:active, .binarysay a:visited {color: #88ff88;}
-.radio {color: #008000;}
-.sciradio {color: #993399;}
-.comradio {color: #948f02;}
-.secradio {color: #a30000;}
-.medradio {color: #337296;}
-.engradio {color: #fb5613;}
-.suppradio {color: #a8732b;}
-.servradio {color: #6eaa2c;}
-.syndradio {color: #6d3f40;}
-.centcomradio {color: #686868;}
-.aiprivradio {color: #ff00ff;}
-.redteamradio {color: #ff0000;}
-.blueteamradio {color: #0000ff;}
-
-.yell { font-weight: bold;}
-
-.alert {color: #ff0000;}
-h1.alert, h2.alert {color: #000000;}
-
-.emote { font-style: italic;}
-.selecteddna {color: #ffffff; background-color: #001B1B}
-
-.attack {color: #ff0000;}
-.disarm {color: #990000;}
-.passive {color: #660000;}
-
-.userdanger {color: #ff0000; font-weight: bold; font-size: 24px;}
-.danger {color: #ff0000;}
-.warning {color: #ff0000; font-style: italic;}
-.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
-.announce {color: #228b22; font-weight: bold;}
-.boldannounce {color: #ff0000; font-weight: bold;}
-.greenannounce {color: #00ff00; font-weight: bold;}
-.rose {color: #ff5050;}
-.info {color: #0000CC;}
-.notice {color: #000099;}
-.boldnotice {color: #000099; font-weight: bold;}
-.adminnotice {color: #0000ff;}
-.adminhelp {color: #ff0000; font-weight: bold;}
-.unconscious {color: #0000ff; font-weight: bold;}
-.suicide {color: #ff5050; font-style: italic;}
-.green {color: #03ff39;}
-.nicegreen {color: #14a833;}
-.shadowling {color: #3b2769;}
-.cult {color: #960000;}
-
-.cultitalic {color: #960000; font-style: italic;}
-.cultbold {color: #960000; font-style: italic; font-weight: bold;}
-.cultboldtalic {color: #960000; font-weight: bold; font-size: 24px;}
-
-.cultlarge {color: #960000; font-weight: bold; font-size: 24px;}
-.narsie {color: #960000; font-weight: bold; font-size: 120px;}
-.narsiesmall {color: #960000; font-weight: bold; font-size: 48px;}
-.colossus {color: #7F282A; font-size: 40px;}
-.hierophant {color: #660099; font-weight: bold; font-style: italic;}
-.hierophant_warning {color: #660099; font-style: italic;}
-.purple {color: #5e2d79;}
-.holoparasite {color: #35333a;}
-
-.revennotice {color: #1d2953;}
-.revenboldnotice {color: #1d2953; font-weight: bold;}
-.revenbignotice {color: #1d2953; font-weight: bold; font-size: 24px;}
-.revenminor {color: #823abb}
-.revenwarning {color: #760fbb; font-style: italic;}
-.revendanger {color: #760fbb; font-weight: bold; font-size: 24px;}
-.umbra {color: #5000A0;}
-.umbra_emphasis {color: #5000A0; font-weight: bold; font-style: italic;}
-.umbra_large {color: #5000A0; font-size: 24px; font-weight: bold; font-style: italic;}
-
-.deconversion_message {color: #5000A0; font-size: 24px; font-style: italic;}
-
-.brass {color: #BE8700;}
-.heavy_brass {color: #BE8700; font-weight: bold; font-style: italic;}
-.large_brass {color: #BE8700; font-size: 24px;}
-.big_brass {color: #BE8700; font-size: 24px; font-weight: bold; font-style: italic;}
-.ratvar {color: #BE8700; font-size: 48px; font-weight: bold; font-style: italic;}
-.alloy {color: #42474D;}
-.heavy_alloy {color: #42474D; font-weight: bold; font-style: italic;}
-.nezbere_large {color: #42474D; font-size: 24px; font-weight: bold; font-style: italic;}
-.nezbere {color: #42474D; font-weight: bold; font-style: italic;}
-.nezbere_small {color: #42474D;}
-.sevtug_large {color: #AF0AAF; font-size: 24px; font-weight: bold; font-style: italic;}
-.sevtug {color: #AF0AAF; font-weight: bold; font-style: italic;}
-.sevtug_small {color: #AF0AAF;}
-.inathneq_large {color: #1E8CE1; font-size: 24px; font-weight: bold; font-style: italic;}
-.inathneq {color: #1E8CE1; font-weight: bold; font-style: italic;}
-.inathneq_small {color: #1E8CE1;}
-.nzcrentr_large {color: #DAAA18; font-size: 24px; font-weight: bold; font-style: italic;}
-.nzcrentr {color: #DAAA18; font-weight: bold; font-style: italic;}
-.nzcrentr_small {color: #DAAA18;}
-.neovgre_large {color: #6E001A; font-size: 24px; font-weight: bold; font-style: italic;}
-.neovgre {color: #6E001A; font-weight: bold; font-style: italic;}
-.neovgre_small {color: #6E001A;}
-
-.newscaster {color: #800000;}
-.ghostalert {color: #5c00e6; font-style: italic; font-weight: bold;}
-
-.alien {color: #543354;}
-.noticealien {color: #00c000;}
-.alertalien {color: #00c000; font-weight: bold;}
-.changeling {color: #800080; font-style: italic;}
-
-.spider {color: #4d004d;}
-
-.interface {color: #330033;}
-
-.sans {font-family: "Comic Sans MS", cursive, sans-serif;}
-.papyrus {font-family: "Papyrus", cursive, sans-serif;}
-.robot {font-family: "Courier New", cursive, sans-serif;}
-
-.command_headset {font-weight: bold; font-size: 24px;}
-.small {font-size: 8px;}
-.big {font-size: 24px;}
-.reallybig {font-size: 32px;}
-.extremelybig {font-size: 40px;}
-.greentext {color: #00FF00; font-size: 24px;}
-.redtext {color: #FF0000; font-size: 24px;}
-.clown {color: #FF69Bf; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
-.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
-.spooky {color: #FF6100;}
-.velvet {color: #660015; font-weight: bold; animation: velvet 5000ms infinite;}
-@keyframes velvet {
- 0% { color: #400020; }
- 40% { color: #FF0000; }
- 50% { color: #FF8888; }
- 60% { color: #FF0000; }
- 100% { color: #400020; }
-}
-
-.hypnophrase {color: #202020; font-weight: bold; animation: hypnocolor 1500ms infinite;}
-@keyframes hypnocolor {
- 0% { color: #202020; }
- 25% { color: #4b02ac; }
- 50% { color: #9f41f1; }
- 75% { color: #541c9c; }
- 100% { color: #7adbf3; }
-}
-
-.phobia {color: #dd0000; font-weight: bold; animation: phobia 750ms infinite;}
-@keyframes phobia {
- 0% { color: #f75a5a; }
- 50% { color: #dd0000; }
- 100% { color: #f75a5a; }
-}
-
-.icon {height: 1em; width: auto;}
-
-.memo {color: #638500; text-align: center;}
-.memoedit {text-align: center; font-size: 16px;}
-.abductor {color: #800080; font-style: italic;}
-.mind_control {color: #A00D6F; font-size: 3; font-weight: bold; font-style: italic;}
-.slime {color: #00CED1;}
-.drone {color: #848482;}
-.monkey {color: #975032;}
-.swarmer {color: #2C75FF;}
-.resonate {color: #298F85;}
-
-.monkeyhive {color: #774704;}
-.monkeylead {color: #774704; font-size: 2;}
-
-.connectionClosed, .fatalError {background: red; color: white; padding: 5px;}
-.connectionClosed.restored {background: green;}
-.internal.boldnshit {color: blue; font-weight: bold;}
-
-/* HELPER CLASSES */
-.text-normal {font-weight: normal; font-style: normal;}
-.hidden {display: none; visibility: hidden;}/*****************************************
-*
-* GLOBAL STYLES
-*
-******************************************/
-html, body {
- padding: 0;
- margin: 0;
- height: 100%;
- color: #000000;
-}
-body {
- background: #E0E0E0; /*CIT CHANGE - darkens chatbox a lil*/
- font-family: Verdana, sans-serif;
- font-size: 9pt;
- line-height: 1.2;
- overflow-x: hidden;
- overflow-y: scroll;
- word-wrap: break-word;
-}
-
-em {
- font-style: normal;
- font-weight: bold;
-}
-
-img {
- margin: 0;
- padding: 0;
- line-height: 1;
- -ms-interpolation-mode: nearest-neighbor;
- image-rendering: pixelated;
-}
-img.icon {
- height: 1em;
- min-height: 16px;
- width: auto;
- vertical-align: bottom;
-}
-
-
-.r:before { /* "repeated" badge class for combined messages */
- content: 'x';
-}
-.r {
- display: inline-block;
- min-width: 0.5em;
- font-size: 0.7em;
- padding: 0.2em 0.3em;
- line-height: 1;
- color: white;
- text-align: center;
- white-space: nowrap;
- vertical-align: middle;
- background-color: crimson;
- border-radius: 10px;
-}
-
-a {color: #0000ff;}
-a.visited {color: #ff00ff;}
-a:visited {color: #ff00ff;}
-a.popt {text-decoration: none;}
-
-/*****************************************
-*
-* OUTPUT NOT RELATED TO ACTUAL MESSAGES
-*
-******************************************/
-#loading {
- position: fixed;
- width: 300px;
- height: 150px;
- text-align: center;
- left: 50%;
- top: 50%;
- margin: -75px 0 0 -150px;
-}
-#loading i {display: block; padding-bottom: 3px;}
-
-#messages {
- font-size: 13px;
- padding: 3px;
- margin: 0;
- word-wrap: break-word;
-}
-#newMessages {
- position: fixed;
- display: block;
- bottom: 0;
- right: 0;
- padding: 8px;
- background: #ddd;
- text-decoration: none;
- font-variant: small-caps;
- font-size: 1.1em;
- font-weight: bold;
- color: #333;
-}
-#newMessages:hover {background: #ccc;}
-#newMessages i {vertical-align: middle; padding-left: 3px;}
-#ping {
- position: fixed;
- top: 0;
- right: 80px;
- width: 45px;
- background: #ddd;
- height: 30px;
- padding: 8px 0 2px 0;
-}
-#ping i {display: block; text-align: center;}
-#ping .ms {
- display: block;
- text-align: center;
- font-size: 8pt;
- padding-top: 2px;
-}
-#userBar {
- position: fixed;
- top: 0;
- right: 0;
-}
-#userBar .subCell {
- background: #ddd;
- height: 30px;
- padding: 5px 0;
- display: block;
- color: #333;
- text-decoration: none;
- line-height: 28px;
- border-top: 1px solid #b4b4b4;
-}
-#userBar .subCell:hover {background: #ccc;}
-#userBar .toggle {
- width: 40px;
- background: #ccc;
- border-top: 0;
- float: right;
- text-align: center;
-}
-#userBar .sub {clear: both; display: none; width: 160px;}
-#userBar .sub.scroll {overflow-y: scroll;}
-#userBar .sub.subCell {padding: 3px 0 3px 8px; line-height: 30px; font-size: 0.9em; clear: both;}
-#userBar .sub span {
- display: block;
- line-height: 30px;
- float: left;
-}
-#userBar .sub i {
- display: block;
- padding: 0 5px;
- font-size: 1.1em;
- width: 22px;
- text-align: center;
- line-height: 30px;
- float: right;
-}
-#userBar .sub input {
- position: absolute;
- padding: 7px 5px;
- width: 121px;
- line-height: 30px;
- float: left;
-}
-#userBar .topCell {border-top: 0;}
-
-/* POPUPS */
-.popup {
- position: fixed;
- top: 50%;
- left: 50%;
- background: #ddd;
-}
-.popup .close {
- position: absolute;
- background: #aaa;
- top: 0;
- right: 0;
- color: #333;
- text-decoration: none;
- z-index: 2;
- padding: 0 10px;
- height: 30px;
- line-height: 30px;
-}
-.popup .close:hover {background: #999;}
-.popup .head {
- background: #999;
- color: #ddd;
- padding: 0 10px;
- height: 30px;
- line-height: 30px;
- text-transform: uppercase;
- font-size: 0.9em;
- font-weight: bold;
- border-bottom: 2px solid green;
-}
-.popup input {border: 1px solid #999; background: #fff; margin: 0; padding: 5px; outline: none; color: #333;}
-.popup input[type=text]:hover, .popup input[type=text]:active, .popup input[type=text]:focus {border-color: green;}
-.popup input[type=submit] {padding: 5px 10px; background: #999; color: #ddd; text-transform: uppercase; font-size: 0.9em; font-weight: bold;}
-.popup input[type=submit]:hover, .popup input[type=submit]:focus, .popup input[type=submit]:active {background: #aaa; cursor: pointer;}
-
-.changeFont {padding: 10px;}
-.changeFont a {display: block; text-decoration: none; padding: 3px; color: #333;}
-.changeFont a:hover {background: #ccc;}
-
-.highlightPopup {padding: 10px; text-align: center;}
-.highlightPopup input[type=text] {display: block; width: 215px; text-align: left; margin-top: 5px;}
-.highlightPopup input.highlightColor {background-color: #FFFF00;}
-.highlightPopup input.highlightTermSubmit {margin-top: 5px;}
-
-/* ADMIN CONTEXT MENU */
-.contextMenu {
- background-color: #ddd;
- position: fixed;
- margin: 2px;
- width: 150px;
-}
-.contextMenu a {
- display: block;
- padding: 2px 5px;
- text-decoration: none;
- color: #333;
-}
-
-.contextMenu a:hover {
- background-color: #ccc;
-}
-
-/* ADMIN FILTER MESSAGES MENU */
-.filterMessages {padding: 5px;}
-.filterMessages div {padding: 2px 0;}
-.filterMessages input {}
-.filterMessages label {}
-
-.icon-stack {height: 1em; line-height: 1em; width: 1em; vertical-align: middle; margin-top: -2px;}
-
-
-/*****************************************
-*
-* OUTPUT ACTUALLY RELATED TO MESSAGES
-*
-******************************************/
-
-/* MOTD */
-.motd {color: #638500; font-family: Verdana, sans-serif;}
-.motd h1, .motd h2, .motd h3, .motd h4, .motd h5, .motd h6 {color: #638500; text-decoration: underline;}
-.motd a, .motd a:link, .motd a:visited, .motd a:active, .motd a:hover {color: #638500;}
-
-/* ADD HERE FOR BOLD */
-.bold, .name, .prefix, .ooc, .looc, .adminooc, .admin, .medal, .yell {font-weight: bold;}
-
-/* ADD HERE FOR ITALIC */
-.italic, .italics, .emote {font-style: italic;}
-
-/* OUTPUT COLORS */
-.highlight {background: yellow;}
-
-h1, h2, h3, h4, h5, h6 {color: #0000ff;font-family: Georgia, Verdana, sans-serif;}
-h1.alert, h2.alert {color: #000000;}
-
-em {font-style: normal; font-weight: bold;}
-
-.ooc { font-weight: bold;}
-.adminobserverooc {color: #0099cc; font-weight: bold;}
-.adminooc {color: #700038; font-weight: bold;}
-
-.adminsay {color: #FF4500; font-weight: bold;}
-.admin {color: #386aff; font-weight: bold;}
-
-.name { font-weight: bold;}
-
-.say {}
-.deadsay {color: #5c00e6;}
-.binarysay {color: #20c20e; background-color: #000000; display: block;}
-.binarysay a {color: #00ff00;}
-.binarysay a:active, .binarysay a:visited {color: #88ff88;}
-.radio {color: #008000;}
-.sciradio {color: #993399;}
-.comradio {color: #948f02;}
-.secradio {color: #a30000;}
-.medradio {color: #337296;}
-.engradio {color: #fb5613;}
-.suppradio {color: #a8732b;}
-.servradio {color: #6eaa2c;}
-.syndradio {color: #6d3f40;}
-.centcomradio {color: #686868;}
-.aiprivradio {color: #ff00ff;}
-.redteamradio {color: #ff0000;}
-.blueteamradio {color: #0000ff;}
-
-.yell { font-weight: bold;}
-
-.alert {color: #ff0000;}
-h1.alert, h2.alert {color: #000000;}
-
-.emote { font-style: italic;}
-.selecteddna {color: #ffffff; background-color: #001B1B}
-
-.attack {color: #ff0000;}
-.disarm {color: #990000;}
-.passive {color: #660000;}
-
-.userdanger {color: #ff0000; font-weight: bold; font-size: 24px;}
-.danger {color: #ff0000;}
-.warning {color: #ff0000; font-style: italic;}
-.boldwarning {color: #ff0000; font-style: italic; font-weight: bold}
-.announce {color: #228b22; font-weight: bold;}
-.boldannounce {color: #ff0000; font-weight: bold;}
-.greenannounce {color: #00ff00; font-weight: bold;}
-.rose {color: #ff5050;}
-.info {color: #0000CC;}
-.notice {color: #000099;}
-.boldnotice {color: #000099; font-weight: bold;}
-.adminnotice {color: #0000ff;}
-.adminhelp {color: #ff0000; font-weight: bold;}
-.unconscious {color: #0000ff; font-weight: bold;}
-.suicide {color: #ff5050; font-style: italic;}
-.green {color: #03ff39;}
-.nicegreen {color: #14a833;}
-.userlove {color: #FF1493; font-style: italic; font-weight: bold; text-shadow: 0 0 6px #ff6dbc;}
-.love {color: #ff006a; font-style: italic; text-shadow: 0 0 6px #ff6d6d;}
-.shadowling {color: #3b2769;}
-.cult {color: #960000;}
-
-.cultitalic {color: #960000; font-style: italic;}
-.cultbold {color: #960000; font-style: italic; font-weight: bold;}
-.cultboldtalic {color: #960000; font-weight: bold; font-size: 24px;}
-
-.cultlarge {color: #960000; font-weight: bold; font-size: 24px;}
-.narsie {color: #960000; font-weight: bold; font-size: 120px;}
-.narsiesmall {color: #960000; font-weight: bold; font-size: 48px;}
-.colossus {color: #7F282A; font-size: 40px;}
-.hierophant {color: #660099; font-weight: bold; font-style: italic;}
-.hierophant_warning {color: #660099; font-style: italic;}
-.purple {color: #5e2d79;}
-.holoparasite {color: #35333a;}
-
-.revennotice {color: #1d2953;}
-.revenboldnotice {color: #1d2953; font-weight: bold;}
-.revenbignotice {color: #1d2953; font-weight: bold; font-size: 24px;}
-.revenminor {color: #823abb}
-.revenwarning {color: #760fbb; font-style: italic;}
-.revendanger {color: #760fbb; font-weight: bold; font-size: 24px;}
-.umbra {color: #5000A0;}
-.umbra_emphasis {color: #5000A0; font-weight: bold; font-style: italic;}
-.umbra_large {color: #5000A0; font-size: 24px; font-weight: bold; font-style: italic;}
-
-.deconversion_message {color: #5000A0; font-size: 24px; font-style: italic;}
-
-.brass {color: #BE8700;}
-.heavy_brass {color: #BE8700; font-weight: bold; font-style: italic;}
-.large_brass {color: #BE8700; font-size: 24px;}
-.big_brass {color: #BE8700; font-size: 24px; font-weight: bold; font-style: italic;}
-.ratvar {color: #BE8700; font-size: 48px; font-weight: bold; font-style: italic;}
-.alloy {color: #42474D;}
-.heavy_alloy {color: #42474D; font-weight: bold; font-style: italic;}
-.nezbere_large {color: #42474D; font-size: 24px; font-weight: bold; font-style: italic;}
-.nezbere {color: #42474D; font-weight: bold; font-style: italic;}
-.nezbere_small {color: #42474D;}
-.sevtug_large {color: #AF0AAF; font-size: 24px; font-weight: bold; font-style: italic;}
-.sevtug {color: #AF0AAF; font-weight: bold; font-style: italic;}
-.sevtug_small {color: #AF0AAF;}
-.inathneq_large {color: #1E8CE1; font-size: 24px; font-weight: bold; font-style: italic;}
-.inathneq {color: #1E8CE1; font-weight: bold; font-style: italic;}
-.inathneq_small {color: #1E8CE1;}
-.nzcrentr_large {color: #DAAA18; font-size: 24px; font-weight: bold; font-style: italic;}
-.nzcrentr {color: #DAAA18; font-weight: bold; font-style: italic;}
-.nzcrentr_small {color: #DAAA18;}
-.neovgre_large {color: #6E001A; font-size: 24px; font-weight: bold; font-style: italic;}
-.neovgre {color: #6E001A; font-weight: bold; font-style: italic;}
-.neovgre_small {color: #6E001A;}
-
-.newscaster {color: #800000;}
-.ghostalert {color: #5c00e6; font-style: italic; font-weight: bold;}
-
-.alien {color: #543354;}
-.noticealien {color: #00c000;}
-.alertalien {color: #00c000; font-weight: bold;}
-.changeling {color: #800080; font-style: italic;}
-
-.spider {color: #4d004d;}
-
-.interface {color: #330033;}
-
-.sans {font-family: "Comic Sans MS", cursive, sans-serif;}
-.papyrus {font-family: "Papyrus", cursive, sans-serif;}
-.robot {font-family: "Courier New", cursive, sans-serif;}
-
-.command_headset {font-weight: bold; font-size: 24px;}
-.small {font-size: 8px;}
-.big {font-size: 24px;}
-.reallybig {font-size: 32px;}
-.extremelybig {font-size: 40px;}
-.greentext {color: #00FF00; font-size: 24px;}
-.redtext {color: #FF0000; font-size: 24px;}
-.clown {color: #FF69Bf; font-size: 24px; font-family: "Comic Sans MS", cursive, sans-serif; font-weight: bold;}
-.hypnophrase {color: #202020; font-weight: bold; animation: hypnocolor 1500ms infinite;}
-@keyframes hypnocolor {
- 0% { color: #202020; }
- 25% { color: #4b02ac; }
- 50% { color: #9f41f1; }
- 75% { color: #541c9c; }
- 100% { color: #7adbf3; }
-}
-
-.phobia {color: #dd0000; font-weight: bold; animation: phobia 750ms infinite;}
-@keyframes phobia {
- 0% { color: #f75a5a; }
- 50% { color: #dd0000; }
- 100% { color: #f75a5a; }
-}
-.his_grace {color: #15D512; font-family: "Courier New", cursive, sans-serif; font-style: italic;}
-
-.icon {height: 1em; width: auto;}
-
-.memo {color: #638500; text-align: center;}
-.memoedit {text-align: center; font-size: 16px;}
-.abductor {color: #800080; font-style: italic;}
-.mind_control {color: #A00D6F; font-size: 3; font-weight: bold; font-style: italic;}
-.slime {color: #00CED1;}
-.drone {color: #848482;}
-.monkey {color: #975032;}
-.swarmer {color: #2C75FF;}
-.resonate {color: #298F85;}
-
-.monkeyhive {color: #774704;}
-.monkeylead {color: #774704; font-size: 2;}
-
-.connectionClosed, .fatalError {background: red; color: white; padding: 5px;}
-.connectionClosed.restored {background: green;}
-.internal.boldnshit {color: blue; font-weight: bold;}
-
-/* HELPER CLASSES */
-.text-normal {font-weight: normal; font-style: normal;}
-.hidden {display: none; visibility: hidden;}
diff --git a/html/changelog.html b/html/changelog.html
index 31935bd1c1..61bc43a99b 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -35,15 +35,15 @@
- Current Project Maintainers: deathride58, LetterJay, kevinz000
+ Current Project Maintainers: deathride58, LetterJay, kevinz000, BlackMajor, Izzy Currently Active GitHub contributor list:-Click Here-
- Coders: Poojawa, deathride58, kevinz000, Trilbyspaceclone, nik707, as well as the /tg/ crew.
+ Coders: Fermis, Poojawa, deathride58, kevinz000, Trilbyspaceclone, nik707, Ghommie as well as the /tg/ crew. Spriters: Michiyamenotehifunana, CameronWoof, and the folks who contributed to /tg/ station project. Sounds: /tg/ Sound crew. Main Testers: You poor saps, our player base. Thanks to: /tg/station, Baystation 12, /vg/station, NTstation, CDK Station devs, FacepunchStation, GoonStation devs, the original SpaceStation developers and Invisty for the title image. Also a thanks to anybody who has contributed who is not listed here :( Ask to be added here on irc.
Have a bug to report? Visit our Issue Tracker.
- Please ensure that the bug has not already been reported upstream and use the template provided here!.
+ Please ensure that the bug has not already been reported upstream and use the template provided here!.
@@ -56,1487 +56,2065 @@
-->
-
27 September 2018
-
Alexch2 updated:
+
04 November 2019
+
4dplanner, MMiracles updated:
-
Fixes tons of typos related to integrated circuits.
-
Re-writes the descriptions of a few parts of integrated circuits.
+
Wizard shapeshift now converts damage taken while transformed
+
transform spell transfers damage correctly instead of healing most of the time
+
0% simplemob health maps to 0 carbon health, 100% simplemob to 100% carbon
+
transforming to a form with brute resistance no longer heals you
+
transforming back to a species with brute resistance no longer heals you
-
Armhulen code, Keekenox sprites and S_____ as the ideas guy :roll_eyes: updated:
+
AdmiralPancakes1 updated:
-
New drinks: Peppermint Patty and the Candyland Extract!!
+
Cryo cell shortcuts: alt-click toggles the doors, ctrl-click toggles the power
-
Astatineguy12 updated:
+
Alonefromhell updated:
-
The experimentor is less likely to produce food when it transforms an item
-
The experimentor no longer breaks when the toxic waste malfunction occurs multiple times and isn't cleaned up
-
The experimentor irridiate function actually chooses what item to make properly rather than picking from the start of the list
-
The mime blockade spell now shows up under the right tab
+
Ported Oracle UI, a framework for self-updating and neat UI's
+
Paper now uses OUI
+
Bins now use OUI
+
fixes tootip offset
-
Beachsprites updated:
+
AnalWerewolf updated:
-
added directional beach sprites
+
Fritz plushie
+
Donor item
-
Big Tobacco updated:
+
Anonymous updated:
-
Cheap lighters now come in four different shapes and Zippos can have one of four different designs, collect them all and improve our sales!
-
All existing lighter sprites have been given a face-lift and the flames are now subtly animated.
-
Cheap lighters now use a fixed list of 16 colors to pick from instead of using totally randomized colors.
-
Cigar cases have been tweaked to be a bit smaller and to have a modified design.
-
Cohiba Robusto and Havanan cigars now use separate case sprites from the generic premium cigar cases.
+
More crusader armor variants to pick from armament: Teutonic and Hospitaller.
+
+
Arturlang updated:
+
+
You can now use CTRL and ALT click on pumps and filters to toggle them on and off and max their output respectively
+
You can now use RPDs on windows and grilles.
+
The RD can now suplex a immovable rod. Good fucking luck.
+
Fixes high alert ERT suit sprites. You can see them now!
+
Traitor codewords are now highlighted for traitors.
+
You can now examine pumps filters and mixers to see if you can use CTRL and Alt click on them.
+
Fixes brain damage/trauma healing nanites so they actually work while there are only traumas.
+
Advanced toxin filtration nanites now heal slimes
+
+
Bhijn updated:
+
+
It's now possible to forcefully eject the occupants of a dogborg's sleeper by using a crowbar on them. This action is instant.
+
Resist values for dogborg sleepers have been adjusted. The baseline has been decreased from 30 seconds to 15 seconds. Medihound sleepers have a resist timer of 3 seconds. Sechound sleepers retain a resist timer of 30 seconds.
+
It now takes 10 full seconds to insert people into your sleeper. This should hopefully give people some more room to breathe and react to a dogborg attempting to sleeper someone either for no reason or in a way that violates law 2.
+
Warp whistles no longer grant permanent invulnerability and invisibility
+
You can now actually use the resist hotkey to resist out of handcuffs. Woah, revolutionary
+
the `!tgs poly` command now actually works
+
Poly now has a 0.01% chance per squawk to speak through the TGS relay.
+
The point production mode of radiation collectors has been reverted to the original behavior of using all of the stored power every process cycle instead of just 4% of it
+
Radiation collectors now display the amount of power/research points they're producing per minute rather than per process cycle, which should hopefully clear up a lot of confusion.
+
Radiation collectors also display what's happening to the gas within them, which should make it a lot more obvious as to how you get tritium.
+
Security borgs and K9s are now only available during red alert or higher.
+
Headmins or other folks with access to the server's config can choose the minimum alert level for secborgs to be chosen via the MINIMUM_SECBORG_ALERT config option. See the default game_options.txt for more info.
+
The server no longer attempts to check if the CID matches the IP of any bans, or if the IP matches any CIDs of any active bans, during client analyzation
+
Vampires can now only ventcrawl in bat form if their blood level is below the bad blood volume (224 blood total)
+
Vampires now only take 5 burn per mob life cycle while within chapel areas, down from the original 20 burn per life cycle.
+
K9 pounces have received a minor rework. It now has an effective cooldown of 2.5 seconds, can now only deal up to 120 staminaloss, deals a maximum of 80 stamloss on hit, has a spoolup of half a second, and now has telegraphing in the form of a quiet noise.
+
K9s now only have 80 health
+
Secborgs (but not k9s) now have a hybrid taser. This can be toggled via server config.
+
The disabler cooler upgrade now applies to all energy-based firearms for borgs
+
Dogborg jaws are now capable of incapacitating targets if using help intent. This deals a hard stun depending on how much staminaloss the target has, and whether or not they're resting. This behavior can be toggled via server config.
+
K9 jaws now have 15 force, up from their nerfed 10 force.
+
Borg flashes regained their ability to cause knockdown. This can be toggled via server config.
+
The WEAKEN_SECBORG config option will disable the new dogborg jaws mechanic and make secborgs spawn with a standard disabler.
+
The DISABLE_BORG_FLASH_KNOCKDOWN will disable the ability for borg flashes to knockdown.
+
Jukeboxes now have 6 audio channels available to them, up from the previous accidental 2 and previously intended 5 channels.
+
Jukeboxes now work again on clients running versions higher than 512.1459.
+
People will no longer have their ears consumed by an eldritch god if multiple jukeboxes are active and the first jukebox in the jukebox list stops playing, then tries to play again
+
Instead of the debug text for invalid jukebox behavior being printed to world, the debug text is now restricted to the runtime panel.
+
+
BurgerB updated:
+
+
Tweaked the UI of the loadout to be less cluttered due to an issue with formatting.
+
+
BurgerBB updated:
+
+
Adds the bonermeter; a device that measures arousal based statistics.
+
Added a new input to the electrostimulator that controls the strength of the shock. It accepts negative inputs which reduce arousal. Added a new output to the electrostimulator that displays the amount of arousal gained.
+
Rebalanced the electro-stimulator to be less spammy by giving it a 2.5 second enforced cooldown per circuit contraption. Increased the complexity of electro stimulator from 10 to 15.
+
Reworked the Vent Clog event to spray smoke instead of foam, also made it shoot smoke over time instead through each vent instead of all at once.
+
Increased the spawn area of the City of Cogs (Reebe). This does not affect the area in which builders can build.
+
Significantly tweaks the Wizard race transformation event to be less unreasonably troublesome.
+
Adds a new 0 cost trait that makes you immune* to Crocin and Hexacrocin
+
Tweaks how slurring works so it's more of a gradual change into slurring instead of immediate.
+
Slurring is now directly proportional to your drunkenness, with other sources of slur being added on top of it.
+
Bras are now separate from underwear, meaning you can mix and match bras if you're into that.
+
Men can wear female accessory clothing, and females can wear men accessory clothing. It's not a fetish, mom, it's PROGRESSIVE.
+
Reorganized accessories into their own files to prevent a massive 1000 line file.
+
i'm 10% sure that merging this PR will cause preference corruption sooooooooooo I just need to hear from @deathride58 or perhaps someone else on how much damage this could possibly do.
+
Tweaked penis.
+
Rebalanced penis.
+
Added the following reagents to the common list of vent clog reagents: ~~Cooking Oil~~, ~~Frost Oil~~, Sodium Chloride, Corn Oil, Uranium, Carpet, Firefighting Foam, semen, femcum, tear juice, strange reagent, ~~spraytan~~.
+
Vent Clog smoke emits the same transparent smoke as a smoke machine, including how much it transfers. Vent Clogs also do not trigger in areas deemed "Safe" in code, such as in the dorms or trusted areas where dangerous things shouldn't occur.
+
Adds additional random brain damage text
+
Adds penis enlargement pills.
+
Adds Stun Circuit and Pneumatic Cannon Integrated Circuits
+
Fixed extinguisher and smoke circuits not accepting any reagents.
+
Adds a few important clockcult tips.
+
Added Mech Sensors, a brass-created trap that activates when a mech not controlled by a cultist crosses it.
+
Added power nullifiers, an emp trap that emps everything in a 3x3 area, with the center suffering a heavy EMP.
+
Brass Skewers now deal 50 damage to mechs.
+
Ass slapping only works if you're actually behind the target. Ass slapping now respects disarm blocking. You can no longer face/ass slap someone on an intent other than help, unless they are also face/ass slapping.
+
Fixed ass and face slapping grammar.
+
Adds meh effects for ass and face slapping.
+
"Unwillingly" eating food now sends a warning message instead of a notice. Unable to stuff food down your throat sends a danger message instead of a warning message.
+
Adds clockwork reflectors, a fragile anti-laser reflection shield object that can be constructed for 10 brass sheets. Upon firing on the object in the direction where it is shielded, it ricochets the bullet off of it relative to the shooting angle.
+
Renames some windows in the build menu for consistency.
+
Clockwork Cult walls can no longer be deconstructed by RCDs when heated.
+
Adds several new toy loot to the arcade machine.
+
Rebalanced the arcade machine loot. Battlemachines now have a 0.5 second delay instead of a second delay between actions.
+
Fixed a bug that would not allow the one in a million pulse rifle to spawn.
+
Adds a new trait "Buns of Steel" that makes you immune to the effects of ass slapping, and temporarily makes the user's arm useless like a stun baton hit. It costs 0 points.
+
Ass slapping blowback from the Buns of Steel perk now deals 20 stamina damage instead of 50, and no brute damage.
+
Gamemode voting results are displayed at the end-round screen.
+
Cloning no longer gives you positive mutations, but a chance for a negative one. Cloning has a chance to "scramble" your visual DNA.
+
Chestbursters no longer give and remove your brain. They just disembowel and kill you now.
+
Fixes WarOps miscalculating players.
+
Activating the nuclear device during war-ops informs the crew of the nuke's position.
+
The alert level is displayed at the job selection screen.
+
Central Command informs you when a Meteor Storm is about to hit 5 to 10 minutes before it happens.
+
+
BurgerLUA updated:
+
+
Added a new framework for reagents. Reagents can now have a bool that determines if it can be detected by handheld medical analyzers. Currently only the changeling sting chemical does this.
+
Made changeling transformation string last between 10-15 minutes. Lowered the dna cost of changeling sting from 3 dna to 2 dna. Lowered the chemical cost from 50 to 10. Lowered the loudness from 2 to 1. Changeling sting transformation can be removed via high doses of calomel.
+
Fixed most reagents having a placeholder color.
+
Fixed autolathe wires not correctly shocking you when pulsed.
+
Rebalanced special jetpacks.
+
+
CalamaBanana updated:
+
+
Added Deer taur
+
Added Elf ears to mammals
CameronWoof updated:
-
Quartermaster added to the list of changeling and traitor restricted jobs
+
Medihounds now have rollerbeds for non-vore patient transport
+
The closed O2 crate now uses the same color scheme as the open one
+
air alarms are green now instead of blue when the atmosphere is ideal
+
Hexacrocin overdose no longer causes climaxes
+
Altered the icons for inventory backplates. Sleek! Stylish! New!
+
Attaching a beaker that contains water to an IV stand no longer causes a visual glitch
+
Fluid-producing sexual organs no longer start full
+
Sexual organ fluid capacity decreased from 50 to 15
+
Sexual organ production rate decreased from 5u to 0.035u per two seconds.
+
Sexual fluid decals no longer contain reagents
+
Sexual fluids cannot by synthesized (e.g., by the Odysseus)
-
CitadelStationBot updated:
+
CdrCross updated:
-
The faint echoes of maracas grows louder, as if a past spirit once forgotten has come back with a vengeance...
-
Removing an ID card from a wallet now properly removes its visual and accesses.
-
You may now take unlimited neutral and negative quirks
-
the walls on the crashed abductor ship ruin in lavaland can now be broken down
-
Pipe icons in the RPD now show properly in older versions of IE.
-
Removing an ID from a PDA in a backpack no longer hides the ID until something else updates.
-
Opening and closing airlocks repeatedly no longer stacks queued autocloses.
-
Mindswapping with someone else no longer forces ambient occlusion on.
-
Admin AI interaction now works properly on firelocks.
-
IRV polls now use the same version of jQuery as everything else.
-
You can now view your last round end report window with the "Your last round" verb in the OOC tab
-
Hydroponics trays can no longer be deconstructed with their panels closed or unanchored while irrigated.
-
Frames for machines which do not require being anchored can now be un/anchored after the circuit has been added.
-
Fix "Your the wormhole jaunter" when a wormhole jaunter saves you from a chasm.
-
Analyzers can now scan all kinds of atmospheric machinery - unary, binary, ternary, quaternary, you name it. This means stuff like gas pumps, gas mixers, vents and so forth can be analyzed.
-
Analyzers now show temperature in kelvin as well as celsius.
-
Analyzers now show total mole count, volume, and mole count of all gases.
-
Analyzers show everything at slightly higher degrees of precision.
-
Any anomaly core can now be deconstructed for a one time boost of 10k points in the deconstructive analyzer.
-
Chasms no longer drop mobs buckled to undroppable mobs or objects.
-
Digital valves are once again operable by silicons.
-
Field generators are once again operable by adjacent cyborgs.
-
Entertainment monitors now view the real Thunderdome rather than the template.
-
Flipping and then rotating trinary pipe fittings no longer causes their icon to mismatch what they will become when wrenched.
-
RPD tooltips for flippable trinary components have been corrected.
-
The green overlay indicating where a map template will be placed is no longer invisible on space turfs.
-
Frost spiders now correctly inject frost oil on bite.
-
Inserting materials into protolathes with telekinesis is now possible.
-
Telekinesis no longer teleports items removed from deep fryers, constructed sandbags, and leftover materials not inserted into lathes.
-
Telekinetic sparkles now appear in the correct place when clicking on a turf and when clicking in the fog of war in widescreen.
-
Telekinetically adjusting power tools no longer causes them to exit the universe.
-
Examining a telekinetic grab in-hand will now examine the grabbed object.
-
Non-harmfully placing someone who is resting on a table no longer makes them get up.
-
The disco machine no longer lags the chat by spamming "You are now resting!" messages.
-
Clicking on the viewport to focus it no longer leaves the input bar red.
-
Running diagonally into space now properly continues the diagonal movement in zero-gravity.
-
Moving diagonally past delivery chutes, transit tube pods, &c. no longer causes your camera to be stuck on them.
-
The limit of monkey's spawned via monkey cubes is now configurable
-
Fixes cyborgs not being able to use two-handed modules while other modules are equipped.
-
Pubby's auxiliary mining base now works again.
-
The overlay effects of cult flooring are now on the floor plane, fixing their odd ambient occlusion appearance.
-
Cloning no longer breaks a character's connection to their family heirloom.
-
Beam rifle tracers no longer fall into chasms.
-
Vomiting on the same tile a second time no deletes the vomited reagents.
-
fixed the clockwork helmet not dropping to ground when used by non-clock cultists
-
The base machinery type is now anchored by default.
-
PDA style now gets loaded correctly.
-
Switching mobs into/out of a mech (by VR, ghosting, or mindswap) no longer improperly applies the mech's cursor.
-
roboticists have access to R&D windoors
-
switched the type of the space suit on the syndicate shuttle
-
fixed hydroponics tray weed light staying on when removing weeds with integrated circuits
-
Atom initialization and icon smoothing no longer race, causing late-loading mineral turfs to have no icon.
-
Faceless persons no longer "melt their face off" in energy gun suicides.
-
The Lightning Bolt spell now works again.
-
Vehicle speed changes now happen immediately instead of on the next movement cycle
-
Picture-in-picture objects now are no longer overlapped by other certain objects
-
A pAI dying while in holoform no longer deletes the card, instead merely emptying it.
-
The thermal sight benefits of lantern wisps no longer disappear if you change glasses.
-
sandstone wall sprite for indestructible object
-
Stabilized gold extracts now respawn the familiar properly.
-
Stabilized gold familiars retain the proper languages even after respawning.
-
Stabilized gold familiars can be renamed and have their positions reset at will.
-
Pulling objects diagonally no longer causes them to flail about when changing directions.
-
Riders are no longer left behind if you move while pulling something that has since been anchored.
-
Fire alarms now redden all the room's lights, and emit light themselves, rather than applying an area-wide overlay.
-
Fire alarms no longer visually conflict with radiation storms.
-
Plasmamen now receive their suit and internals when entering VR.
-
Deaf people can no longer hear cyborg system error alarms.
-
Lockboxes are now actually locked again.
-
Legion cores and admin revives now heal confusion.
-
checks to see if bullets are deleted if they are the ammo type and the bullet chambered.
-
Capitalization, propriety, and plurality on turfs have been improved.
-
Unbreakable ladders are now left behind when shuttles move.
-
Players who edited a circuit assembly can scan it as a ghost.
-
It is no longer possible to pull the mirages images at space transitions, and some other abstract effects.
-
Moving large amounts of items with bluespace launchpads no longer creates a laggy amount of sparks.
-
The escape pod hallways on MetaStation and DeltaStation now have air again.
-
It is no longer possible to repair cyborg headlamps even when their panel is closed.
-
Item fortification scrolls no longer add multiple prefixes when applied to the same item.
-
The blob core (and only the blob core) now respawns randomly on the station when the core is taken off z-level
-
Prevents the round from going into an unending state
-
Added a variable to the stationloving component for objects that can be destroyed but not moved off z-level
-
After years of protests NT decided to update the fire security standards by adding 3 (three) advanced fire extinguishers to all the new stations.
-
Hyperspace ripples now remain visible until the shuttle arrives, even during extreme lag.
-
Ripples now correctly take the shape of the shuttle, rather than always being a rectangle.
-
Non-secure windoors now properly support the "One Required" access mode of airlock electronics.
-
The gulag shuttle no longer moves instantly when returned via the claim console.
-
It is now possible to use the ".p" (Asay) and ".d" (Dsay) prefixes while an admin ghost.
-
Speaking in deadchat now shows your rank instead of ADMIN
-
Added a pink scarf to vendomats
-
Players can now ctrl-click the PDA to remove the item in its pen slot
-
added a clamp so you can't set a negative multiplier to create materials and create more than 50 items.
-
anomaly cores no longer tend to dust
-
Plant disks with potency genes clarify the percent is for potency scaling and not relative to max volume on examine.
-
Blast cannons have been fixed and are now available for purchase by traitorous scientists for a low low price of 14TC.
-
Blast cannons take the explosive power of a TTV bomb and ejects a linear projectile that will apply what the bomb would do to a certain tile at that distance to that tile. However, this will not cause breaches, or gib mobs, unless the gods (admins) so will it. experimental: Blast cannons do not respect maxcap. (Unless the admins so will it.)
-
Cyborgs now drop keys on deconstruction/detonation
-
The "Save Logs" option in the chat now actually works (IE 10+ only).
-
Fixed cyborgs not getting their names at round start
-
Fixed cyborgs and A.I.s being able to bypass appearance bans
-
fixes cult shuttle message repeating
-
Hardsuit helmets now protect the wearer from pepperspray
-
It is once again possible for Cargo to export mechs.
-
tourettes doesnt stack on itself anymore
-
AI static now uses visual contents and should perform better in theory.
-
Bucket helmets cannot have reagents transferred into them until after they are removed
-
R&D deconstructors can now destroy things regardless of if there's a point value or material
-
You should now receive your destroy AI objectives properly during IAA
-
Deconstructable TEG now propertly connects to pipes.
-
Fix of inverted TEG sprite of slow turbine turning. add:Now you can flip circulator and make TEG of your dream. add:Add TEG and circulator to "Advanced Power Manipulation" techweb node.
-
New icon for plastic flaps that actually looks airtight.
-
Update to plastic flaps code to use tool procs rather than attackby and removed two pointless states.
-
Printing the TEG and circulator boards no longer prints the completed machinery instead.
-
Medical HUDs will now show an icon if the body has died recently enough to be defibbed
+
Adds the ability for cloning consoles to read and write record lists to the circuit board, and provides a template for giving other machines local circuit board memory.
-
Cobby updated:
+
Cebutris updated:
-
Decals are the exception to the recent removal of effects in Chameleon Projectors.
-
Removed Advanced Mining Scanner from roundstart voucher kits.
-
Removed Explorer Webbing from all voucher kits besides the shelter capsule pack.
-
Paper doesn't give illegal tech anymore
+
Hugs of the North Star! Get them from the arcades (if you're lucky) and hug your friends at INCREDIBLE hihg speeds!
+
Tea Aspera now properly contains tea powder
+
Breasts no longer lactate by default, lactation is now a preference
-
Cruix updated:
+
Chayse updated:
-
AIs now have an experimental multi-camera mode that allows them to view up to six map areas at the same time, accessible through two new buttons on their HUD.
+
Changed the Warden's compact combat shotgun to instead be a regular combat shotgun with a foldable stock and penalties for being folded.
+
Assorted space-worthy helmets can now act as masks for internals.
+
Internals code can now check any item with the ALLOWSINTERNALS flag through the GET_INTERNAL_SLOTS define. For now this only checks head and mask slots, since those are the most realistically speaking usable ones.
+
Medbay doors can now be opened by anyone from the inside without having to press the exit button.
+
Borgs now have the necessary dexterity to unbuckle people from themselves and from bucklable objects.
+
Fixes the Trek Uniform/Suit worn icons
+
AIs can now once more talk through holopads successfully
-
Dax Dupont updated:
+
Code-Cygnet updated:
-
Fixes the wrong tiles in Syndicate VR trainer and uses different tiny fans.
-
Access didn't append to VR IDs
-
Fixes missing curator hud icon.
-
Cult items will no longer be a long ride on the vomit coaster if picked up by a non cultist.
-
Cult space bases are kill again.
-
Cult floors now pass gas.
-
Fixed a few things deconning into the wrong circuit.
-
You can no longer do infinite bioware surgery.
-
Foam no longer gives infinite metal
-
Mulligan didn't work on lizards and other mutants. Now it does.
-
The BoH dialog now has Abort instead of Proceed as an default option.
-
Fixes accidental empty ahelp replies.
-
More chemicals can be found when vents get clogged.
-
Experimentor no longer shits out primed TB nades.
-
Fixed rpeds throwing stock part rating related runtimes.
-
Fixes a sentience related exploit by blacklisting it in restricted uplinks.
-
Botany trays don't magically refill anymore with a rped.
-
It's now easier to become fat. Don't eat so much.
-
Fixed missing grilles under brig windows of the pubby shuttle.
-
For the pubby shuttle, added some food in the fridge, mostly pie slices. Also added a sleeper to the minimedbay.
-
Reworded pubby shuttle description to be more inline with the new train shuttle.
-
Syndicate and Centcom messages have been squashed together.
-
You can now send both Syndicate and Centcom headset messages. Be mindful that the button was changed to HM in the playerpanel
-
Fixes missing cream pies in the cream pie fridge.
-
Chem synths overlays aren't all kinds of fucked anymore.
-
Unfucked all of the remaining chem synth code.
-
Reagents no longer have an unused var that's always set to true. Who did this?
-
Makes the xeno nest ruin harder to cheese.
-
Fixes the bathroom being airless in the Space Ninja anime jail.
-
Create antags now checks for people being on station before applying.
-
Malf AI machine overloads now are logged/admin messaged.
+
Added new things - Mind trait, alcohol reagent, chemical reagent, drink sprite and recipe.
+
added commander_and_chief sprite to drinks.dmi
-
Denton updated:
+
Coolgat3 updated:
-
APC/air alarm/airlock/fire alarm/firelock electronics are now available once Industrial Engineering is researched..
-
Engi-Vend machines now contain fire alarm and firelock electronics!
-
Loose tech storage circuit boards have been replaced with spawners.
-
Added /syndicate subtypes for air alarms and APCs.
-
Added missing stock parts to the syndicate lavaland base.
-
Added kitchen related circuit boards to the syndie lavaland base.
-
There are rumors of the Tiger Cooperative adding a "special little something" to some of their bioterror kits.
-
Loose silver/gold/solar panel crates have been replaced with "proper" crates.
-
Skewium is much less likely to appear during the Clogged Vents event.
-
Navbeacon access requirements have been fixed: Now you need either Engineering or Robotics access, but not both at the same time.
-
Pubbystation: Added a dual-port vent pump to the toxins burn chamber.
-
Removed most airlock_controller/incinerator related varedits and replaced them with defines/subtypes.
-
The Deltastation toxins lab has its portable scrubber, air pump and intercom back.
-
Swarmers can no longer attack field generators and turret covers.
-
Arcades have been stocked with preloaded tactical snack rigs.
-
The Pubbystation maint bar Booze-O-Mat now shows its contents correctly.
-
Added a warning to the shuttle purchase menu.
-
Pirates and Syndicate salvage workers have been beefed up around the caravan ambush ruin.
-
NanoTours is proud to announce that the Lavaland beach club has been outfitted with a dance machine, state of the art bar equipment and more.
-
Did you know that honey has antibiotic properties?
-
Improved supply shuttle messages and firefighting foam descs.
-
Supply shuttles will no longer spill containers on docking.
+
Changed player number checks to 20 from 24 for cult and clockcult, also made nukeops 28 required players instead of 30.
+
Changed enemy minimum age from 14 to 7
+
Added the code for the semen donut and made it craftable
+
Added the donut sprites
+
Made the sec and warden berret offer as much protection like the helmet
+
Added berets for all the heads.
+
Added sprites for the berets.
+
Coded the berets to spawn in appropiate lockers.
+
Raised the ripley's movement speed and lights range by 1, also lowered its armor to compensate.
+
Added combat gloves sprite
+
Added said sprite
+
added combat boots sprite
-
Dimmadunk updated:
+
Coolgat3 / Avunia updated:
-
There's a new type of reagent added to the booze dispenser: Fernet. With it you can make a couple of new digestif drinks that will help you reduce excess fat!
+
Made kindle put the target into stamcrit, which makes it an actually working, useful stun.
+
Added a stamina loss modifier to the vanguard spell which makes the user's stamina drain at a way slower rate. This doesn't make them immune to tasers, but it takes a few hits to actually get them to fall down.
+
Made it so that clock culties don't start with a chameleon suit. Instead they start with an engineer suit which is pretty much the same sprite and looks. If this is not perfect, then I am willing to make a slightly more brass-colored version of the engineer suit sprite and call it a ratvarian engineer jumpsuit.
+
Increased the cost of vanguard, as it is now a spell that works somewhat like adrenals, minus the move speed, making your stamina drain really slow and making you unable to get knocked onto the ground by just a single taser shot.
+
Lowered the charge time of kindle, reason being that you can usually have only one active spell on you, or two at max if you decide to run two slabs, but the fact that kindle silences people for such a small amount of time makes up for it, in my opinion.
+
Figured out that the consoles and their warp function actually work with the current code. The thing that makes them not work is when the gamemode is ran on debug mode, without the required players to actually support it. It also breaks the ark timer which is stuck on -1 seconds until activation. Whenever the gamemode starts properly, like any other gamemode, with player checks and all, everything seems to work just fine.
-
ElPresidentePoole updated:
+
CydiaButt13 updated:
-
SFX for seppuku (on all katanas)
-
suicide message for energy katanas ("cyber-seppuku")
-
suicide message for replica katanas ("seppuku")
+
Lamp Plushie to loadout
+
added plushie_lamp to plush icons
+
added Lamp Plush to loadout and icons and items
-
Flatty updated:
+
EgoSumStultus updated:
-
The blurry eye overlay has been replaced with an actual blur.
-
The vending machine UI is now prettier.
+
Fixed blood chiller's inhand
+
FIXED SHIELF
+
fixed magpistol magazine sprites
+
Added the Femur Breaker
+
Adds male AI vox.
-
Garen updated:
+
EmeraldSundisk updated:
-
Thrower and Gun circuits put messages in chat when they're used.
-
Only the gun assembly can throw/shoot while in hand
-
Adds inhands for the gun assembly
-
grabber inventories update when a thrower takes from them
+
Adds a gun range to Box Station
+
Provides some extra power grid connections
+
Sunglasses and Earmuffs removed from the Warden's Office - they can be found at the range instead
+
Rearranges a few objects within the prison as to accommodate the new gun range
+
Adds a mass driver to Delta Station's chapel
+
Adds a second means of entry into the chapel
+
Slightly expands the chapel to make room for the driver, slight adjustment to air systems
+
Clears a path in the station exterior for the mass driver to work properly
+
Nearby maintenance loot has been relocated to accommodate the chapel expansion, surrounding area has been "cleaned up" somewhat
+
CentCom has noticed the lack of coffins in Delta Station's chapel and provided some, but in exchange for reducing the chapel morgue's capacity.
+
Fixed a maintenance door the chaplain should have been able to open.
+
Fixes space areas outside the driver removal: CentCom Defense Analysts have ordered the maintenance hatch to the Mass Driver room be removed citing "security concerns".
+
Increases the number of plots to 9 (from 5)
+
Additional lighting placed directly outside the garden
+
Cleans up the area to reflect use. Moves the seed extractor to a more central location
+
Relocates the seed packs on botany's counter to the garden removal: Removes wooden barricades outside the garden
+
Renames "Abandoned Garden" area designation to "Maintenance Garden", but does not replace the icon in Dream Maker
+
Expands the chapel mass driver room to make it easier to use
+
Rearranges the chapel backroom so there are now six coffins and burial garments roundstart
+
Cleans up the Janitor's office
+
Readjusts the station exterior so mass-driven coffins (hopefully) have less friction
+
Adds a fan to the chapel driver
+
The Janitor missed a few spots around the newly renovated Maintenance Garden
+
Readjusts positioning of Delta's QM keycard device
+
Cleaned up a few spots I missed in #9356, particularly around the janitor's office
+
Adds some potted plants around Box Station
+
The tile mentioned in #9409 should now be radiation-free.
+
+
Fermi updated:
+
+
Fixes tiny runaway decimals in reagents system.
+
SDGF: Fixes infinite clones.
+
fixed an angery PR
+
+
Fermis updated:
+
+
Added a panda simplemob
+
fixes empathy exploit.
+
Added the secbat, a box to hold it and the ability to dispense it from the SecTech vendor.
+
Adds 3 new music tracks.
+
tweaked Neurotoxin
+
added more depth to Neurotoxin
+
fixed the inability to create Neurotoxin
+
fixes fermichem reactions for tiny volumes work
+
makes quantisation level for chemistry finer
+
re-enables femichem explosions in grenades.
+
adds nuance to the SDGF and hatmium explosions.
+
Fixes analyse function on ChemMasters to correctly display purity.
+
Fixes the custom transfer for buffer to beaker button.
+
Debug option: Generate Wikichems
+
graft synthtissue surgery, new reagent synthtissue
on_mob_dead(), bitflags and CHECK_MULTIPLE_BITFIELDS
+
refactored fermichem vars, moved impure chems into their own reagents subtype
+
Fixes small residues of chems that won't go away!
+
tweaked beaker health and allows use of syringes/droppers on chem_heaters
+
added a sound for when beakers take temperature damage.
+
added some icons for melting beakers
+
refactored how beakers take damage
+
fixes how beakers would only take one instance of damage on pH damage
+
fixes Janitor grenades.
+
fixes reaction mechanics at low volumes
+
stops reactions constantly bubbling on the edge of reaction temperature
+
stops small amount reactions from occurring, and prevents disappearing tiny numbers
+
Reduced minimum reaction volume from 1 to 0.01
+
cleaned up Fermichem
+
Adds Jacqueline the Pumpqueen and her familiar Bartholomew for the spooky season
+
Adds a giggle
+
Adds cauldron, Jacq and Jacq o lanterns, and a costume for halloween! mapedit: adds a new landmark so Bartholomew can spawn somewhere sensible.
+
fixes food reactions and explosion runtimes,
+
fixes the too much yes problem
+
Heart, Tongue and stomach regen.
+
lung damage threshholds.
+
Graft synthtissue
+
Skeleton's burning for no reason
+
Organ freezing handling.
+
Fixes chemistry books to point to the right wiki, and keeps tg's just in case
+
Changes top right wiki button location to go to both wikis
+
fixed Jacq's fondness for the AI
+
+
Ghom updated:
+
+
minor clean up on hydroponics reagent containers.
+
fixes the perpetual lack of moisture that has affected genitalia descriptions since, like, forever.
+
implements the arousal state for mammary glands.
+
+
Ghommie updated:
+
+
Fixes many possible situations of null icons for cit races' bodyparts.
+
Removes duplicate slimepeople' sprites.
+
Purges that draw_citadel_parts().
+
Fixes ISINRANGE_EX using the wrong relational operator.
+
The kindle status effect stun duration now properly proportional to the owner's remaining health.
+
Clockwork cult's kindle now affects silicons.
+
Cyborg mounted disablers/tasers/lasers now slowly self-recharge off the cyborg user's power cell instead of draining from it directly.
+
Borg rechargers now properly recharge the borg module's energy guns.
+
Prevents a couple more special/mounted guns from being preserved on cryo
+
Halved borg energy guns self-recharge delay and increased their cell capacity by 3/4
+
Fixes chemical patches always checking the suit slot even if the targetted limb was the head.
+
Skeleton, nightmare and golem races are once again available to get chemical patches applied onto.
+
Adds two cartons of space milk to the space skellie pirates cutter's fridge.
+
Refactored implants to not be located inside mobs codewise, akin to organs.
+
Fixed gps tracking implants.
+
Fixed item not being dumped out of storage implants onto the owner's turf upon removal.
+
Fixes cult potentially stalling if the target is erased from existence without being sacced.
+
Nukes the stunprod's 3 seconds delay.
+
Fixes teleprods.
+
Stops pulls of resting mobs breaking off whenever you swap turfs with someone else because of crawling delays.
+
fixes IAA.
+
EMPs now flick off stunbatons, they can be turned back on immediately by the user anyway.
+
Stunbatons now very slowly consume charge whilst kept on, at a rate of 4/1000th of a standard batoning charge cost per tick.
+
Softened up the charge cost checks to stop the above update from practically reducing the maximum uses of a stun baton by one. Now, should the remaining charge be lower than the hit cost, the resulting stun will be be proportional to the remaining charge divided by the hitcost, within a limit under which the stun batoning just won't happen.
+
Buffs condensed capsaicin, a yet another feature previously dunked by stam combat.
+
speeds up pepper spray puffs.
+
Buffed krav maga leg sweep stun and stamina damage. On the other hand, it's now unable to be used on already lying targets.
+
fixes eyestabbing people with cutlery while being a pacifist.
+
Reduces goonchat lag from being blasted by pellets and bullets repeatedly whilst wearing armor by properly removing the armor protection texts this times.
+
also reduced the size of armor protection messages in general. they clog up the chat box.
+
Fixes stunbatons icon not properly updating on cell removal and insertion.
+
Allows lower charge cells to be used with stun batons, and thus single use crapshots batons.
+
Adds in a 7 seconds delay to the jackhammer dismantling a superheated clockwork wall.
+
escape pods emergency suits storage can now be busted open by emags or excessive damage.
+
Fixes alt click bypassing the escape pods' suits storage lock.
+
Fixes emags wasting charges on un-emaggable & co stuff.
+
Ported some radials code updates.
+
Ported the RCL wiring menu and a comfier RCD interface.
+
A milder combat stance message will show up if the user switch combat mode on while on help intent.
+
Properly rewords the extinguisher's instructions on how to empty it on the floor since it was changed to be a screwdriver action instead of Alt Click a while ago.
+
Reskinnable PDAs. A related game preference.
+
Refactoring the pda, pda painter, obj reskinning and chameleon pda a bit to support this feature.
+
more PDA sprites and ported reskins.
+
turned virtual reality into a component datum, which is then applied to spawned virtual mobs. This fixes mob transformations (such as wabbajack and monkeyizing) breaking the previously hardcoded behaviour and trapping you in VR, also enabling a more concrete virtual reality inception experience.
+
Fixes power cells being unable to be rigged. Also prevents them from starting processing on init if they don't self recharge.
+
Fixes many, little or otherwise, issues with the stunbaton status refactor.
+
The sacrificial target icon will now display onto the cult objective ui alert once again.
+
Stopping borgs from sprinting into negative cell charge.
+
The default amount of z-levels reserved specifically for space ruin generation has been increased from 1 to 2
+
Moving some tablecrafting recipes to the appropriate categories: Kitty ears and lizard cloche hats to "clothing"; Hot dogs to "Sandwichs"; Cuban carb, fish and chips and fish fingers to "Fish".
+
Fixes the not-a-sandwich recipe being M.I.A.
+
Adding in peanuts, peanut butter, peanut butter toasts and sandwiches, and the PB&J sandwich. The peanuts contain a little bit of extractable cooking oil (similarly to soy beans) and can be microwaved or dried in a drying rack to make roasted peanuts, which can be mixed in a all-in-one-grinder for peanut butter, required to make those sandwiches.
+
Buffed wizard and artificier's Magic Missile, wizard and xeno queen's Repulse and juggernaut's Gauntlet Echo.
+
Fixes flashlights being unable to be used for rudimentary eyes and mouth exams.
+
Adds in a grey jumpsuit to the loadout choices, restricted to Assistants.
+
Fixes CWC construct shells being visible as ghost role to latejoiners.
+
new sprites for the flechette gun, its magazines and the toy ray gun
+
Merges the end-of-shift and its shuttle autocall announcements into one.
+
Prevents the end-of-shift shuttle from being recalled (even if to no avail).
+
Fixes being able to teleport papers to your location with TK.
+
Fixed some monkey-code shenanigeans making items sometimes disappear from pickpocketing.
+
New sprites for the some pda cartridges.
+
The crew monitor's entry for the Quartermaster will now appear bolded, while HoP's will be of the same color of the service/unknown/other jobs.
+
emergency pods' storage will now properly work.
+
The PDA skin preference will now properly save up.
+
Changed the default PDA icon var to match the default PDA skin preference.
+
Fixing the `(pointless) badassary` category appearing between the `dangerous and conspicious` and `stealthy and inconspicious` categories.
+
Combat gloves plus now properly use the combat gloves sprite.
+
Fixes the space ninja's energy netting.
+
Adding one pAI to the wizard shuttle and ERT prep room
+
Fixes the rocket launcher being unreloadable.
+
Buffed its accuracy a bit.
+
Replaced the grenade launcher emagged minesweeper loot with the rocket launcher like it was originally supposed to be.
+
Tweaked the :b: emoji.
+
Rubber Toolboxes.
+
Porting in two bar signs: Cyber Sylph's and Meow Mix.
+
Fixing stamina damage melee weaponry being unusable by pacifists, and still damaging objects and triggering electrified grilles when thrown.
+
refactored underwears to allow custom color preferences, instead of manually colored sprites.
+
The aforementioned manually colored pieces. Some of your char preferences may have been resetted as result.
+
More underwear choices, including: Bowling shirts, long johns, a tank top, fishnets, more bee socks, bee t-shirt and bee boxers (original PR for the latter three by nemvar from /tg/station).
+
random bodies will now have random underwear again.
+
Dressers will now properly change undergarment again.
+
Toned down many species' female chest sprites to fit the smaller cups.
+
Fixed some body parts sprites inconsistencies, such as the W/E female and male chest sprites being the same in some species, and jellypeople's legs being one tile off on W/E
+
Fixing baklava pies a bit.
+
Sweaters now cover groins too.
+
Improved the zelus flask to be more viable for bottle smashing than the average barman's selection.
+
Very slight bottle smashing code clean up, stupid const vars.
+
Fixes krav maga gloves, wizard spells knockdowns.
+
Added in an alert pop up to the cult convertees, on top of the older "click here to become a blood cultist" chat message.
+
The convertee's screen will now flash red to fit in the aforementioned message's fluff.
+
Made said message less verbose.
+
Towels. Crafted with 3 sheets of cloth, they can be worn on head, suit and belt slots even without uniform, or laid flat on the floor. Sprites from Baystation and Aurora Station.
+
You can combat mode right click people while wielding rags and towels to pat out their flames (to no use for rags) or otherwise drying them out.
+
toned down the stamina costs of some of the bulkier weapons.
+
repathed hypereutactic blades to be a subtype of dual sabers. Way less copypasta.
+
Fixing CX Shredder guns not accepting standard flechette mags.
+
Fixing missing magpistol magazines icon states.
+
sort of overhauled darkmode/lightmode to /vg/station's, also reincluding the pre-existing black'n'white theme.
+
Fixed LOOC color, fixed .userlove and .love span classes being a bit too blurry on dark mode.
+
The syndicate base's bathroom is now fitted with a shower, and a special towel.
+
Fixed many issues with towels.
+
The dry people off with rags/towels action can only be done if the object is NOT moist with reagents now. Also cleans banana creaming.
+
Towels deal more damage while soaked with reagents.
+
You can now squeeze rags/towels with Alt-Click.
+
deleted an old and crappier towel sprite that got in the way.
+
Fixes Pubby's disposal conveyor belts and lack of a second lawyer spawner.
+
Cleaned up the absolute state of the arousal module.
+
refactored exhibitionism into a quirk.
+
arousal states won't persist after death.
+
Fixes testicles size adjective thing.
+
undergarments toggling now works instead of just making underwear disappear and not come back.
+
The "Always visible" genitals setting will now display them above clothes.
+
combat pushes will now properly stop targets from using firearms, and will disarm the firearm if performed a second time, and also slow down people by 15%, and won't push people on tables blocked by shutters or other dense object anymore.
+
Fixes CHECK_BITFIELD macro.
+
Fixes hypovials being unable to transfer out liquids or be refilled by large dispensers like water tanks.
+
Fixes chem-masters machineries not dispensing newly made pills inside loaded in pill bottles.
+
Stunswords now fit in the captain's sabre sheat.
+
reworked ninja's stealth mode. Increased invisibility, but engaging in combat, attacking or throwing things, bumping people will temporarily lower it.
+
Ninja shoes are even stealthier.
+
cleaned up some 2014 tier processing code horror.
+
the oxyloss fullscreen overlays now also take in consideration 1/5 of the user stamina loss.
+
When you're jogging, you will only slip on water if you have more than 20% staminaloss, for real this time.
+
Different cuffs now come with different worn overlays instead of a generic one.
+
High luminosity eyes can now be properly deactivated and won't illuminate your surroundings again until turned back on.
+
Fixes freshly cloned people starting with undershirts. Fixes random characters possibly rolling with undergarments of the opposite gender (Doesn't affect preferences' freedom of choice).
+
MRE menu 3 has cuban nachos instead of a chili now.
+
Removed the illustration overlay from MREs, looks pretty weird otherwise.
+
MRE menu 4, vegetarian.
+
fixes a few bad touchs on combat mode pushing.
+
Fixes clock cult Abscond scripture not dragging pulled mobs into Reebe. Also fixes blood cult tele runes teleporting you from the source turf to the source turf.
+
fixes clock cult mass recall.
+
Fixes underwear colors a bit.
+
Fixes Blood Cult conversion prompts
+
Removes an obnoxious temporary overlay var.
+
colorable socks can be colored again.
+
Fixed undergarments color preferences resetting each round.
+
Fixed a few dozen suits' body coverage inconsistencies. These changes shouldn't affect armor and utility vests for most.
+
Fixed clown shoes and work boots.
+
Fixed some overlay bug that happens when legcuffed and then handcuffed.
+
Slowed down police baton and tele baton speed by 75%, should be still be faster than the legacy speed (2 seconds) by 0.6 seconds. Telescopic batons' stamina cost per swing is now on par with police batons, ergo more expensive.
+
Fixed undershirts n socks colors prefs.
+
You can now alt-click to rotate machinery such as the tachyon-droppler array or emitters again.
+
Sofas can't be wielded and transformed back into plain chairs anymore.
+
Enables emojis for PDA messages.
+
Removes revenant blight's shabby toxin damage in favor of mood maluses, and a dangerous necropolis curse if not cured in time. Remember
+
Blood cult altar, forge and archives now use radial menus.
+
Fixed some machineries' UIs.
+
blood and clock cultists messages from metabolizing
+
Fixed advanced medical scanners borg upgrades.
+
Fixes certain borg upgrades being unapplicable on dogborg counterparts of the target cyborg type.
+
Fixed people being shovable hrough windows, windoors and the such.
+
You can now shove people into disposal bins.
+
refactored altdisarm(), ergo the "shoving people around" proc.
+
war ops is now lowpop friendly and doesn't require roughly 54 starting players anymore.
+
Singularity beacons now also moderately increases the odds meteor waves, while lowering their estimeed arrival countdown.
+
non-alphanumeric graffiti decals will no longer display as "letter".
+
Nerfs cyborg disabler and its internal power cell to hold 25 disabler beam shots rather than 43/44, just like a normal disabler.
+
Adds some missing species_traits for cloth, clockwork and cult golems.
+
Added towel linen bins, found in dormitory restrooms. Also enhanced the bedsheet bins found in some stations' dormitories
+
Resprited bedsheet bins in 3/4 perspective
+
Made SDGF ghost poll message less verbose, made the experimental cloner's complaint with the former, and added ghost poll ignore options for both.
+
fixing some related onmob sprites issues with the above accessory.
+
Teleprods work on non-carbons mobs now.
+
Fixed tracking implant teleport issues.
+
Increased stunbatons power cell depletion rate when left on by 50%.
+
Gorlex Marauders are pleased to announce non-slip grooves were given to their .50 sniper rifles, and thus shouldn't accidentally flop on the floor like pocket spaghettis whenever taken out of a bag anymore.
+
Silicons can now operate teleporter, medical and security records console from a distance again.
+
Fixed custom say emotes conflict with drunk memes.
+
Fixes identity transfer (envy knife, changeling transformation, making a vr avatar) not copying digitigrade legs.
+
Fixes temporary transformation sting triggering heart attacks on heartless humans.
+
Fixed mobs folded inside bluespace bodybags getting their clothing and items deleted when passing through a recycler.
+
The alien-bursting-from-your-thorax and the xeno "hud" embryo stage images will now properly delete them once the embryo egg lifecycle is complete.
+
Fixed artificier lesser magic missile.
+
Phantom thief masks will now fancy your combat mode yet again.
+
Fixed gulag teleporter stripping the user of stuff it really shouldn't (like storage implant bags).
+
fixing cydonian armor a bit.
+
Resprited wooden and critter crates.
+
Improved the Cyber Sylph' good yet cumbersome bar sign a little.
+
Cyborgs can now use camera consoles on the edge of their widescreen. These consoles are also TK friendly now.
+
Updated gang dominator sprites.
+
Miner borgs can again have installed PKA mods.
+
Fixed invisible blackberry n strawberry chocolate cake slices.
+
Nuke ops / adminbus combat mechs will no longer spawn with tracking beacons.
+
Arcade machine directional sprites.
+
lowered the arcade's random plush / other prizes ratio from 1 : 2.5 circa to 1 : 5. Dehydratated carps and the awakened plush can not be achieved this way anymore.
+
Added armrests overlays to sofas and tweaked their sprites a little.
+
Fixed dogborg sleepers. Just don't tell me what is exactly fixed, cause I don't want to find out.
+
Buffed the deep space familiar gorilla against runtimes.
+
Updated ratvarian computer sprites.
+
Fixed storage implant transplant.
+
Refactored how Jacqueen teleportation destination is selected, preventing them from teleporting on off-station holopads.
+
+
Ghommie && Kevinz000 updated:
+
+
Lichdom and necromantic stone skeletons are now of the spaceproof kind too.
+
skeletons now also like dairy products.
+
Halloween roundstart skeletons and zombies are no more spaceproof.
+
You can choose to set your species to zombie or skeleton through the pride mirror yet again, Alas they are not of the spaceproof kind either.
+
+
Ghommie (Credits to Kmc2000 for the original PR) updated:
+
+
Porting in MRE boxes from Yogstation. But be careful, eating possibly expired MREs found in maintenance comes with an unrealistically large (actually small) chance of food poisoning. Otherwise just bail out and order actually safe-to-eat MREs from cargo for 2000 credits.
+
+
Ghommie (Original PR by Dennok) updated:
+
+
Now areas_in_z get areas spawned by templates and blueprints.
+
+
Ghommie (Original PR by Dreamweaver) updated:
+
+
Nanotrasen has received word of a high-tech research facility that may contain advancements in bluespace-based research. Any crew members who become aware of its whereabouts are to report it to CentCom immediately and are restricted from sharing said info.
+
The turf reservation system now dynamically creates new z levels if the current reserved levels are full.
+
+
Ghommie (Original PR by JJRcop) updated:
+
+
Ports in more emojis, including : flushed :
+
+
Ghommie (Original PR by LaKiller8) updated:
+
+
Goonchat options should now save properly.
+
+
Ghommie (Original PR by Vile Beggar) updated:
+
+
Warden now has an added drill hat in his locker. You can change the loudness setting of it by using a screwdriver on it. Use wirecutters on it for a surprise.
+
+
Ghommie (Original PR by coiax) updated:
+
+
atom/var/container_type has been moved into datum/reagents/var/reagents_holder_flags. There should be no visible changes to effects.
+
+
Ghommie (Original PR by nemvar) updated:
+
+
Botanists can now get beeplushies (or cultivator and bucket) as an heirloom.
+
Clowns and mimes will now properly pick either a can of paint or their brand as heirloom now.
+
+
Ghommie (Original PR by tralezab) updated:
+
+
Fixes an issue with spontaneous appendicitis picking incompatible mob biotypes.
+
+
Ghommie (Original PRs by Tortellini Tony and BuffEngineering) updated:
+
+
E-cigs will continue to display their setting after being emagged.
+
Vapes now come out of the mouth. fix Fixes an E-cig initialize() runtime.
+
+
Ghommie (Original PRs by nemvar and Rowell) updated:
+
+
Added beekini bras and panties, thigh-high and knee-high bee socks.
+
+
Ghommie (by Arkatos) updated:
+
+
Fixed an issue with a Lizardwine drink crafting, where a final product would contain unwated 100u of Ethanol.
+
+
Ghommie (by Floyd / Qustinnus, Arathian) updated:
+
+
The robotocist now has robe to show his love for toasters
+
+
Ghommie (by nemvar) updated:
+
+
Dwarfs are now more robust.
+
+
Ghommie (original PR by 4dplanner) updated:
+
+
thrown objects (but not mobs) no longer hit the thrower
+
mirror shield rebound no longer depends on the original thrower's momentum
+
+
Ghommie (original PR by 81Denton, kriskog and nemvar) updated:
+
+
Sleepers now show a message if players try to unscrew the maintenance hatch while they're occupied or open. Fixed typos in sleeper/organ harvester messages.
+
Sleepers and dna scanners can now be pried open with crowbars.
+
You can open and close sleepers and dna scanners by alt-clicking them.
+
The scanner's hatch now must be closed (on top of being unoccupied), just like sleepers, before being screwdriverable. This fixes a tricky door stuck issue with the machine.
+
+
Ghommie (original PR by AffectedArc07 and Shazbot) updated:
+
+
Added 8 new sock styles
+
+
Ghommie (original PR by AffectedArc07) updated:
+
+
Religion is now a globalvar instead of being a subsystem for some reason
+
+
Ghommie (original PR by AnturK) updated:
+
+
Supermatter now melt walls if it finds itself in one.
+
+
Ghommie (original PR by Anturk) updated:
+
+
Recipe for fabled secret sauce can now be found in the deepest reaches of space.
+
+
Ghommie (original PR by Barhandar updated:
+
+
Pumpkin meteors on Halloween now replace catastrophic meteor waves, instead of ALL OF THEM.
+
+
Ghommie (original PR by CrazyClown12) updated:
+
+
The chloral hydrate inside of the sleepy pen is no longer slower acting than chloral hydrate made in chemistry.
+
The chloral hydrate inside of cookies synthesised by emagged borgs is no longer slower acting than chloral hydrate made in chemistry.
+
Slight tirizene buff.
+
Delayed chloral hydrate
+
+
Ghommie (original PR by Denton) updated:
+
+
Nanotrasen has started shipping more types of bedsheets to its stations.
+
Added in Runtime, Pirate and Gondola bedsheets. The second one can also be found in some pirate ships, while the last can be crafted from gondola hides.
+
You can no longer reveal the 'illegal tech' research node by deconstructing .357 speedloaders, riot dart boxes, syndicate cigarettes, syndicate playing cards or syndicate balloons.
+
+
Ghommie (original PR by Mickyan) updated:
+
+
Fixed being unable to smother people using the damp rag
+
+
Ghommie (original PR by MrDoomBringer) updated:
+
+
morgues have had their proton packs removed and as such no longer suck in ghosts on closing.
+
+
Ghommie (original PR by MrDoomBringer, AnturK and YPOQ) updated:
+
+
Explosions will no longer damage wizards in rod form, the supermatter monitoring radio and megafauna GPS.
+
Supplypods no longer detonate their contents.
+
Fixed silicon items (e.g. cyborg modules) being destroyed by explosion epicenters.
+
+
Ghommie (original PR by Naksu) updated:
+
+
get_area() is now a define rather than a proc.
+
+
Ghommie (original PR by Nicjh) updated:
+
+
Abductor console's select disguise option now uses a radial
+
+
Ghommie (original PR by ShizCalev) updated:
+
+
Pineapple haters/lovers will get/no longer get pineapple pizzas respectively from infinite pizza boxes.
+
As a non-human mob, hovering your cursor over an inventory slot while holding an object in your active hand shouldn't runtime now.
+
+
Ghommie (original PR by Skoglol) updated:
+
+
New helper proc for alt-click turf listing, bypasses any interaction overrides.
+
Ghosts and revenants now use the new proc.
+
Ghosts can no longer toggleopen sleepers, adjust skateboard speed or close laptops
+
Revenant can now alt-click turf to list contents.
+
Revenant now slightly less nosy, use shift click to examine.
+
Alt-clicking the same turf again no longer closes the turf listing tab.
+
Reduced ventcrawl lag greatly.
+
Mining bags will no longer drop ore into backpack.
+
Mining bags in backpack no longer interferes with other mining bags.
+
Fixes some storage size circumventions.
+
Moved machine and computer frames below objects, parts are now always on top.
Disassembling a chem dispenser for the first time will no longer always yield a fully-charged cell.
+
+
Ghommie (original PR by Swindly) updated:
+
+
Arm-mounted implants that contain more than one item use a radial menu instead of a list menu.
+
+
Ghommie (original PR by Tlaltecuhtli) updated:
+
+
Other people's clothes burning no longer spam you
+
+
Ghommie (original PR by XDTM) updated:
+
+
Reagents now stop their passive effects (for example, stun immunity) if the liver stops working while they're active.
+
+
Ghommie (original PR by YPOQ) updated:
+
+
Fixing roffle waffle, mushroom halluginogen and some invalid reagents.
+
Fixes clockwork armor not actually having armor.
+
+
Ghommie (original PR by cacogen) updated:
+
+
The font size of all text in the chat window now scales
+
High volume (megaphone/head of staff headset) is a slightly smaller
+
Admins have slightly larger OOC text
+
+
Ghommie (original PR by coiax) updated:
+
+
Randomly coloured gloves and randomly coloured glowsticks now have slightly different typepaths, but otherwise function the same.
+
The Squeak subsystem has been renamed to Minor Mapping.
+
+
Ghommie (original PR by duckay) updated:
+
+
Added better names and descriptions for blueshirt officer gear.
+
Added the above gear to the premium selection of the sectech
+
+
Ghommie (original PR by harmonyn) updated:
+
+
Resisting out of bucklecuffs takes more/less time depending on the handcuffs you used, i.e., fake handcuffs will not bucklecuff someone for ages.
+
fake handcuffs shouldn't no longer demoralize restrained criminals scums.
+
+
Ghommie (original PR by monster860) updated:
+
+
fixes advanced proccall
+
+
Ghommie (original PR by mrhugo13 on tgstation13) updated:
+
+
The Syndicate has decided to equip their Syndicate leaders operative (Aswell as their clown counterparts) with the new Combat Glove Plus! The new Combat Glove Plus does everything the old boring Combat Gloves does but with the added extra of learning Krav Maga upon wearing them, any other Syndicate operative who wants to get in on the action will have to pay 5tc.
+
+
Ghommie (original PR by nemvar) updated:
+
+
Some drinks have new icons or slightly altered icons. In particular Wizz Fizz, Bug Spray, Jack Rose, Champagne and Applejack.
+
+
Ghommie (original PR by ninjanomnom) updated:
+
+
Orbiting is a little more aggressive about staying in orbit. The wisp as a result now correctly follows you over shuttle moves.
+
Gaps between sounds in some looping sound effects should no longer happen as much under heavy server lag.
+
+
Ghommie (original PR by variableundefined) updated:
+
+
Cancel button to assault pod destination selector.
+
+
Ghommie (original PR by wesoda25) updated:
+
+
disembowelment no longer works on mobs that aren't dead or in critical condition
+
+
Ghommie (original PRs by Akrilla, Arkatos and Denton) updated:
+
+
Sprays cans have a cap on how dark you can make objects. Art is uneffected.
+
Fixed a bug where you could get cyborg spraycans via pyrite extracts.
+
Added an infinite spraycan for admins to spawn.
+
+
Ghommie (original PRs by Denton and Skoglol) updated:
+
+
Reorganized the syndicate uplinks. Items are now mostly alphabetical, some misplaced items moved to more fitting categories. Bundles, random item and TC have been moved into a new category called "Bundles and Telecrystals". Gloves of the North Star and Box of Throwing Weapons have been moved to Conspicuous and Dangerous Weapons. Combat Gloves Plus have been moved to Stealthy and Inconspicuous Weapons. Moved all implants into the Implants category.
+
Added a new category to the uplink: Grenades and Explosives.
+
+
Ghommie (original PRs by Floyd/Qustinnus, optimumtact, Denton and coiax) updated:
+
+
You can now select what your pills will look like when making pills from the Chem Master
+
Red pills can make you think.
+
+
Ghommie (original PRs by Jujumatic and PKPenguin321, respectively) updated:
+
+
Minesweeper Arcade machines. The higher the difficulty setting, the better the prizes will be.
+
Also keep your eye out for another new (and rare) arcade game!
+
+
Ghommie (original PRs by Kmc2000 and actioninja) updated:
+
+
Added darkmode! You can opt-in to this by clicking the new toggle darkmode button just beside the settings one.
+
Byond members will now have a new setting for their Antag OOC color, instead of using their OOC one. (Antag OOC still locked under admin discretion though)
+
Default black'n'white windows style.
+
+
Ghommie (original PRs by Mickyan, Anturk, ShizCalev, nemvar and Naksu) updated:
+
+
After rigorous mandatory art training for the crew, many new graffiti styles are now available
+
Cleaned up some crayon and spraycan code for futureproofing.
+
Spraypainting blast doors no longer makes them see-through.
+
Paint remover now works on blast doors and the like.
+
Most objects can now be colored using a spray can.
+
Added visible message to spraying objects and windows.
+
Colored lights now shine in different colours.
+
Removed individual buttons text in crayon/spraycan UI, speeding it up.
+
Text mode buffer is actually visible in the UI.
+
Last letter of a text mode buffer no longer rotates out to be replaced with "a", allowing the text mode to be used for individual symbols.
+
+
Ghommie (original PRs by Naksu and XDTM) updated:
+
+
Transferring quirks now properly removes the roundstart trait from the person losing the quirk.
+
Roundstart traits no longer block the removal of other sources of that trait.
+
status traits are now a datum var, the accessors are now defines rather than functions.
+
+
Ghommie (original PRs by Naksu and coiax, loser) updated:
+
+
Cleaned up saycode
+
Taking mutadone while having the communication disorder brain trauma will no longer spam your chat with messages.
+
IPCs now come with a subtype of robotic tongue without the omnilingual ability, instead of innately having robotic voice spans.
+
+
Ghommie (original PRs by Nichlas0010 and ShizCalev) updated:
+
+
AI core display screen can now be set in character preferences.
+
AI core display screen will now be restore when revived.
+
Corrected some inconsistent capitalization in the player preferences screen.
+
Readded some forgotten AI sprites.
+
Fixed Hades AI death animation not playing.
+
the AI icon-selection menu now uses a radial.
+
Added in the death icon_states for the "TechDemon" AI screen.
+
+
Ghommie (original PRs by ShizCalev and bobbahbrown) updated:
+
+
Headsets now dynamically show in their description how to speak on any channels they can use when held or worn.
+
Radio channels names and keys now use defines.
+
The head arrival announcement will now be broadcast to the supply for the quartermaster.
+
+
Ghommie (original PRs by ShizCalev) updated:
+
+
Fixed a bug that allowed you to teleport an ID in your possession to a PDA anywhere ingame.
+
Fixed an exploit allowing you to steal ID's/pens from PDA's not in your possession.
+
Fixed an exploit allowing you unlimited control of a PDA's interface even if it wasn't near you/in your possession.
+
Fixed Pride Mirror exploits.
+
Corgi collars can now be removed!
+
Updated the corgi & parrot inventory panels to use the same formatting as other mobs
+
Fixed corgi inventory panels not closing properly.
+
Fixed the parrot inventory panel not closing properly if you're not able to interact with it.
+
+
Ghommie (original PRs by ShizCalev, MrDoombringer, AnturK, bgobandit, 81Denton and actioninja) updated:
+
+
Failsafe codes for uplinks are now available for purchase.
+
Nuke Ops now have the ability to purchase a usable RPG, the PML-9, as well as a couple different types of rockets for it. you can also suicide rocket jump with them!
+
Improved Uplink item descriptions and formatting.
+
+
Ghommie (original PRs by ShizCalev, coiax and Tlaltecuhtli) updated:
+
+
Caks will no longer override the bonus reagents provided in a donut when frosting them.
+
Caks can no longer create frosted frosted jelly donuts.
+
Jelly donuts will no longer lose their vitamins when they're frosted.
+
Fixed chaos donuts potentially doubling the amount of reagents added when microwaved with something else.
+
Donuts now always contain 1 sprinkles as was stated on the wiki. Frosted donuts have a chance at adding an extra sprinkle.
+
Improved the code for ensuring that security members enjoy donuts and security-themed alcoholic drinks.
+
neurotoxin doesnt insta stun but gives you limb paralysis overtime and heart attacks if it stays in for too long and it is also alcholic
+
beepsky smash now summons imaginary beepskys that deal stamina damage instead of outright stunning
+
+
Ghommie (original PRs by Time-Green and Qustinnus) updated:
+
+
loot crates can't explode after unlocking anymore
+
jumping into loot crates no longers causes them to go boom
+
You can now deconstruct abandoned crates with a welder without making them go boom. After unlocking them, of course.
+
+
Ghommie (original PRs by Tlaltecuhtli and nicbn) updated:
+
+
alt click to eject beakers from chem masters + chem dispensers + grinders + chem heaters
+
hit chem master + chem dispenser + chem heaters with a beaker and if its loaded with another it swaps em
+
All-In-One Blender UI uses a radial menu now. You can see the contents and reagents by examining.
Merged tinfoil hat kind of protection into the anti_magic component.
+
Tinfoil hats can also be warped up from excessive dampening of mindray/though control/psicotronic anomalies, or by simply being microwaved in an oven, and become useless.
+
Immortality Talisman and Paranormal Hardsuit helmets now come with tinfoil protection too (minus the paranoia and limited charges).
+
Genetics/Slime/Alien Telepathy and Slime Link are now stopped by tinfoil protection.
+
+
Ghommie (original PRs by XDTM, optimumtact, Nichlas0010 and monster860) updated:
+
+
Added Quantum Keycards, devices that can link to a quantum pad, and can be used on any other quantum pad to teleport to its linked pad. spellchecking: Renamed "Bluespace Teleportation Tech" tech node to "Bluespace Travel".
+
Moved roasting sticks from the "Bluespace Travel" to "Practical Bluespace".
+
Spraying holy water on tiles will now prevent cult-based teleportation from using them as a destination point.
+
Quantum, wormhole and magic teleportation is no longer disrupted by bags of holding.
+
You are now also blocked from teleporting IN to no-teleport areas, not just out of them.
+
Quantum teleportation now makes pretty rainbow sparks instead of the normal ones.
+
Non-bluespace teleportation (spells etc.) no longer makes sparks.
+
Fixed teleportation deleting mob spawners like golem shells and ashwalker eggs.
+
+
Ghommie (original PRs by carshalash, GranpaWalton, BebeYoshi & Hexmaniacosanna, Fire Chance, Ordonis, Krysonism and OnlineGirlfriend) updated:
+
+
Reduced booze power of Mead, Red Mead, and Irish Cream.
+
Increased booze power of Grappa.
+
Added a new premium drink to the soda machine called "Grey Bull" which gives temporary shock resistance
+
A new drink called Blank Paper was added to the bar menu, it was made by a mime and it represents a new start.
+
Adds a variety of fine alcoholic beverages for discerning patrons of the bar: Wizz Fizz, Bug Spray, Champagne, Applejack, Jack Rose, Turbo, Old Timer, Rubberneck, Duplex, Trappist Beer, Blazaam and Planet Cracker!
+
Also more nonalcoholic drinks: Cream Soda, Lemonade and Red Queen.
+
Packs of a novel artificial sweetener have been added to the kitchen vendor.
+
Bottles of trappist beer and champagne are now available in the premium seection of the booze-o-mat.
+
Juicing parsnips now yields parsnip juice.
+
Maintenance peaches.
+
Grape soda now cools you down like other sodas.
+
tweaked the Arnold Palmer recipe, it now uses lemonade.
+
Added new drink, bottle, vomit and peach can sprites.
+
+
Ghommie (original PRs by grandpawalton and Mickyan) updated:
+
+
the contents on the smartfridge icon now change depending on how many items it contains
+
opening the maintenance panel of smartfridges now correctly updates the icon
+
Screwing a disk compartmentalizer no longer makes it look like a smartfridge.
+
+
Ghommie (original PRs by nicbn and coiax) updated:
+
+
Microwave UI uses a radial menu now. You can see the contents by examining.
+
Microwaves have a single wire accessible when open, the activation wire. When cut, the microwave will no longer function, when pulsed, the microwave will turn on.
+
Stabilized dark purple extracts now cook items in your hands, rather than dropping the cooked item on the floor.
+
+
Ghommie (original PRs by ninjanomnom and nemvar) updated:
+
+
Trays now scatter their contents when used for attacks, like they are supposed to.
+
+
Ghommie (original PRs by ninjanomnom, coiax, yoyobatty) updated:
+
+
Fixed slaughter demons not getting a speed boost when exiting a pool of blood. Fixed slaughter demon giblets not being visible.
+
+
Ghommie (original PRs by subject217, AarontheIdiot, pireamaineach, Gousaid67 and SouDescolado) updated:
+
+
Removed plasmamen species speedmod in favor of a slowdown for envirosuits.
+
Nanotrasen has began deploying departementalized enviro plasmasuits to the station! plasmamens can now benefit from some of the bonuses aswell as the color pattern of their job, while allowing others to easily determine their profession!
+
Benevolent Nanotrasen makes gulag available for everyone! (Plasmamen retain their equipment and don't die.)
+
Removes code that theoretically limits plasmamen from being clowns and mimes, but actually doesn't.
Blob overminds, sentient diseases, etc. can no longer dump out boxes. Sorry gamers.
+
Sentient Disease now has almost all symptoms at its disposal.
+
Adding single-symptom disease abilities is super easy now.
+
Sentient Disease can now hear (not sure if this was a bug or intentional).
+
Sentient Disease is a linguist and knows all languages. Still cannot speak.
+
Gives Sentient Diseases a medical hud to observe their victims further with.
+
Fixes and moves around some on_stage_change() and Start()-related things for virus symptoms and (sentient) diseases.
+
The inorganic biology symptom should work properly now when bought by a sentient disease.
+
Oxyloss icon no-longer shows up when someone has the self respiration symptom
+
The self respiration now makes you not contract diseases through the air and not breathe in smoke
+
Sentient diseases can no longer pick two cures that react and disappear when eaten.
+
Sentient disease cures are now consistently harder, will only pick cures from tier 6 and up.
+
Disease cures should now stay the same for all infected mobs.
+
The regenerative coma symptom has a new resistance 4 threshold effect! Said threshold effect will give hosts of the symptom's virus the TRAIT_STABLECRIT trait if its threshold is met.
+
An obscure, probably never reported before bug that may or may not exist involving sentient diseases and the self-respiration symptom should be fixed now (if it even existed in the first place).
+
The cooldown time between each removal or addition of a symptom for sentient diseases has been brought down from an agonizingly long 2 minutes to a more reasonable 1 minute.
+
+
Ghommie (original pr by Dennok on tgstation) updated:
+
+
Now you don't lose your pulled thing on the z level edge.
GrayRachnid updated:
-
Adds private rooms to the ninja holding center
-
Along with a few things to make it more tolerable, but fear not. There is now a suicide chamber for those who want the easy way out.
-
-
GuyonBroadway updated:
-
-
Adds gloves of the north star to the traitor uplink. Wearing these gloves lets you punch people five times faster than normal.
-
Sprites for the gloves courtesy of Notamaniac
+
Added windoors to all the flaps on delta.
+
rebalanced k9dogborgs
Hatterhat updated:
-
The plasma formerly present in some execution syringes was replaced with amatoxin.
+
Magnetic pistols now fit in boot pockets - jackboots, workboots, etc.
+
literally every pistol subtype fits in shoes now. go wild.
-
Hyacinth updated:
+
Hippie Circuit Port updated:
-
Grenadine is now available in the bar!
-
Tequila sunrises now require grenadine to make!
+
Added all Atmospheric Circuits
+
Added the ability to color data disks
+
Added Selection and Storage Examiner Circuits
+
Added Smoke, Extinguisher, and Beaker Connector Circuits
+
Added Inserter, Renamer, Redescriber, and Repaint Circuits
+
Added MMI Tank and pAI Connector Circuits (The possibilities are endless!)
-
Iamgoofball updated:
+
Improving and Balancing Cyborgs updated:
-
Lipolicide now only does damage if you're starving.
+
Added Crew Pinpointer to Security Borg
+
Added Crew Monitor to Medical Borg
+
Added Crew Pinpointer to MediHound Borg
+
Made the Disabler_Cooler compatible with both Security Borg and K9 Borg
+
Changed the Warning Text upon selecting Security or K9 module
-
Improvedgay updated:
+
ItzGabby updated:
-
Naming immerions
+
Bat Species parts for more leeway for character customization.
+
Alphabetized decor wing selection window in character creator for simplicity.
-
Improvedname updated:
+
JTGSZ updated:
-
Adds rubbershot secrifle shots
+
Added one more gang boss slot bringing total to 4 from 3
+
Fixed Gang Boss being able to be deconverted
+
Gave Qualifies_for_Rank Check back its checks in job controller.
+
Optional species based clothing restrictions
+
Gang Dominator excessive wall check tweaked to 25 open turfs
+
Gang Dominator no longer functions off-station.
+
Adds more control over species based offsets.
+
qualifies_for_rank now checks latejoin menu
+
Added Halloween Dwarves, for Halloween... Yep.
+
Can flip pipes once more.
+
barricade girder walls use PlaceOnTop instead of new
-
JStheguy updated:
+
Linzolle updated:
-
Added the data card reader circuit, a circuit that is able to read data cards, as well as write to them.
-
Data cards are now longer inexplicably called data disks despite clearly being cards, and can be printed from the "tools" section of the integrated circuit printer.
-
Data cards no longer have a special "label card" verb and instead can have their names and descriptions changed with a pen.
-
Also, some aesthetically different variants of the data cards, because why not.
-
Data cards have new sprites, with support for coloring them via the assembly detailer.
+
ability to quickly max sensors
+
atmos helmet visual bug
+
supply display are now properly on the wall
+
consistency in hop and cap berets
+
slime people now enjoy eating toxic food and it will not disgust them
+
hos trenchcloak now properly has a sprite on digi characters
+
duplicate definition of hos and sec skirts
+
Krav Maga leg sweep now works properly.
+
shoes can have a different icon used for their item and mob icons
+
combat gloves plus having no mob icon
+
inhands sprite for rainbow knife
+
colour of highlight on the regular knife when held in the right hand
+
mining shuttle console can now be printed after computer consoles have been researched
+
can now carry people on your back by aggressive grabbing them while they are laying down and then dragging their sprite onto yours.
+
dragging people who are prone is now much slower, and carrying them will allow you to move faster at the cost of taking 5 seconds to lift them up onto your back.
+
pacifists can now aggressive grab (cannot table slam people though)
+
blood on your body floating a bit to your right if you're a taur
+
some suits having no icon on tauric characters
+
front facing CMO hardsuit icon for naga taurs
+
colour of medical cross on CMO hardsuit for taurs
+
taur body and jumpsuit showing through mining suits
+
all chaplain suits can hold the same items in suit storage
+
improvement to organisation for chaplain suits
+
blood halberd not going back to 17 force after unwielding
+
unnecessary 's at the end of blood rites healing
+
QoL to blood rites, examine the ritual aura to view how many blood charges are left
+
surgery cleanup
+
dissection available round-start
+
better dissection surgeries from RnD, gives more points
+
abductors can now see what glands do
+
antagonist abductors now have a surgeon trait that teaches them every surgery rather than having it just check if they're an abductor
+
muscled veins surgery
+
having one of your hands used up if you fireman carry but the person being carried dismounts any way other than you dropping them
+
Four colour variants of ankle coverings. Select them on the loadout screen.
+
ankle coverings
+
allows for shoes that don't cover your feet to be taken into account for footstep sound effects and glass shards
+
Tend Wounds surgery. Heal in the field, with better healing the more damage the patient has.
+
Reconstruction replaced by Tend Wounds
+
made Revival more accessible, more viable alternative to cloning.
+
advanced surgery tools can't perform lobectomy or coronary bypass
+
Decorative and insect wings can now be coloured individually, similar to horns.
+
people getting assigned wings if their savefile is old.
+
wings that take the hair colour. Unnecessary if you can just set the colour.
+
Cannot make horns pure black. Trying to do so will set it to a default value.
+
decorative angel wings being invisible
+
abductors now actually work
+
abductor scientist has their own greet message now
+
unable to read paper on airlocks
+
ai can see paper (still just shows stars)
+
Target head and throw a hat at someone to toss it onto their head, knocking whatever they're wearing off if they are wearing a hat. Some headgear can't be knocked off this way.
-
Jay updated:
+
MediHound updated:
-
Bans CMO, RD, CE, and HoP from antag/ling
+
Made Cyborgs be affected by Ion Storm Law Changes like AIs
-
Jegub updated:
+
MrJWhit updated:
-
Glowcaps now have their own sprite.
+
rebalance melee stamloss
-
Kor updated:
+
Multicam Config updated:
-
The Quartermaster and HoP can now access the vault so they can use the bank machine.
-
Engineering can now create anomaly neutralizer devices, capable of instantly neutralizing the short lived anomalies created by the supermatter engine.
-
Bubblegum has regained his original (deadlier) move set.
-
-
LetterN updated:
-
-
Fixes shock collars, they now fit on the neck slot
-
you can't put them on pockets anymore
-
-
MacHac updated:
-
-
Bedsheets once again properly influence the dreams of those who sleep under them.
-
-
Mickyan updated:
-
-
Drinking too much Gargle Blaster, Nuka Cola or Neurotoxin no longer breaks time and space.
-
Pacifists can now use harm intent for actions that require it (but still can't harm!)
-
fixed typo in bronze girder construction
-
New trait: Drunken Resilience. You may be a drunken wreck but at least you're healthy. If alcohol poisoning doesn't get you, that is!
-
Fixed pacifists being able to harm using bottles/screwdrivers
-
-
MrDoomBringer updated:
-
-
the VR sleeper action button has a sprite now
-
Central Command can now smite misbehaving crewmembers with supply pods (filled with whatever their hearts desire!)
-
CentCom Supplypods now stun their target before landing, and won't damage the station as much
+
removed whether or not the stuff for multicam was checking the useless var and instead now checks the CONFIG_GET flag.
+
Admins now have a verb in the Server tab to turn AI multicam on and off.
Naksu updated:
-
clothing-specific flags are now defined in /obj/item/clothing.clothing_flags
-
More flags have been moved to their appropriate places
-
HEALS_EARS_2 is removed in favor of the earhealing component
-
wearertargeting component is available to subtype for components that want to target the wearer of an item rather than the item itself
-
changed the shockedby list on doors to be only initialized when needed.
-
Chameleon projector can no longer scan (often temporary) visual effects like projectiles, flashes and the masked appearance of another chameleon projector user
-
Drones can no longer see a static overlay over invisible revenants
-
adjusted default antag rep points to grant every job the same amount of points per round, except for assistant which gets 30% less
-
Nuclear explosive-shaped beerkegs found on metastation can now be triggered with the nuclear disk and the syndicate's legacy nuclear code for a foamy surprise
-
comms consoles now work in transit again, and no longer work in centcom
-
removed unnecessary getFlatIcons from holocalls
-
Screwdrivers and other items with overlays now show the proper appearance of the item when attacking something with them, or when put on a tray.
-
moved /datum.isprocessing into datum flags
-
Removed unused effect object that could be used to spawn a list of humans
-
The ladders in the tear in the fabric of reality no longer spawn their endpoints when the area is loaded, but only when the tear is made accessible via a BoH bomb.
-
CentCom is no longer accessible via the space ladder in the tear.
-
The lavaland endpoint can no longer spawn completely surrounded by lava, unless it spawns on an island
-
ChangeTurf can now conditionally inherit the air of the turf it is replacing, via the CHANGETURF_INHERIT_AIR flag.
-
when ladder endpoints are created, the binary turfs that are created inherit the air of the turfs they are replacing. This means the lavaland ladder endpoint will have the lavaland airmix, instead of a vacuum.
-
navigation beacons are now properly deregistered from their Z-level list and re-registered on the correct one if moved across Z-levels by an effect such as teleportation or a BoH-induced chasm.
-
constructed directional windows no longer leak atmos across them
-
setting the value of anchored for objects should be done via the setAnchored proc to properly handle things like atmos updates in one place
+
default radiation insulation is now handled by atom vars rather than a component, components can still be used.
+
squeezed a little bit more perf out of atmos
-
Nicc updated:
+
Nero1024 updated:
-
toxins lab boii
+
Bare feet will now make the correct footstep sounds.
+
Other mobs will make the correct footstep sounds.
+
Crawling/dragging sounds for downed/incapacitated mobs
-
Nichlas0010 updated:
+
Onule & Nemvar (ported by Ghommie) updated:
-
Reseach Director Traitors can no longer receive an objective to steal the Hand Teleporter
-
Comms consoles won't update while viewing messages
-
you now feel nauseated instead of nauseous
-
You can no longer use a soapstone infinitely
-
You now can't get multiple download objectives!
-
RDs, Scientists and Roboticists can no longer get download objectives!
+
New Revenant icons
+
+
Original by Citinited, port by Sishen1542 updated:
+
+
You can now use an airlock electronics on a locker to add a lock, and can screwdriver an unlocked locker to remove its lock.
+
You can now remove the locks on broken or emagged lockers.
+
Removing the lock from a personal locker now wipes that locker's ID details.
+
Broken lockers have had their appearance changed.
+
+
Owai-Seek updated:
+
+
custodial cruiser cargo crate
+
removed light replacer from power designs and moved to misc designs
+
added pimpin ride to custodial locator
+
added additional items to janibelt whitelist
+
made plant DNA manipulator unwrenchable
+
reduced janitor premium supply costs
+
fixed them strawberries
+
false codpiece
+
crocin/camphor bottles
+
updated kinkmate item list
+
+
PersianXerxes updated:
+
+
Adds the clockwork_warp_allowed flag to the Captain's Office area, set to FALSE the same way it is for the chapel and armory.
+
Relocates cult catwalks outside the Reebe dressing room.
Poojawa updated:
-
Admin IC issue is no longer TG i ded passive aggressive.
-
Added *insult, for when you just can't think of anything more clever
-
Makes vore specific prefs call Rust_g else uses normal stuff.
-
Citadel Toggles should save properly now
-
fixed clothing vendor fedoras having Detective Fedora grade armor
-
Fixes missing icons on mag weapons for techmemes
-
Fixes APCs being replaced in maint from counting Maint as their wall turff
-
Added Vore based moodlets, primitive and ain't gunna adapt for not belly things but w/e
+
Digitigrade legs are now able to wear shoes and look fancy, Uniforms to come.
+
Xenos are only digitigrade now, mammals and aquatics have the option.
+
Fire Alarms are visible in low light situations
+
fixed vore prefs saving inconsistently, new characters might have a previous slot's prefs tacked on.
+
fixed mammals not having the option for digilegs. Sprites are fucky until body-part related sprites are done.
+
improved vore sound responsiveness to preference choices.
+
removed morphine from Medihound sleeper chemical list
+
fixed preference setting being broken
+
Medihound sleepers are Initialized properly, and icons update correctly now on eject
+
Air alarm All clear color changed from green to blue
+
APCs are harder to destroy.
+
Added Digitigrade versions of everything appliciable in suit.dmi
+
Snowflake Icons weren't modified, and were given NO_MUTANTRACE_VARIATION
+
naga and quad Taurs literally don't freeze their ass off in space anymore.
+
Digitigrade legs will toggle on/off properly on character menue
+
The misleading "normal" has been removed from species options
+
Added sanity checks to emag usage
+
fixed vtech, but it still doesn't work because of overriding jog/sprint mechanics from combat reworks.
+
Puppy jaws properly store if you're emagged, they are also toggle-able for stealth like the tongue.
+
Digitigrade legs should properly fucking update for the last fucking time. Fucking snowflake code. refractor: Got rid of snowflake sechound cuffs, gave them normal zipties like regular secborgs.
+
dogborg sleepers actually extinguish people who are on fire, in case you don't have time to lick them out.
+
Taur suits should fix themselves properly when worn by other people.
+
Added the Yogs/Oracle ported latejoin menu
+
All markings, tails, ears, and snouts for Citadel races are color matrixed!
+
all markings are on a per-limb basis, including Digitigrade legs!
+
a bunch of tails were blessed with tail wagging sprites, Fish, Sharks, Fennecs, Wahs, raccoons, and others.
+
Tiger markings + tail added, skunk tails improved via sprites from Virgo
+
tweaked some sprites to look better, but they absolutely could use a few extra passes for quality
+
HumanScissors in the Tools folder will permit anyone to contribute matrix'd markings to the sprite sheet, however Mam_markings is very, very full. Be careful.
+
Character preview was both optimized for taurs and bad-touched for better updating. I don't know if it'll be bad, but hey its better.
+
Added Dark Medihound and Pup Dozer from Virgo
+
Clone pods no longer announce the name of the clone
+
fixed flavor text appearing when your face is hidden but you're not an Unknown
+
Tauric suits now apply an (placeholder) blood overlay, as well as their shield overlay.
+
Ashwalkers now have lungs. They cannot breath station air without suffocation effects, but are completely fine on their homeworld.
+
Carbon mobs now have a maximum tolerance to oxygen of 50kPa.
+
Deluxe synthetic lungs have a very high bonus to O2 tolerance.
+
Digitigrade legs returned to normal, since digi leg markings overlay them anyway.
+
commented out lizard mam_snout entries, because too many abominations
+
Vore Panel restored to have various interactions available again. Semi-untested but should work as advertised.
+
Vore Panel has more feedback.
+
is_wet var to bellies, toggled in the panel, will remove flesh sounding struggles and the internal loop. JSON version updated.
+
Feeding var. You will need to enable feeding to recieve any feed vore actions, but you can now feed yourself to mobs that have this set. TODO, Dogborg sleeper feeding.
+
vore mode button now required to be enabled to perform vore actions. It's the mouth icon!
+
Ash Drake vore fixed for actual reals this time
+
Mobs shouldn't spam the released contents announcement anymore on qdel or death. Only if triggered
+
Hostile mob code now properly ignores targets in bellies
+
Your belly can quietly growl if you're starving now.
+
Normal blood splattering isn't offset due to tauric mode
+
Added plasma man suit icons for taurs
+
Added bee butt for insects to have stripes
+
adjusted random spawn sprite accessories, humans won't be demi by default and lizard/mammal spawns will randomly get digitigrade legs
+
sprite adjustments for tentacles, as well as a misspelling.
+
Humans once again use ears and tail_human, as intended. This is to prevent garish randomness
+
istype for species is actually correct and usable now, it'll be a factor for monkey form expansions.
+
Hair functions are de-gendered and more easily selectable now.
+
Slimes can *wag, select markings and snouts, and yes it works.
+
Slimepeople extra parts now respect their hair_alpha in terms of being somewhat see-through. it shouldn't stand out as badly now!
+
Hunger noises are now toggled per character
+
Ashwalker den is habitable by ashwalkers again
+
Medical belts now have overlays! Now you can see if a belt is useful or just flatout empty.
+
fixed hypo MK IIs not being able to be put on medical belts
+
fixed Navy officer uniforms that failed to spawn
+
Loadout items will be forcefully added to backpacks or at your feet instead of left behind at title screen
+
hypospray kits hold 12 now, but only vials and sprays themselves
+
labcoats can carry MK II hyposprays on them now.
+
Vore Mobs are a thing now, not just ash drakes
+
Removed hunger sound stuff. never taking requests from Coolgat3 ever again. refractor: Simple Mobs use the same system regular human mobs do, itjustworks.png
+
Character Window settings unsnowflaked and normalized. I have no fucking clue how to make them work with taurs still tho, sorry.
+
added rotating background images for better clarity and contrast than just SOLID FUCKING BLACK. Images from Virgo/Polaris/Eris
+
Defib users automatically stop pulling when they attempt to perform a defib shock
+
added muzzled varients of space helmets and full masks
+
added knight_grey to taur suits, all paranormal ERT now have tauric versions enabled
+
Lava knights have digitigrade and tauric versions now
+
Added a glass version of the gas mask, because it was in the files and looked nice. does everything regular ones do except make you an unknown
+
Added custom species names! Examining people will now display their species name unless they're an Unknown or have their face hidden. like flavor text. Set it in your character window!
+
changed how health scanners print messages, wrapping it in msg for one to_chat instead of printing every line to_chat.
+
Discord bot will now report when a round ends and give the vague news ticker that a sister-station would have received for the game mode and result of the round.
+
fixed medical hardsuit overlay issue. I thought it was going to work well but fuck byond.
+
None body markings shouldn't give rgb hell, but it also should reset properly anyway. ree.
+
Sorted some sprites to better sooth my byond icon limit anxiety.
+
Box Cryopods expanded to 6 public. Permabrig cryo fixed.
+
Delta Cryopods expanded to 6 public. Permabrig cryo fixed.
PubbyStation gained one more cryopod, Permabrig's cryo fixed.
+
Omega given one more crypod as well.
+
Gulag was given a cryopod.
+
Box and Meta's cryo rooms are now a new room entirely.
+
Added erect states for all phallic bodyparts
+
YOUR DICK ACTUALLY STANDS UP NOW, YOU'RE WELCOME.
+
skintone locked genitals match the new skintone colorations.
+
added two new vaginal types and descriptions.
+
fixed borg defib runtimes
+
fixed heart attacks being nonlethal
+
Ported Oracle's cloning set up, you're now visible like cryo when being cloned, though it's a mystery until you have skin on your meat puppet existance
+
Recyclers are unable to destroy the indestructible any longer.
+
Kiara's toy sabre now actually is the correct item + icon states
+
Generic armor for taurs fixed, there isn't actually any sprites for 'em, so. Full sprites overlay over bodies, but I really can't be bothered to do all the offset fixes otherwise.
+
Large maps have had a patient room transformed into micro chemistry stations with nothing else in them. They've been labelled 'Apothecary' rooms and are accessible by doctors.
+
females now have female defined sprites
+
Slime legs have had their excess pixels adjusted
+
Mammal normal legs are more in line with human legs now
+
fixed species like abductors and golems getting the fat tiddy or pingas
+
Atmos and Station alerts should be more alerting.
+
Added visible and hidden testicles
+
Added multi-boob support. Now you can have two or three pairs of breasts.
+
fixed missing vagina and breast sprites
+
fixed prosthetic hands being invisible
+
male foxes exist again
+
female chest markings improved from being too dark in comparison to their other colors, blending better
+
Markings behave better on non-organic limbs.
+
tweaked the name of Sublter to distinguish its use
+
Gave a hint for vore posting.
+
Readded Ninja speech modifications with their mask
+
Pacifists can eat people for heal belly or noisy. Digestive modes are auto-swapped to noisy
+
Added an underwear toggle button under 'Object' tab
+
Genitals now layer under underwear. Hide these if they're too obnoxious.
+
Added digitigrade socks of all known ones anyway.
+
tweaked the Genital character creation layout to look better
+
fixed having balls/womb when you don't have the linked organ at character creation
+
fixed being able to squeeze semen directly from your balls. Probably.
+
NT Newscasters have had repeated reports of gang activity and are now looking into it.
+
NT Psykers keep mumbling about last words of someone who died. Somehow they even have a newsletter for this...
+
Gangster greeting messages are a batch message rather than 5 laggy to_chats
+
RCL now show what color is currently in use
+
Added RGB blood effects, know whose blood this is by color!
+
Added Synthetics blood, and a machine that produces it. A universal donor for medical to heal people with. Make it via medical protolathe!
+
With hearts, slimepeople shouldn't die from the effects of not having a heart.
+
Plasma vessels from xenomorphs will restore blood if you're on resin.
+
Poly's speech now echos to the chat bot.
+
Added new wings to Insects and separated fluff from old ones, they're Insect's new body markings now without being per-limb (for now).
+
Horns are now available to mammals, and they have their own color.
+
Legs are no longer a binary hack code, but actually something that can be changed. Framework for tauric adaptations.
+
Purged Modular Citadel's sprite_accessories.
+
improved the quality of a number of sprites.
+
Moths are now all insects. Avians and Aquatics are all anthromorphics. Just as planned.
+
Anthromorphs can choose their preferred gibbing meat. I guess. Snowflakes are weird.
+
Additional Gentlemen names.
+
Medical huds are now calibrated for Radioactive wavelengths.
+
Engineering equipment, blue space, and common storage containers are radiation protected
+
fixed suit storage not cleaning radiation levels of everything stuffed into them.
+
QM is able to hire/fire people to their department now.
+
cryopod UI isn't complete shit anymore
+
Cryopods purge silicon gear more efficiently now. Same with ghosts.
+
Med Sprays are now more aligned with patch mechanics
+
Chemistry is encouraged to be more varied in their healing, as well as careful in its application
+
Active NPC priority set much higher priority for the MC, with the intent on making NPC combat more interesting
+
Clarified access descriptions of some jobs
+
fixed missing deco wing states
+
fixed a few things related to vore content
-
Pubby updated:
+
Putnam3145 updated:
-
PubbyStation: Fixed disposals issue in security hallway
+
Bottles in PanD.E.M.I.C 2200 can now be replaced with an inhand bottle directly
+
Ejecting a bottle from the PanD.E.M.I.C 2200 puts it directly into the user's hand
+
Alt-clicking the PanD.E.M.I.C 2200 ejects the current bottle
+
neural nanites only work/drain if you have brain damage or traumas the nanites can fix
+
Pod people can no longer get fat from standing in the light
+
PanD.E.M.I.C 2200 now ejects onto itself instead of onto user if user's hands are full
+
Added configs for a bunch of Dynamic rule parameters.
+
Added defaults for all the configs (WIP).
+
Added dynamic midround/latejoin antag injection to the config.
+
Made starlight condensation not kill slime people.
+
Added not-killing-slime-people to the transmission threshold of plasma fixation and radioactive resonance.
+
Made the clone scanner lock while it's scanning.
-
Robustin with cat earrs updated:
+
R3dtail updated:
-
Gun overlays should be way less laggy now. remove: Chameleon guns are completely removed since they crash the server, were already made unavailable, and are the worst shitcode I've ever seen in my life.
Added a new carpet. Red! Also added said carpet to the Premium Carpet crate from the cargo supply console. Trilby said she'd take care of the crafting recipe.
-
ShizCalev updated:
+
Raptorizer updated:
-
Adminorazine will no longer kill ash lizards.
-
Adminorazine will no longer remove quirks.
-
Fixed mobs immune to radiation being killed by HIGH bursts of radiation.
-
The book of mindswap will now properly mindswap it's users.
-
Fixed a runtime with the gulag teleporter that could cause the process to fail if you removed the ID.
-
Not setting the goal of a prisoner's ID when teleporting them will now set the ID's goal to the default value (200 points at the time of this change.)
-
Fixed cigar cases & cigarette packets taking two inventory slots
-
Fixed cigar cases showing the wrong icon for the cigars inside them.
-
Fixed cigar cases & cigarette packets stating the wrong name of the cigar/cigarette when removed via altclick.
-
Fixed items in pockets vanishing when a mob is monkeyized.
-
Fixed items in pockets vanishing when a mob is gorillized.
-
Fixed items in pockets vanishing when a mob is infected with a transformation disease.
-
Fixed items in pockets not being properly deleted when a mob goes through a recycler
-
Fixed items in pockets not being properly deleted when highlander mode is enabled.
-
Fixed exploit allowing you to remove unremovable tanks from pockets.
-
Fixed items in pockets dropping when a mob is equipped with a new outfit.
-
Fixed items in pockets not being covered in blood when equipping the psycho outfit.
+
Doubled peach spawn rate
+
tweaked numbers/variables
+
rebalanced numbers/variables
+
removed unneeded code
-
SpaceManiac updated:
+
Seris02 updated:
-
The destructive analyzer can once again be used to reveal nodes.
-
Some references to "deconstructive analyzer" have been updated to "destructive".
+
Abductor Replication Lab ruin and advanced tools
+
Added looc hotkey
+
made the autoprocess button relevant
+
changes so that spooktober starts earlier
+
fixed the dark blue lum major effect
-
TGstation contributors updated:
+
Sirich96 and Dennok (ported by Ghommie) updated:
-
Nukeop eshields are now buyable. tgstation/tgstation#39025
-
Staff of storms now has admin logging. tgstation/tgstation#39011
-
Fixed a couple of inconsistencies in the uplink descriptions of SMGs and SMG ammo. tgstation/tgstation#38980
-
Fixed blob victory. tgstation/tgstation#38988
-
You can now un-ignore notifications you've clicked "never this round" on, and more. tgstation/tgstation#38990
-
Fixes a weird bug with timers. tgstation/tgstation#38994
-
(tgstation/tgstation#40043) - Beam rifles no longer open lockers
-
(tgstation/tgstation#40061) - Mobs can no longer get stuck at min/max body temperature
-
(tgstation/tgstation#40041) - Pictures of asses are now properly sized
-
(tgstation/tgstation#40084) - The lastattacker var now includes unarmed attacks
-
(tgstation/tgstation#39968) - Plastic golems can no longer ventcrawl with items in their pockets
-
(tgstation/tgstation#39885) - You can no longer crash the server by overcharging energy guns.
+
Added new Teleporter Station sprites
+
Added teleport station calibration animation.
-
Thunder12345 updated:
+
Sishen1542 updated:
-
Added a colour picker component for use with circuits.
+
Pentetic Jelly, new chemical made through mixing 1:1 slime jelly and pentetic acid.
+
Anatomic panacea now gives pent jelly instead of pent acid. Medbeams now have TRUE tox healing to heal TOXINLOVER as well.
+
Changed bible heal proc, halving the healed damage and increasing brain damage 5x in exchange for a much wider array of items to protect you from it.
+
Moved around some chems from emag list into upgrades.
+
Added some fun chems to dispensers.
+
Gave dispensers old tg functionality.
+
Leather, cardboard, bronze & bone golems!
+
Bone hurting juice and interactions with plasmamen, skeletons & bone golems!
+
Ported addition of new CAS cards.
+
Ported a fix for CAS.
+
Added the ability to alter your genitalia as a slimeperson more than addition/removal.
+
fixed genitalia removal proc in alter form.
+
Ported the inability for non-station AI to interact with station z-level.
+
HoS mains can now peacefully sleep in their office.
+
Podpeople now have customization options.
+
Removed the human check for cult conversion of captain/chaplain minds.
+
Roundstart carbon jetpacks now have full_speed FALSE.
+
Adds plasteel to medical and security techfabs.
+
Added public autolathes to all maps.
+
density = 0
+
hugboxing mining loot
+
ling blade now has 40 armor pen
+
fun
+
bad stuff
+
mech bad
+
rebalances strained muscles
+
added in the assistant response team
+
fixed up access on the centcom hangar button
+
storage tweaks for belt briefcase
+
codersprite for belt briefcase
+
added pharaoh gear to chaplain vendor
+
fixed typos in pharaoh items
+
made laser minigun not shitcode and also craftable
+
added new fire sounds for the laser minigun
+
holy lasrifle, hypertool, divine lightblade, and blessed baseball bat. Four new holy weapons!
+
stamina and force tweaks for most holy weapons.
+
prayer beads no longer deconvert after a 10 second timer, now just inject holy water for delayed effect
+
cultist runes are now destroyed with a bible or a null rod
+
bo-staff now functions as a nerfed sleepy carp staff
+
fixed kevinz code to add in non-null rod child items as holy weapons
+
fixing chems for strained muscles
+
narsie no longer asks for consent
+
removed reflect from divine lightblade
+
teleporting a locker is bad
-
Time-Green updated:
+
Sishen1542, original by @Tlaltecuhtli updated:
-
Soda is no longer intangible to the laws of physics
+
alt clicking the emitter now rotates it instead of only flipping
+
+
Sishen1542, original by @zxaber updated:
+
+
Utility mechs no longer automatically get beacons.
+
Tracking beacons no longer delete themselves when EMPing a mech, and instead have a ten-second cooldown in-between EMPs. They also now do heavy EMP damage rather than light.
+
Mechs that take EMP damage lose the use of their weapons and equipment temporarily. Movement and abilities are not effected.
+
Mechs taking EMP damage no longer roll for a random malfunction.
+
+
Sishen1542, original by Arkatos updated:
+
+
Action buttons can now be dragged onto each other to swap places
+
+
Sishen1542, original by NewSta updated:
+
+
updated the miasma canister sprites
+
+
Sishen1542, original by Skoglol updated:
+
+
Heaters/freezers now support ctrl clicking to turn on and alt clicking to min/max target temperature.
+
+
Sishen1542, original by XDTM updated:
+
+
Using the wrong surgery tool during surgery no longer attacks the patient, if on help or disarm intent.
+
Surgery steps are now shown in detail only to the surgeon and anyone standing adjacent to them; the patient and people watching from further away get a more vague/ambiguous description.
+
+
Skoglol updated:
+
+
You can now alt click storage (bags, boxes, etc) to open it.
+
+
Skully) updated:
+
+
Nudity Permit, a completely invisible uniform that still has pockets and such, to loadout options. It is more or less a direct port from the RP server.
+
+
SkullyRoberts updated:
+
+
Penis autosurgeon as rare maint loot.
+
+
TerraGS / Skoglol updated:
+
+
Adds toggleable light and blinking charge indicator to kinetic crusher
+
Kinetic crusher can now be one-hand carried. You'll still need two hand to use it.
+
+
Thalpy updated:
+
+
fixes message_admins in SDZF
+
Alkaline buffer recipe so people don't get grumpy and expanded the pH range
+
fixes buffers
+
fixes broken compiler because a var changed name
+
impure travis var anger
+
Added the ability to dispense smartdarts from the chemmaster.
+
Tweaks medolier amd chembags to allow quickpickups of smartdarts, lets the latter soak in beakers (on the floor)
+
fixed rounding errors with smartdart mixes.
+
added modified smartdartgun icon.
+
1. Kev asked that there were no antag datums used, so that's been changed. 2. Tricks can no longer turn someone into a dullahan, instead you have to spend candies to get that. I felt it was too mean to turn people into that, I didn't realise you couldn't revert it. 3. Barth will no longer as for impossible items. 4. Barth will no longer as for the same item multiple times. 5. Barth will now accept broader things, rather than asking for something, when meaning something specific. 6. Jacq will now no longer poof off the z level. 7. Jacq will (hopefully) stop spooking the AI by teleporting into there 8. Jacq will now try to teleport to a location with someone nearby. 9. Barth will tell you where Jacq is currently when you speak to him. 10. You can trade 2 candies for a Jacq Tracq (tm) 11. Jacq should stop getting mad and cover the station in gas when killed. 12. Fixed Jacq not singing (the link died). 13. Slightly changed wording so that people will hopefully get to know her. 14. Jacq no longer disappears when you're getting to know her.
Toriate updated:
-
It appears that ancient pieces of armor have wound up on the open market! These armors have degraded beyond usefulness. Grab one now in the loadout!
-
added flak jacket and M1 Helmet sprites
-
Gives the flak helmet a tiny storage compartment
-
Made the flak helmet even weaker against acid and fire so it crumbles into dust easier
-
Added the Corporate Uniform and the Silver Bike Horn
-
added sprites for the Corporate Uniform and Silver Bike Horn
+
All regular crates are now 3/4ths ToriCrates iamgeadd: Unused plastic crate sprite added
+
Blood freezer crates now have unique sprites.
+
RPD now has inhands
+
New sprites for RCDs and RPDs, inhands included
+
Updated the sprites of all the regular crates
+
+
Trilbyspaceclone updated:
+
+
cakes!
+
Made some sprites! -Love them really came out well
+
new economics
+
cargo and robotics relationships
+
unbalanced something
+
fixed a maybe oversight
+
Fun
+
costs of suit voucher
+
Unblances miner vender
+
spare cheaper brute kit
+
harm from hentie
+
rebalanced goliaths stun to be less auto death
+
Armor to blob shields
+
block weaken state to 70% from 75%
+
restores the deathriplys missing armor
+
new lockable colalr
+
armor
+
missing hopes and dreams
+
orgized the weapon file to be more cat brain friendly
+
This means sprite right?
+
Many engi flags on non-engi things
+
changed some code to be organized at a glance
+
25% < --- 50% For NPC blocking bullshit ided: Yes
+
mag gun uses cells
+
kev things their to op
+
syndicate phobia
+
other phobia's
+
laser carbine
+
makes collars only locked via key
+
charging
+
Combat inducers for COMBAT!
+
made it look nice
+
golden swag boxes
+
Crafting suitcases
+
more bountys
+
Nitryl bounty
+
better stocks
+
more evil blood fluff text
+
Added more mime names
+
replaces a sink with a autolathen
+
2 -> 3
+
MASON SUIT!
+
adds the sec jetpack to sec hardsuit storge
+
Added a few jet packs to the space queens men
+
volume of jet packs
+
Bad Idea
+
bio mass meat
+
more box options
+
a lack of replaceable boxes
+
clothing needing a emag
+
4 - > 5
+
5->6
+
4tc - > 2tc
+
mulligan costs 4 - > 3
+
Tuberculosis 12tc - > 8tc
+
15 - >10
+
both bags have the same name
+
5 - > 2
+
3 -> 1
+
2 < - 4
+
1->2 and ultra
+
shield + crafting
+
hierophant movment and melee attack
+
More plushies
+
attack verbs and descs
+
bone satchles
+
rebalanced stunslugs
+
colored boxes, and more types
+
harm and such
+
item classes
+
resonators being so shitty
+
Game braking bug critical: bug fix
+
items to syndie surgery bags
+
SNOW CONES
+
carts buy-able cargo
+
selling/time to craft
+
crafting problems, and red stamp exsplote
+
gives paper work sprites that are nicer
+
origami
+
gang tower shield
+
costs of boots
+
organ box
+
Medical breifcaseses
+
New cargo crate for tech-slugs!
+
Ammo to each fitting crate
+
Cat-code
+
fixed a few typos - Again my bad
+
fixed airless place
+
baklava
+
makes uplink kits more usefull for the risk
+
Changes some files to be better
+
As all things are not
+
fixing cat code that dosnt work, my bad
+
Arcades stealing from noodles
+
rapier
+
speedy quirk
+
Ironic
+
A bunch of minor issues with xenobiology are no more!
+
I didn't code it right it in the first place
+
new nodes
+
points and node gear
+
stuff n things
+
gear harness and a conflict merg
+
Nudity permits
+
nothing
+
Donner item
+
Luna's Gauntlets
+
rebalanced lingy dingy powery gamey
+
melee and block harm
+
sprites*
+
holster doing holster things
+
Donor item
+
Joy, Happiness, Honk
+
small mix up in terms
+
Promiscuous Organs crate, pills to lewd crate and testicles to maints
+
Made unholy water healtoxinlover
+
Zelus Oil, brass flasks
+
Added new chairs
+
Bugtesting zone upgrades for easy bug/game testing
+
more cargo to cargo
+
More loadout gear
+
Poojawa power creep
+
Not my work not my credit
+
Emitter gun
+
suit storage nulling anti magic item protection
+
rebalanced steal goals restrictions
+
fixed a few misleading goals
+
ports a fix
+
oversight in benos
+
QM rooms not getting Key Aunths
+
new books/cooking
+
less bad wording in slime
+
strawbarries and such
+
amazing things like tea of catnip, catnip and plant
+
glue uplinks
+
RPDs to drones
+
Armor and such
+
flavor
+
maybe a runtime
+
chameloen clothing
+
tons of peach themed items
+
caje
+
New book - Unused
+
organized files
+
redid brass tools to look better*
+
/cursed from a item path
+
Almost all clothing and most weaponds can be sold for pocket change
+
Cargo costs of packets and selling
+
Lowered mat selling as well as most if not all bountys
+
Adds more files for easy finding/adding in packs
+
oops not being blacklisted
+
removes some cit-modular things
+
Missing sprites with bad ones
+
emag charge amount
+
Reebe QoL aka creep in gear
+
???
+
HEY MADE THE REEBEEE WAY SMALLER - Making it less lagging hopefully
+
Surgerys and spays in bags
+
earthbloods stam regen
+
Red to Blue/Black crosses as questioned by Bhijn
+
clean bot not cleaning basic cleanables
+
new traitor bundle
+
trash
+
eye bleed :add: misstakes
+
Removed old things!
+
UI memes
+
Blue space blood bag
+
blood costs
+
Beebal and Honeybalm plants
+
Costs of crates and paperwork
+
Adds 2 more crates hacked only
+
Added two seed packets of cotten to ash walkers base
Tupinambis updated:
-
Removes the tesla coils from engineering secure storage, and places them within the engine room, functional upon being wrenched down. (Arranged in the common method of three coils on the left and right sides.)
-Reduces the width of engineering secure storage and its blast door by one tile. The machinery within has been rearranged in order to make the most commonly used machinery the most accessible.
-
Replaces the blood-red hardsuit in Deep Storage with a mining EVA hardsuit, and an included oxygen jetpack.
-
Adds a replacement to the old lavaland xeno ruins in the form of lavaland_surface_alien_nest.dmm An image of which is shown below. (The area layer is disabled for visibility.)  
-This replacement is designed to act as a sort of raid, with the queen as the raid boss. The most notable loot includes the corpse of a drone, security bio armor, a bone axe, some basic syndicate equipment, and a syringe containing alien microbes. All references to the old lavaland xeno ruins have been replaced with references to the new map file.
-
New corpse spawners for alien queens and drones.
-
New syringe containing the alien microbe reagent.
-
Removed the currently unused lavaland_surface_xeno_nest.dmm map file, and its references.
-
Added an experimental hard suit to toxins bomb test room on Box.
-
Increased the size of the toxins bomb test room, moved the telescreen, and added chairs on Box.
-
Moved some pipes out of the way on Box and Meta.
-
Two air pumps have been added to the toxins lab on Pubby and Meta.
-The following changes apply to Box, Meta, and Pubby:
-
Unbolts the toxin burn chamber doors on round start.
-
Unlocks the toxins lab air alarm on round start.
-
When spawned as a nuclear operative, you keep your characters race instead of being changed into a human. Plasmamen are an exception to this change.
-
By popular request, makes the Head of Security spawn with a telebaton instead of a stun baton.
+
Changes large parts of the nuclear operative base, including the addition of a new barracks where the ops spawn, a personal bedroom for the leader, the rearrangement of numerous rooms, some added fluff, a slightly more roomy bar, a larger hanger, a kitchen, and various other small changes to make the base feel just a bit more alive. This was achieved by completely redoing the base from scratch so there was room to work with, as a result potential bugs could crop, please do report them.
+
The drop pod chamber was airless. This seems like an oversight, and has been filled with air.
+
Cryo Sleepers have been added to Perma on all four maps in rotation. the bathroom windoor and window have switched places to accommodate this change.
+
You can now choose the pre-exisiting "loader" sprite as an appearance for your engineering borg.
+
A vast majority of references to humans within ion laws have been replaced with crew. AI modules have received similar treatment
+
Adds a syndicate themed emergency shuttle that costs 20000 credits, and can ONLY be purchased when the communications console is emagged. This shuttle features a fully stocked medbay with self serve sleepers, plenty of room that can fit highpop, a fully featured bridge, ballistic auto turrets, and an armory, EVA prep room, and bar, all of which are only accessible by either an agent ID or through hacking.
+-EVA prep features 2 syndicate hardsuits and 3 syndicate softsuits. -Armory features 5 stetchkins with spare ammo, and 2 riot c-20r's.
+
+
Lone operatives no longer spawn with a syndicate hardsuit and a bulldog. They instead spawn with a black and red EVA suit and an extra 15 TC (40 in total) 
+
The tesla engine has been replaced with a supermatter engine, and pubby engineering has been redesigned to accommodate this change.
+
The tesla engine has been completely removed along with any related components
+
RD and R&D vents are now actually connected to the air distribution.
+
New engineering hivebot. Has a bit more health but otherwise aesthetic.
+
Oldstation no longer has an excessive amounts of hivebots within it, however the bots that remain are individually a larger threat.
+
Hivebots are now more robust, with a higher melee damage output and health.
+
Remove this ruin from the blacklist or this PR is pointless.
+
the air injectors for the SM engine waste and for toxins waste should now receive power
+
Adds a mixed clothing closet to Deltastation Dorms.
+
Adds a bottle of unstable mutagen to Botany, on account of its distance from Chemistry.
+
Omegastation should no longer have any turf with missing textures, as those spots have been replaced with playing covered in a sandy turf decal.
+
Removed all living eggs from the xeno ruin because people self antag. Honk.
+
Adds a new security level between Blue and Red (Amber). The shuttle call time at this level is 8 minutes.
+
Blue security level now has a shuttle call time of 12 minutes.
+
The security level increase/decrease texts have been modified to accommodate the change.
+
Adds a code Amber sprite for the fire alarms
+
Removed the plushes from the toy crate, giving them their own.
+
Plushes are now less likely to spawn out of arcades
+
Removes a moth plush from the game.
+
added a small fire delay (3 ticks) to automatic shotguns
+
Reduced buckshot brute damage by 20%. (12.5 -> 10 brute per pellet) (75 -> 60 brute at close range)
+
Reduced rubbershot stamina damage by 40% (25 -> 15 stamina per pellet) (150 -> 90 stamina at close range)
+
Reduced beanbag stamina damage by 12.5% (80 -> 70 stamina per shot)
+
Engivend RCDs now vend upgraded RCDs
+
Beautified and stylized the cyborg HUD sprites, animated and cleaned up some of the old, modernized APC hacking and Doomsday sprites,
+
moved cyborg language select above the radio icon, instead of above the picture icon.
-
Werebear updated:
+
Twaticus & Poojawa updated:
-
Seven new holochassis options for pAIs and two new display images for pAIs.
+
Added new carpets from TauCetiStation!
+
More Liquid carpet chemicals, mix carpet with certain reagents to get different colors!
+
Tablets have a better means of being assembled codewise. nothing's different on player end.
-
Wilchen updated:
+
UntoldTactics updated:
-
Removed box of firing pins from rd's locker
+
Rewords the click here prompt given when an attempted conversion is done on an offer rune (for blood cult)
+
+
UristMcAstronaut updated:
+
+
allows a pai to activate its holoform while in a pai connector without getting derped.
+
+
Useroth updated:
+
+
the collars are now aware of their proper overlay sprites
+
The space hotel dorms are now properly boltable with the buttons inside.
+
Makes the booze-o-mat hacked by default. Alternative to https://github.com/Citadel-Station-13/Citadel-Station-13/pull/8350.
+
After the PR which raised the ammo capacity of said magazines, due to the code, they ended up with an invalid icon state. Fixed through changing the icon state name in the icon file.
+
Taeclowndo shoes which grant the four following abilities: - Conjuring a cream pie right into their hand. Every three seconds. - Making a banana peel appear out of thin air at the tile of the clown's choice. Every ten seconds. - Mega HoNk. A touch-ranged, very small AOE ability, with effect equal to being honked by a Honkerblast on a clown mech, with the effects halved for anyone who isn't its direct target. Every ten seconds. - Bluespace Banana Pie. You don't throw this one... not right away at least. This baby can fit an entire body inside. Good for disposal of evidence. 25 second-long action, 45 second cooldown. Also produces a "[victim's name] cream pie". The body drops out of the pie if you splat it somewhere or destroy the pie. If you eat it, it will chestburst out of you a'la monkey cube.
+It's a 14 TC item for traitor clowns and a 12 TC item for clown-ops.
+
The tentacle now directly puts the item in your hands, instead of toggling your throwing and tossing it at you. Tentacles suffer from ranged inaccuracies as if they were guns, I think it's enough of an inconvenience.
+
Makes the netting much less clunky. If there's only one target you can net while you press the button, it will just net that target instead of bringing up a list of mobs.
+
Energy nets now revive and fully heal capturees (even dead ones, after calculating points). If someone's got a scan and wants to get cloned, they can always kill themselves still.
+
Capture points are added on capture, rather than round-end, so it no longer matters whether your captures kill themselves in the holding facility or not.
+
Makes the nets a bit more sturdy. (previously it took mere two welder hits to break one)
+
Makes stungloves actually stun people (currently comparably with stunbatons, adjustable). Because electrocute_act(25, H) did fuck all, stunwise, and on top of that, people in insulated gloves were completely unaffected.
+
Reduced the stunglove electrocute_act value to 15 due to above. Could possibly be lowered further.
+
+
Weblure updated:
+
+
Added the relevant Beepsky animations from TG's aibots.dmi file to Cit's aibots.dmi file.
+
+
WhiteHusky updated:
+
+
Sleepers now show blood level and type.
+
Changed the styling of arousal messages to use pink-ish colors.
+
The orgasm moodlet message new-lines properly.
+
Flavor text with special characters will not get partially unescaped.
+
Canceling when setting flavor text does not clear it anymore.
+
Checking yourself shouldn't freeze the client anymore.
XDTM updated:
-
Fixed anti-magic not working at all.
-
Diseases now properly lose scan invisibility if their stealth drops below the required threshold.
-
Coldproof mobs can now be cooled down, but are still immune to the negative effects of cold.
-
This also fixes some edge cases (freezing beams) where mobs could be cooled down and damaged despite cold resistance.
-
Androids are now immune to radiation.
-
-
Xhuis updated:
-
-
Character traits are now called character quirks. Functionality remains unaffected.
-
-
Zxaber updated:
-
-
Cyborgs can wear more hats now.
-
-
and Fel updated:
-
-
New chairs are on most shuttles! Finally, you can relax in style while escaping a metal death trap.
-
-
armhulen updated:
-
-
chameleon guns are disabled for breaking the server
-
-
cacogen updated:
-
-
You can now see what other people are eating or drinking.
-
Borg shaker can now synthesise milk, lemon juice, banana juice and coffee
-
Renamed drinks no longer revert to their original name when their reagents change
-
-
cyclowns updated:
-
-
Fires no longer flicker back and forth like crazy
-
Fusion has been re-enabled! It works similarly to before, but with some slight modification.
-
Fusion now requires huge amounts of plasma and tritium, as well as a very high thermal energy and temperature to start. There are several tiers of fusion that cause different benefits and effects.
-
The fusion power of most gases has been tweaked to allow for more interesting interactions.
-
BZ now takes N2O and plasma to create, rather than tritium and plasma.
-
Fusion no longer delivers server-crashingly large amounts of radiation and stationwide EMPs.
-
-
deathride58 updated:
-
-
(Only visible on 512) Stamina crit will now result in the mob's sprite subtly darkening around its edges.
-
Added a tiny reference item to a year-old weeby game. If you're a traitor, you can find this item in the "badassery" section of the uplink. It's free, and you can order up to 4 of them! The effects of this item are only visible on 512.
-
Added a component signal for toggling combat mode on/off.
-
The cleaving saw now deals less staminaloss to its user while inactive.
-
You can now make use of custom say verbs with the [say verb*message] format
-
Yelling will now echo and penetrate walls
-
Distant voices now have smaller text
-
You can now see the amount of charges an emag has by examining it
-
Emags now make a quiet noise when they're close to running out of charges.
-
Emags are no longer irreversibly destroyed upon running out of charges.
-
Traitors can now purchase emag recharge devices for 2 TC. They have five extra charges each, and can be found in the devices and tools section of the uplink.. There's no cap on the amount of charges a single emag can have, though do be aware that upstream spaghetti code makes it easy to waste charges.
-
Small emag flavortext changes here and there
-
The warden's particle defender now deals less staminaloss when in stun mode.
-
"code [alert level]" has been changed to "[alert level] alert" on the hub entry.
-
The hub entry now displays the current map.
-
Lavaland is no longer fullbright. We have memory to spare.
-
Adds the wheelofsalt command to TGS3. Spin the wheel of salt to find out what the Citadel Station 13 players are salting about today!
-
You can now slam or slap your hands onto tables by right clicking them in combat mode.
-
Non-admins can no longer use LOOC while dead, unconscious, in crit, or while ghosting.
-
The syndicate mask available in the uplink will now inject you with a chem that cuts your click delay in half and increases your stamina regeneration, when you enter combat mode. The mask has a five minute cooldown between adrenaline injections.
-
Dogborgs will now reduce firestacks when they use their tongue to lick someone's face.
-
The repo compiles again
-
The flag cape donor item should render properly now.
-
The default amount of z-levels reserved specifically for space ruin generation has been reduced from 7 to 1
-
Items now spawn on top of, rather than inside, closets and other storage structures
-
Jukeboxes now have realtime directional audio, complete with occlusion when you're far away or behind a wall.
-
More than one jukebox can play a song at a time now. Have up to 5 jukeboxes playing at once!
-
Devs can now control the wet and dry channels of sounds played via playsound_local. The new envwet and envdry arguments will control the volume of the wet and dry track, respectively.
-
Jukeboxes have been turned into a subsystem. Track initialization, audio playing, etc, are now handled via SSJukeboxes instead of via the jukebox object procs.
-
Jukebox tracks now require an additional ID field at the end of their name. This will make it easier to add jukebox-style objects that are only capable of playing specific songs, without worrying about copyright issues.
-
Added Raiq's boombox as a donor item
-
You can now manipulate tails, ears, body markings, mutant colors, and taur types via DNA console!
-
Reduced the exponent on gas tank ruptures. TTVs and suicide onetanks that were previously 20dev are now approximately 9.6dev. Let's see the actual toxins nerds adapt!
-
When a custom say verb message is spoken without any actual words, the text will render without a `, ""` at the end of it.
-
The combat rework's training wheels have been removed. Knockdowns no longer have any noticeable stun. This indirectly means stunbatons and tasers will always deal their full stamloss on hit.
-
The stamloss required for boxing gloves to throw a knockout punch has been increased from 50 to 100.
-
You can now prime the grenade on bombspears by using them in your hand. The wield hotkey is moved to combat mode rightclick while a spear has a grenade on it. This is explained in the examine text.
-
Bombspears no longer instantly explode on impact when thrown. They now have to be primed to explode when thrown.
-
Bombspears now have 90% embed chance.
-
If an embedded item is normal sized or larger, you can take it out instantly by pressing resist.
-
Embedded items are now much harder to pull out the smaller they are, rather than the other way around. It's much easier to rip out a sword from your chest than it is a shard of glass in your face.
-
The message you get when you get bounced by the PB is now a little more clear about what you need to do to gain access to the server.
-
The jukebox now falls off over a greater distance. You can now actually hear the jukebox while sitting in a far corner of the bar, or while passing through the main hallways.
-
Added antag OOC. This is disabled by default, but you can access it with the "AOOC" verb as an antagonist when an administrator enables it.
-
LOOC now supports emojis
-
Deadchat and asay will now both render emojis! :snya:
-
The disarm attack on EMP'd defibs now has an interruptible 1 second timer before it actually lands.
-
The stamina buffer now only takes 1 second to start regenerating.
-
Disablers have had their damage reduced from 36 stamloss to 24 stamloss, increasing their shots to stamcrit from 4 to 6.
-
Tasers have had their damage increased from 55 stamloss total to 61 stamloss total. Shots required to stamcrit are unaffected.
-
Introducing the Kitchen Gun (TM)! Say goodbye to daily stains and dirty surfaces with Kitchen Gun (TM)! Just five shots from Kitchen Gun (TM), and it'll sparkle like new! Includes two extra ammunition clips for the low, low price of just 10 TC! Laser sight and night vision accessories sold separately! Magazines can be purchased individually for 1 TC a pop!
-
Active turf processing is now its own subsystem.
-
Ports tgstation/tgstation#39287 - You can now configure how fast a mob fires, and how many shots they fire in a single burst
-
When you spawn as a miner, you'll get text clarifying your job description. You might not think it's necessary, but believe me, it is.
-
mushroom people are now roundstart on live
-
The geargroupID var of loadout entries can now be a list rather than a string. GeargroupID changes are additive when multiple are defined in a single loadout entry.
-
-
deathride58 (Original PR by Basilman/Militaires) updated:
-
-
Ported TGstation's Agent Stealth Box! You can the implanter in the syndicate uplink for 8 TC. Credit goes to Basilman/Militaires. This port includes minor adjustments, see the GitHub for details.
-
-
hatterhat after being yelled at by kevinz updated:
-
-
deletes an entire line that might fix flash icons idk blame him if it gets worse
-
-
iksyp updated:
-
-
stacking machines and their consoles no longer dissapear into the shadow realm when broken
-
you can link the stacking machine and its console by using a multitool
-
Ever since the great emotion purge of 2558, people were able to work at top efficiency, even while starving to death. This is no longer the case, Nanotrasen Scientists say.
-
Hunger slowdown only applies if mood is disabled in the config.
-
-
imsxz updated:
-
-
Using mayhem bottles and going under their effects is now logged.
-
-
izzyinbox updated:
-
-
Added an integrated circuit part that interacts with the arousal system
-
changes the admin-pm input box from single line to multi-line
-
Tennis balls now equip and show up in the correct slots
-
Adds option in the hide/expose genitals verb to hide genitals even without clothes
-
-
kevinz000 updated:
-
-
Cameras now can take pictures up to 7x7. Alt click them to change their width/height from the default 3x3.
-
Photos are now logged to disk, assuming the host enabled the configuration option
-
If the above is enabled, albums/frames can now have their persistence IDs set in variables to allow for PHOTO PERSISTENCE
-
Every head of staff gets a unique album with its own ID in their locker. Let your successors know about your accomplishments, screwups, and everything in between!
-
All of this works or should work with newcasters/pdas/etc etc
-
Photo taking now clones the area into transit space and then operates on it, instead of on the spot, in theory making photographing things more accurate?
-
-
nicc updated:
-
-
no more dark locker corner woo
-
area alterations
-
escape pod
-
see above
-
adds windoor to the plastic flaps in the atmos lobby
-
-
ninjanomnom updated:
-
-
A plush that knows too much has found its way to the bus ruin.
-
-
resistor updated:
-
-
Added circuit labels! You can now customize the description of your assemblies.
-
-
slate3 updated:
-
-
ported a new alternative sprite for engineering borgs, mr. handy
-
ported a new alternative sprite for security borgs, a spider-like walker
-
ported a new alternative sprite for medical borgs, an eyebot
-
-
steamport updated:
-
-
Borgs/AIs can now toggle rad collectors
-
-
ursamedium updated:
-
-
slapping / slamming hands on tables now uses appropriate pronouns
-
crow pAI is no longer invisible while resting
-
-
yenwodyah updated:
-
-
A few virus threshold effects should work now
-
-
yorii updated:
-
-
Fixed the smartfridges to be in line with all other machines and puts the released item in your hand.
-
-
yorpan updated:
-
-
Brain damage makes you say one more thing.
-
-
-
04 September 2018
-
Denton updated:
-
-
Mech construction messages no longer incorrectly mention high-tier stock parts.
-
Added a nanite lab to Deltastation! It's at the old EXPERIMENTOR lab.
-
Delta: Moved the Xenobiology disposals bin to be less obstructive. Added two sets of insulated gloves to Engineering.
-
Delta: Fixed scientists not having maintenance access near the circuitry lab and toxins launch chamber.
-
-
Shdorsh updated:
-
-
Made all the extinguishers use less sleep and spawn procs
-
-
-
03 September 2018
-
Cdey78 (Ported by Floyd / Qustinnus) updated:
-
-
AI can now think
-
New OOC emote: :thinking:!
-
-
Naksu updated:
-
-
a new admin secret has been added to create a customized portal storm
-
-
Shdorsh updated:
-
-
Makes it possible to create circuits that can get an item loaded into them while they are in an assembly and the assembly is open.
-
Optimized electronic assemblies also.
-
A bug pertaining putting batteries in assemblies
-
-
Skoglol updated:
-
-
Eggplant and egg-plant seeds now have different names and plant names.
-
-
XDTM updated:
-
-
Fixed nanite cloud storage not allowing uploads.
-
-
octareenroon91 updated:
-
-
Supermatter more likely to log fingerprintslast when it consumes any object.
-
-
-
02 September 2018
-
Denton updated:
-
-
Fixed species type names that show up on health scanners.
-
-
-
01 September 2018
-
ElPresidentePoole updated:
-
-
removes curator's fear of snakes
-
-
McDonald072 updated:
-
-
Defibrillator nanites work properly.
-
-
Poojawa updated:
-
-
fixed clothing vendor fedoras having Detective Fedora grade armor
-
-
Potato Masher updated:
-
-
The color of Wooden golems should be more in line with the color of the wood used to make it.
-
-
WJohnston updated:
-
-
Reinforced floors are now shinier.
-
-
-
31 August 2018
-
Anonmare updated:
-
-
AIs can now turn shield generators on and off again
-
-
Denton updated:
-
-
Plastic golems can no longer vent crawl with items in their pockets.
-
-
Mickyan updated:
-
-
Skateboards can fit in backpacks
-
Skateboards are slower by default, speed can be adjusted by alt-clicking
-
Show your support for the fine arts with these new quirks:
-
Tagger: drawing graffiti takes half as many charges off your spraycan/crayon
-
Photographer: halves the cooldown after taking a picture
-
Musician: tune instruments to temporarily give your music beneficial effects such as clearing minor debuffs and improving mood.
-
-
Skoglol updated:
-
-
Dispensers can now add 5u to buckets, plastic beakers and metamaterial beakers, down from 10u.
-
You can now pour 5u from buckets, plastic beakers and metamaterial beakers, down from 10u.
-
Chem dispenser window width increased slightly, no longer shuffles buttons when scroll bar appears.
-
-
The Dreamweaver updated:
-
-
Sentience Potions no longer require you to have Xenomorph toggled on in preferences and now relies on its own preference in order to be notified of open roles.
-
Split xenomorph, intelligence potions, and mind transfer potions into separate roles for more precise role management.
-
Sentience Potion Spawns and Mind Transfer Potions are now job-bannable roles.
-
-
Time-Green and locker sprites by MrDoomBringer updated:
-
-
Reports have come in that the wizard federation has harnessed some of the ancient locker force to create a wand
-
-
XDTM updated:
-
-
Removed the chance of spouting brain damage lines when over 60 brain damage. The dumbness trauma still has them.
-
Fixed Mechanical Repair nanites not working.
-
-
ninjanomnom updated:
-
-
Computers are now visible even in the darkest of rooms. Comfy!
-
Because computers are now far easier to find in dark rooms their base light output has been reduced.
-
Broken components left over from the signal origin refactor should be fixed.
-
Lava isn't a safe place to throw your flammable shit anymore
-
The computer screen overlay being rotated incorrectly after construction has been fixed.
-
-
-
28 August 2018
-
Denton updated:
-
-
The 10 second anti spam cooldown of night shift lighting now works properly.
-
Added an examine message to APCs that mentions Alt-click and Ctrl-click (silicons only) behavior.
-
-
Garen updated:
-
-
adds a signal for screwdriver_act
-
-
SpaceManiac updated:
-
-
Multiple copies of a shuttle each get their own area instances (affects APCs and air alarms).
-
-
XDTM updated:
-
-
The forcefield projector is now available ingame in the engineering protolathe. It can project up to 3 forcefields which act as transparent walls, and share a pool of health which is recharged over time. The projector must remain within 7 tiles of the forcefields to keep them active.
-
-
-
26 August 2018
-
CitrusGender updated:
-
-
Added note severity to [most] bans and the notes associated with them
-
Banning panel now has a severity option UI: Changed the UI of the note panel UI: Changed the UI again, added some icons, removed brackets in urls, fading out notes cannot be selected to expand the browser anymore
-
-
Floyd / Qustinnus (Credits to KMC for the sprites) updated:
-
-
The Clown Car, your 18TC clown-only solution to asshole co-workers
-
Regular car implementation (makes it easier to add more cars if someone actually feels like adding those)
-
-
JJRcop updated:
-
-
Asay logs show "ADMINPRIVATE: ASAY:" again instead of just "ADMINPRIVATE:"
-
-
Naksu updated:
-
-
living and stack typecaches now use a shared instance where it makes sense, giving small memory savings
-
-
PKPenguin321 updated:
-
-
Integrated circuit medium screens have been readded. They are now called large screens. They now only work from your hands or on the ground when you're standing on top of them (NOT from pockets, lockers, backpacks, etc).
-
Roundstart cyborgs will now be properly referred to as "it."
-
-
SpaceManiac updated:
-
-
The shuttle manipulator now allows flying any shuttle to any port which will fit it.
-
The shuttle manipulator now allows fast-travelling shuttles with 5s remaining, down from 50s.
-
Status displays have been refactored to be cleaner and more flexible.
-
The AI dying properly updates its status displays again.
-
-
intrnlerr updated:
-
-
Refactored nettles to be reagent_containers
-
-
nicbn updated:
-
-
Nanotrasen shoes no longer contain Silencium. Now footsteps make noise! Sounds from Baystation.
-
-
-
25 August 2018
-
Denton updated:
-
-
Added missing export rewards for various lavaland items (tendril/megafauna/ruins) and engine parts.
-
Increased export values for emitters, PA parts, field generators and radiation collectors to match the rest of engineering exports. Reduced supermatter shard value by 1000 credits.
-
Removed export rewards for red/blue warp cubes since they're blacklisted from the cargo shuttle.
-
Added private intercoms to the confession booths of the Deltastation+Pubbystation chapels.
-
Fixed invalid radio frequencies on interrogation chamber/confession booth intercoms.
-
Anime is even more horrifying than previously discovered!
-
Added a new shuttle loan event where crew can get paid for having an active syndicate bomb delivered to cargo bay.
-
-
Mickyan updated:
-
-
Blue polo undershirt option has been restored
-
underwear "nude" option moved to the top of the list
-
-
SpaceManiac updated:
-
-
The map loader now supports vars to be set to lists containing non-strings.
-
Overcharging energy guns no longer crashes the server.
-
Ordering the Build Your Own Shuttle kit no longer crashes the server.
-
-
The Dreamweaver updated:
-
-
Refactored gift code to fix a minor inefficiency.
-
-
XDTM updated:
-
-
Fixed chest and head augmentation not working properly.
-
-
-
23 August 2018
-
Naksu updated:
-
-
Waddling is now available as a component
-
-
Nervere updated:
-
-
re-adds the joy emoji.
-
-
SpaceManiac updated:
-
-
The body zone selector now indicates which body part you are about to select when hovered over.
-
Transit space initializes about five seconds faster.
-
-
Tlaltecuhtli updated:
-
-
Cyborg ion thrusters consume 1/5 of their previous power.
-
-
-
22 August 2018
-
BlueNothing updated:
-
-
Allows video camera circuits to be seen on networks other than the science cameranet.
-
Alphabetizes camera list for camera bugs, and lets camera bugs see through borg and circuit cameras.
-
Makes video camera circuits fit in tiny assemblies.
-
-
PKPenguin321 updated:
-
-
The GPS circuit now has a 4th output, placing X,Y,Z all in a string.
-
2 new converters: Rel to Abs, and Advanced Rel to Abs.
-
Rel to Abs takes a set of relative and a set of absolute coordinates, and converts the relative one to absolute. 1 complexity.
-
Advanced Rel to Abs takes a set of relative coordinates and converts it to absolute without the need for an already known set of absolute coordinates. 2 complexity.
-
-
SpaceManiac updated:
-
-
Freezers and heaters which start on no longer stay visually on when you turn them off.
-
Atmospherics now initializes 93% (about 40 seconds) faster.
-
-
floyd updated:
-
-
fixes the hunger alert appearing forever
-
-
intrnlerr updated:
-
-
Tank temperature is no longer based on pressure
-
-
ninjanomnom updated:
-
-
Shuttle templates now handle shuttle registration in the load rather than the shuttle manipulator. This means admin loaded shuttle templates no longer need to be manually registered.
-
-
oranges updated:
-
-
Inventory overlay now uses a traffic light to indicate if the item can be placed in there
-
-
-
20 August 2018
-
Basilman updated:
-
-
Added gondola fur products
-
-
Basilman, Sprites by WJohnston updated:
-
-
His Grace ascension is back, feed Him 25 people and you will unlock His full potential.
-
-
Denton updated:
-
-
Added new destinations for the parcel tagger! You can now send packages to the Circuitry Lab, Toxins, Dormitories, Virology, Xenobiology, Law Office and the Detective's office. Viro/Xeno can only receive parcels.
-
Deltastation: Tagged parcels no longer get routed straight into the crusher. Untagged parcels also no longer get routed straight into the crusher!
-
Deltastation: Added disposals to Xenobiology that launch contents into space.
-
-
Epoc updated:
-
-
Putting an extinguisher into a cabinet with the safety off will no longer cause it to spray first
-
-
Floyd / Qustinnus updated:
-
-
removes useless mood events subtypes
-
fixes mood event timers not resetting when they get triggered again remove: removes the depression overlay which makes our fruit happy
-
-
Frosty Fridge updated:
-
-
Added the Surgical Processor upgrade for medical cyborgs. Scan surgery disks or an operating computer to be able to initiate advanced procedures.
-
Cyborgs can now perform surgery steps that do not require an instrument.
-
Plastic creation reaction now properly scales with the amount of reagents; 10u = 1 sheet.
-
-
Garen updated:
-
-
fixed using items on a circuit removing all its access(now access gained from each new item stacks)
-
adds logging for gun circuits, grabber circuits, and dragging claw circuits
-
grabbers can select what they want to drop
-
-
MrDoomBringer updated:
-
-
The Nanotrasen Airspace Aesthetics division has shipped out a newer design of NT-Brand "Ore Silos". No new features have been added, but they certainly look much nicer!
-
-
Naksu updated:
-
-
Having a high body temperature now increases the damage you take gradually, whether you're on fire or not. Being on fire also always increases body temperature damage
-
-
NewSta updated:
-
-
The names of haircuts, facial hair, undershirts, underwear and socks have now been sorted and categorized
-
-
WJohnston updated:
-
-
Remade titanium and plastitanium floors to be less of an eye strain and something mappers might actually consider using.
-
New reinforced floor sprites.
-
-
XDTM updated:
-
-
Added programmable nanites to science!
-
Science now has a nanite chamber, a nanite program hub, a nanite cloud console and a nanite programmer.
-
From the program hub you can download nanite programs (unlocked through techwebs) to disks.
-
You can then customize their functionality and signal codes through the Nanite Programmer.
-
The nanite chamber is necesary to inject nanites into a patient, and it's also used to install/uninstall programs into a patient's nanites. A second person is required to man the console.
-
The nanite cloud console controls remote program storage; it stores program backups that nanites can be synced to through cloud IDs.
-
Nanite programs range can be either helpful or harmful; their main potential is that they can be enabled at will through the use of remotes and sensors. The potential uses are endless!
-
More detailed information is available in the wiki.
-
-
-
18 August 2018
-
Floyd / Qustinnus updated:
-
-
moves nutrition events to the mood component
-
-
Jared-Fogle updated:
-
-
Hovering over storage slots with an item in your hand will show you first if you can put the item in.
-
-
XDTM updated:
-
-
Fixed augmentation not working and/or giving you extra limbs
-
-
nicbn updated:
-
-
New janitor cart sprites (by Quantum-M)
-
Dirt is smooth (by AndrewMontagne)
-
-
zaracka updated:
-
-
You can now use certain emotes and the suicide verb while buckled, but not while stunned.
-
-
-
17 August 2018
-
Anonmare updated:
-
-
Ore silos circuit boards are now constructable
-
-
SpaceManiac updated:
-
-
The "Map Template - Upload" verb now reports if a map uses nonexistent paths.
-
-
Tlaltecuhtli updated:
-
-
fixes diamond drill bounty having the wrong object path
+
Added the experimental dissection surgery, which can be performed once per corpse to gain techweb points.
+
Rarer specimens are more valuable, so xenos and rare species are more efficient subjects.
+
Added two new surgery procedures, under the Experimental Surgery techweb node.
+
Ligament Hook makes it so you can attach limbs manually (like skeletons) but makes dismemberment more likely as well.
+
Ligament Reinforcement prevents dismemberment, but makes limbs easier to disable through damage.
+
Golem limbs can now be disabled, although they are still undismemberable.
YPOQ updated:
-
Roundstart motion-detecting cameras work again
+
Stealth implants work again
-
intrnlerr updated:
+
Yakumo Chen updated:
-
"Allows image windows sent by PDA to be closed"
+
Made stealth implant boxes flimsier
+
Autocloning now requires tier 4 parts
+
Removes autoscan
+
Scanning people now requires someone to operate the cloning computer regardless of part level.
+
removed antimagic component from holymelon
-
-
15 August 2018
-
barbedwireqtip updated:
+
YakumoChen updated:
-
added binoculars to the detective's locker
+
AEGs brought more in line with current radiation system. Try not to get EMP'd.
+
Jetpacks no longer last twice as long between air refills.
+
Reverted laser miniguns.
+
Adds beanbag slugs to the sec protolathe at round start
+
Brings shotgun ammo availability back in like between seclathe and autolathe.
-
-
14 August 2018
-
Coolguy3289 updated:
+
Zargserg updated:
-
Removed un-needed and un-used RENAME comment from game_options.txt
+
Lungs maximum toxin threshold is 0.5% of the atmosphere.
+
Permanently contaminated atmosphere does not murder crew anymore.
-
SpaceManiac updated:
+
ZeroNetAlpha updated:
-
Escape Pod 1 now reaches the CentCom recovery ship again.
-
-
WJohn updated:
-
-
Titanium walls and windows are a bit prettier looking now.
-
-
Zxaber updated:
-
-
Airlock electronics can have now have unrestricted access by direction set. The resulting airlock will allow all traffic from the specified direction(s) while still requiring normal access otherwise. A small floor light will indicate this.
-
Medbay Cloning and Main Access doors now have unrestricted access settings set, and the buttons have been removed. All maps have been updated.
-
Airlocks now correctly update their overlays (bolts lights, emergency lights) when their power state changes.
-
-
-
13 August 2018
-
Basilman updated:
-
-
Adds Arnold pizza, dont try putting pineapple on it.
-
-
Denton updated:
-
-
The briefcase launchpad can now hold items while in briefcase mode (just like a regular briefcase). Its remote has been disguised as a folder and now spawns pre-linked inside the briefcase.
-
Increased the briefcase launchpad's range from 3 to 8 tiles, which is roughly half the screen.
-
Added more ingame manuals that access wiki pages.
-
Added botanical and medical bounties as well as a static adamantine bar bounty.
-
Increased the syndicate document bounty's reward from 10.000 to 15.000 credits.
-
Removed the gondola hide bounty and in return, increased the export value to the old level.
-
The briefcase bounty now also accepts secure briefcases.
-
The action figure bounty now correctly spawns as an assistant type bounty.
-
-
Logging refactor and improvement updated:
-
-
All mob-related logs now include the area name and (x,y,z) position.
-
All logs that included an (x,y,z) position now also include the area name.
-
Standardized logging format of mob/player keys.
-
Telecomms logs are now included in the individual logging panel.
-
Fixed many other cases of logs being sent to either the individual logging panel or the saved log files, but not both.
-
The logging system has been refactored to contain less redundant code and to produce more consistent logs.
-
-
SpaceManiac updated:
-
-
The VV window loads and searches faster.
-
Fields in the VV window's header will immediately show your edits.
-
Selecting an action from the VV dropdown no longer leaves it selected after the action is done.
-
-
YPOQ updated:
-
-
Uncalibrated teleporters can turn humans into flies again
-
-
-
12 August 2018
-
Denton updated:
-
-
Killing gondolas now lets you harvest meat from them. Eating it raw might be a bad idea.
-
-
Mickyan updated:
-
-
Mixed drinks now give mood boosts with varying strength depending on their quality.
-
Although powerful, mood boosts from quality drinks are short lived. If you want to make the most out of them, take a sip every few minutes like a normal human being instead of downing the entire glass like the alcoholic you are.
-
-
Nichlas0010 updated:
-
-
Admins with +admin and without +fun are no longer able to smite.
-
-
SpaceManiac updated:
-
-
Blood and oil footprints sharing a tile no longer causes footprint decals to stack.
-
-
WJohnston updated:
-
-
Syndicate (melee) simple animals will now move less predictably and attack twice as often, hopefully making them quite a bit more dangerous.
-
-
XDTM updated:
-
-
Operating Computers can now sync to the research database to acquire researched surgeries, instead of requiring installation by disk.
-
You can now review the full list of unlocked surgeries from the operating computer.
+
Cleans up autoylathe code and brings it back in line with the regular autolathe.
+
Fixes autoylathe interface not updating propperly.
+
Silicons are now consumable by scrub pups.
actioninja updated:
-
Added (unobtainable) Felinid Mutation Toxin.
+
APC UI autoupdates correctly
-
lyman updated:
+
bluespace bio bags updated:
-
Updated the Chronosuit Helmet sprite.
+
Added bluespace bio bags and put it in the tech web, in the node applied bluespace
+
added a crappy icon for bluespace bio bags
-
-
11 August 2018
-
Denton updated:
+
chef updated:
-
Fixed the Beer Day date and added a few more holidays.
+
Added main hallway approach to monastery
+
Added Maintenance hallway approach, with some maint loot
+
moved the docking arm for the white ship
+
changed placement of some grills and windows
-
Jordie0608 updated:
+
coiax updated:
-
Asay history is once again logged under the admin log secret.
-
Notes, messages, memos and watchlists can now have an expiry time. Once expired they are hidden like as if deleted.
+
When the nuclear disk stays stationary long enough to trigger an increase for the lone op event chance, admins will be notified every five increments.
-
SpaceManiac updated:
+
dapnee updated:
-
Giant spiders can now freely pull their victims through webs.
Plasmaglass structures now drop plasmaglass shards instead of nothing
+
Trim lines!
+
You can now make plasmaglass tables again.
-
Time-Green updated:
+
deathride58 updated:
-
Circuit Boards now tell you the components required to build them on examine
+
When a gamemode fails pre_setup, it will now send a message in admin IRC and in ingame admin chat, instead of only being viewable in the logs.
+
Portal guns now spawn without firing pins.
+
Reduced the default/baseline nanite pool amount from 100 nanites to 25 nanites, and reduced the maximum nanite amount from 500 nanites to 125 nanites. The safety threshold was reduced from 50 nanites to 12 nanites.
+
Most of Lavaland's mobs are now on crack.
+
Blood drunk miners now move once every two ticks, rather than once every three ticks.
+
Bubblegum now has a maximum movement speed of once every three ticks. Buffed from the original value of once per 5 ticks.
+
The minimum time for the Colossus to attack again after firing a random shot is two deciseconds, Sped up from the original value of three seconds. The minimum time for the Colossus to attack again after performing a blast is now one second, with the original value being two seconds. The minimum time for it to attack again after performing its alternating shot pattern is now two seconds, original value being four seconds.
+
Ashdrakes now move once every five ticks, rather than once every ten ticks.
+
Heirophant chasers now move once every two ticks rather than three ticks by default, and the chaser cooldown has been reduced from 10 seconds to 5 seconds. The cooldown for the Heirophant's major attacks has also been sped up to 4 seconds from the original value of 6 seconds.
+
The Legion (megafauna) now moves at two ticks per second rather than three ticks. It additionally now actually moves faster while charging. The cooldown timer for it's special attacks has been reduced from 2 seconds to 1 second. Additionally, The Legion's view range has been decreased from 13 tiles to 10 tiles.
+
All megafauna now have a default view range of 4 tiles, decreased from the original of 5 tiles, and an aggro'd view range of 15 tiles, decreased from the original of 18
+
Goliaths now move once every ten ticks, sped up from the original value of 40(!!!) ticks. Additionally, their cooldown for their tentacles has been reduced from 12 seconds to 6 seconds. To compensate, their cooldown now only decreases by 5 deciseconds every time they're attacked, rather than 10 deciseconds, their melee damage has been reduced to 18 per hit from 25 per hit, and their vision range has been decreased from 5 tiles unaggroed, 9 tiles when aggroed, to 4 tiles and 7 tiles respectively. Ancient goliaths have a default attack cooldown of 8 seconds, sped up from the original value of 12 seconds.
+
Legion (the common mob) now has a cooldown of 1.5 seconds on their skull attack, sped up from the original value of 2 seconds. Additionally, their view range has been decreased from 5 tiles, 9 tiles when aggroed, to 4 tiles, 7 tiles when aggroed.
+
Stamina no longer regenerates at hyper speeds.
+
To accommodate for upstream's stamina changes, knockdown() now applies staminaloss only to the chest.
+
adjuststaminaloss() now has a new argument that allows you to specify a zone to apply staminaloss to. This defaults to the chest
+
apply_damage() is now capable of healing carbon mobs and human mobs.
+
Since the head has the same exact effects as the chest when disabled, and doesn't really make much sense to be affected by stamina, the head no longer has stamina.
+
The chest now has a stamina cap of 200 stamina due to the above.
+
Footsteps now sound mostly the same as they did before the hard sync
+
Jukeboxes now properly remove themselves from the active jukebox list when destroyed
+
Server operators and badmins can now make the server play like TG by toggling the stamina buffer on/off using the DISABLE_STAMBUFFER config option.
+
Airlock wires now work as they did prior to the hard sync
+
The thing you're currently grabbing is now taken into account when left-click disarming. Things you have grabbed now roughly have a 45% chance to be disarmed.
+
Disarm push rolls are now determined by the target's staminaloss rather than a flat number.
+
When you're in combat mode, pushing someone who isn't in combat mode is a guaranteed knockdown. Hard counter to stam regen squeezing in melee combat.
+
Failed disarm push attempts now deals light staminaloss to the target so long as both the attacker and target are standing. The total stamloss dealt to the target is random, clocking in at a very inefficient 1-5 stamloss per unsuccessful push attempt.
+
Disarm pushes now play the thudswoosh sound regardless if they're successful or not. Had it not been for copyright, I would've used L4D's melee sound.
+
Disarm push attempts are now logged
+
Autostand no longer makes you invulnerable to dropping items when being knocked down with a force greater than 80
+
You can no longer abuse an href exploit to return from the labor camp before obtaining enough points to satisfy your point goal.
+
Norko's donor item is now listed in the right category
+
The medihound sleeper now has a non-vore variant. This will be used by default. The old voracious variant will only appear if both the person being sleeper'd and the medihound have the voracious hound sleepers pref enabled. Sprites by Toriate
+
"Allow medihound sleeper" is now labelled "Voracious medihound sleepers", and is now off by default
+
AOOC no longer prints to players in the lobby
+
Human tails and human ears now save again. Humans now use mam_tail and mam_ears for their snowflake bits instead of tg's equivalent, just as they did prior to human tail and ear saving breaking
+
Disarm pushes no longer deal staminaloss to resting targets
+
You can no longer force a hard stamcritted spaceman to stand by clicking them with help intent. Get more creative if you want to torture someone that's in hard stamcrit.
+
The revolution gamemode now waits until the 20 minute mark before checking for win conditions.
+
You can no longer resist/move out of grabs while you're resting. Disarming your way out still works, though.
+
Stamina damage now has diminishing returns on people who are in hard staminacrit with the addition of a new multiplier. When you take staminaloss while in hard staminacrit, you'll be under the effects of the new multiplier, which reduces the amount of staminaloss you take from all sources of staminaloss. The diminishing returns multiplier will steadily return to 1 once you're out of staminacrit.
+
You can now scramble while resting. You can do this by dragging your spaceman onto an adjacent turf. This works even if you're in staminacrit, but the timer depends entirely on your staminaloss.
+
Fully augged cyborg people now heal stamina damage properly.
+
Job EXP is now tracked properly for all roles.
+
Nightmares and shadowpeople have had their light threshold for being considered in darkness reduced. Nightmares can no longer stand unharmed next to a light fixture during a nightshift 100% unharmed. The threshold is high enough so that APC lights on their own won't harm a nightmare, but being on the edge of a light source will.
+
The detective revolver's .38 bullets are now non-lethal again, but now require 3 shots to hard stamcrit
+
The current lethal variant of the .38 bullets can still be printed at sec protolathes.
+
You can now access ghost roles from the latejoin menu.
+
Eyeblur now scales depending on how much actual eyeblur you actually have.
+
Ebows now induce 50 drowsiness on whatever they hit.
+
Telepads have been buffed across the board. T1 parts on a launchpad still grants you a range of 15 tiles, but T4 parts now grant you a pretty large 60 tile range (up from their original 18 tile range). Briefcase launchpads were also buffed, they now have a range of 20 tiles, up from their previous laughable 8 tiles.
+
The grace period for the revolution win condition check has been reduced from 20 minutes to 10 minutes. You don't need to wait nearly as long for the round to end if no heads join in.
+
You can now select plural and neuter as your gender. They're labelled "non-binary" and "object" in the character customization menu, respectively.
+
A lot more light sources now use the same nonbinary colored lighting philosophies as flashlights and light fixtures!
+
Flashlights mounted to guns and helmets now retain the same color and power as their original light. Lavaland's caves will reflect a fluorescent blue as you shine your KA around, and sec's helmets are now capable of illuminating maint in that fancy fluorescent blue.
+
Cameras now shine a fluorescent blue when lit up by an AI
+
Glowing goo now actually glows green.
+
Candles had their power reduced from 1 to 0.8.
+
Lighters now shine a little further, and are now properly colored.
+
PDAs now shine an incandescent yellow to match their sprite.
+
Welding tools now shine an appropriate color
+
Hardhats now shine an incandescent yellow.
+
Plasmaman helmets now shine an incandescent yellow.
+
Microwaves no longer overpower literally every single light in the game, instead having a power of 0.9.
+
Borgs now have incandescent yellow lights to match their sprites
+
Bots now shine a fluorescent blue light
+
Airlock light overlays are now on the above lighting layer. This means airlock lights can actually be seen in the dark now.
+
The mob spawners list no longer leaves null entries behind when a spawner has a job description defined. The latejoin menu will no longer show ghost roles that are filled, and the spawners menu actually works again.
+
The voting system now actually tracks who voted for what. This means it's now possible to change your vote, and it's possible to see what you voted for.
+
Using help intent on someone that's in hard stamcrit will now make them heal 15 stamloss.
+
Auto fit viewport is now enabled by default for new players. One less question off the FAQ
+
The Khajiit favorite, Skooma, was added as a chemistry recipe that can be produced with cooperation between chemistry and either cargo or service. If you want to spoil the recipe for yourself, take a look at the PR for it!
+
When the shuttle leaves for centcom, a vote will be started to select the next map instead of the map being randomly chosen via biased voting methods
+
If a server operator wishes to re-enable the biased TG preference voting system, you can do so by toggling the TGSTYLE_MAPROTATION config flag on in the config.txt. Keep in mind that doing so will bring you great misfortune.
+
Cacti in lavaland now have 6u of vitfro instead of just 4u. This lessens the gap between cacti and first aid kits, the third rarest and second rarest readily available healing methods for ashwalkers, respectively.
+
the "genitals use skintone" option now appears in the character appearance menu when appropriate again.
+
Clicking your stamina bar will now show your exact stamina along with info regarding your stamina buffer
+
The bug where ghost role spawners leave null entries in glob.mob_spawners has actually been fixed
+
The Kitchen Gun (TM) is no longer invisible.
+
The majority of cult spells no longer have exclamation marks at the end of their invocations. This means they will no longer be bound to the rules of shouting. Which means sec officers will no longer be able to hear culties sacrificing the captain from the complete opposite side of the maintenance tunnel the sacrifice is happening in. However, things like EMP pulses and runeless teleportation still have the effect due to their inherent loud nature.
+
The stun blood spell now instantly causes hard stamcrit. However, to offset this, it now also only has one charge and has a higher cost.
+
The Gloves of the North Star now restore 2/3 of the stamina used up by punches when harm intent punching. With aggressive play and good stamina buffer management, this makes it entirely plausible to roughly double your stamina regeneration per mob life process tick.
+
Revs can no longer remember the name of the person who flashed them when deconverted. This brings it in-line with the other conversion antag deconversions.
+
The bug where you can sometimes get permanently stuck in stamcrit should HOPEFULLY be fixed. I'm unable to reproduce the bug myself, but let's hope.
+
The night vision trait now grants you darksight for an entire 1:1 screen, but the alpha of the lighting plane with the trait has been increased from 245 to 250 to balance it out
+
It's now actually possible to click the stamina hud button
+
The stamina hud button now displays your stamina buffer correctly
+
Bone spears now have a reach of 2 tiles.
+
You can no longer phase through solid objects via scrambling
+
The syndicate mask now works properly as intended.
+
Stamina is no longer affected by health at all.
+
You can now right-click yourself in help intent in combat mode to instantly get up from resting. This will cost stamina equal to your entire stamina buffer. Manage your stamina well, and you'll be able to shrug off a single stray golden bolt
+
The new player panel now displays your currently selected character's name
+
Flashes no longer knockdown. Instead, they deal eyeblur and have increased confusion
+
The server's tagline is now a config option. People can now stop confusing us with BR cit
+
Attack animations will now rotate your character slightly, similar to Goon.
+
Throwing items will now perform the attack animation and play a sound
+
flashlights will now make sounds when toggled on/off
+
Things in disposals will now emit sounds every single time they hit corners. This increases immersion.
+
Air alarms now actually emit the proper light color when their status is okay.
+
Backpacks and other storage items will now jiggle and squish when you interact with them, similar to the animations seen on Goon.
+
Mops no longer have a delay on their cleaning, making them an actually viable alternative to all of the janitor's other cleaning tools
+
To balance this, mops now take stamina to clean tiles. Standard mops take 5 stamina to use, while advanced mops take 2 stamina.
+
Oh and also mops make fancy new sounds and play animations when used now
+
Pump-action shotguns now take 2 stamina per pump instead of 5 stamina per pump. This also applies to bolt-action rifles, as bolt racking counts as pumping.
+
Pickpocketing items will now place them in your hands if possible
+
Combat mode is now displayed in examine text
+
Combat mode now makes a visible message when enabled if you haven't touched your combat mode button in the last ten seconds. It's done this way to avoid chat spam from those who know how to pull off stam regen squeezing.
+
All knockdown sources will now force people to be dismounted from ridden vehicles.
+
When an item is thrown, it will now be rotated and displaced.
+
Shards of glass will now be rotated when spawned.
+
Bullet casings will now be rotated when they're ejected from a gun.
+
Bottles now have random rotations and pixel offsets when smashed via throwing.
+
Picking up an item will now reset its rotation.
+
Glasses thrown onto tables by bartenders will now have their rotation reset.
+
Slime speed potions can now only increase the speed of vehicles to be on par with sprinting speed. They can no longer make a scooter roll around ten times faster than a speeding blue hedgehog.
+
Changelings will no longer recieve team objectives
+
Changelings no longer start off with hivemind communication as an innate ability. Hivemind communication now requires 1 dna point, on par with syndicate encryption keys, which are 2 TC.
+
Hivemind link now relies on hivemind communication just like the hivemind download/upload abilities.
+
It's now only possible to zoom a gun if it's in one of your hands
+
Mobs without clients no longer cause runtimes when their eyeblur updates
+
Blood tests have been added. If a changeling has a sufficient number of loud abilities, you will be able to test their blood by heating up a sample of it. However, if the changeling has a large amount of loud abilities, attempts to test their blood will have explosive results.
+
Changelings now make a very obvious noise when readapting. This is to prevent the cheese strat of simply readapting when you get caught to avoid detection.
+
The blood splatter effect that happens when you get attacked will now always make you lose blood depending on the damage you've taken. The effect now also scales with item damage, meaning tiny little papercuts will no longer be able to cause a massive blood splatter.
+
The blood reagent will now cover items and spacemen in blood when applied to objects and mobs.
+
Helmets, masks, and neck items are all now valid targets to get splattered when you get covered in blood. Groovy.
+
The temperature notification will now take into consideration both the ambient temperature and your body temperature, increasing the responsiveness of the temperature notification and making it much more realistic.
+
Shuttle transit borders are now 10 tiles wide instead of 8 tiles, hopefully repairing the immersions that get shattered by the ability to see normal space where the transit areas end.
+
Instead of transit turfs simply teleporting things to space, transit is now handled in a somewhat realistic manner. Transit turfs now act like normal space turfs, though exiting the transit area or being present in the transit area after the shuttle moves out of transit will teleport you to space and throw you in the direction the shuttle was moving in.
+
Reservation areas are now able to designate a border turf.
+
The sprint hotkey will no longer cause you to get permanently stuck sprinting if the server lags. Just tap shift again if you get stuck
+
You can now hear sounds in the real world while inside of a VR sleeper.
+
You can now make nameless characters. Nameless characters will spawn in with their name set as their job title followed by a unique five digit number. The "Name" option in the character setup menu will be replaced with a "Default designation" option for nameless characters, and the default designation will be used in place of a job title for assistants and other jobs that don't require dress codes.
+
The out-of-game round end notification is now a little more verbose. It'll now display the round type, end result of the round, and the survival rate.
+
Xenos can no longer strip items off of people to be capable of using any item in the game.
+
also, items from pockets get placed into your hands properly now
+
A mob's last words are now properly tracked and recorded on death. The first death of the round will now actually display the victim's last words on the round end screen.
+
Divine shenanigans can no longer result in someone becoming immune to staminaloss
+
Fixed body_markings in bodyparts being assigned as a list when in reality, it's a string and literally everything expects it to be a string and uses it as a string. This should mean that markings no longer have completely fucked up caches for character preview and other things.
+
Since apparently the game is literally unplayable if items are not in the exact center of a turf, the maximum pixel variance of thrown objects has been reduced by four pixels to make things a smidge more clearer for those that dont know what a turf is.
+
Bartender glasses should HOPEFULLY no longer be tilted when landing on a table. Why the fuck is after_throw called via a timer.
+
Changeling screeches now have their own unique sounds, and are much easier to recognize.
+
Most synthetic emotes are now available to humans. *ping
+
You can now merp
+
The TEG will now only produce a meaningful amount of power if the hot pipe contains gas that's actively combusting
+
Added the "add PB bypass" and "revoke PB bypass" verbs, which allow admins to let a specific ckey to bypass the panic bunker for the rest of the round
+
Jogging is no longer treated exactly the same as sprinting for water slips. When you're jogging, you will only slip on water if you have more than 20% staminaloss.
+
The atmospherics turf subsystem now has double the wait time, which should free up server processing power for other tasks.
+
The IRC now actually displays the actual survival rate
+
Bloodcult conversions are now consensual. Convertees are given a ten second timer to accept or wait out. This should drastically improve the quality of those that get converted into bloodcult.
+
All sacrifices now count as a third of a cultist for the end-game narsie summon.
+
Nameless captains will no longer proc a "Captain Captain on deck!" message. Instead, it'll be a much more boring but much more sensical "Captain on deck!" message.
+
Transit turfs on the centcom z-level now function properly again at keeping mobs within the areas defined by their boundaries.
+
The title screen is also positioned correctly again.
+
Ghost role eligibility for both event and spawner ghost roles is now affected by DNR status. If you suicide, ghost, or cryo out, you will be unable to qualify for any ghost roles
+
Cryo now applies DNR status no matter how long the round has been going on
+
Suicide is now properly admin logged as it is supposed to be. Ghosting while alive is now also logged.
+
Sparks and igniters will now actually heat areas rather than cooling them, as was intended.
+
To alleviate some potential complaints, RPDs now have a cooldown before they can create sparks, and both RPDs and emitters produce less sparks.
+
Conversion runes will now mute the victim temporarily while they're deciding whether to convert or be sacrificed.
+
Conversion runes no longer require a third cultist to sacrifice if the victim refuses conversion
+
Staminaloss targeted at the head now properly redirects to the chest.
+
Sprinting no longer takes stam when you're being pulled or when you're in zero gravity. Other sources of involuntary movement are not affected.
+
In an attempt to improve performance during highpop, mouse movements will now only call onmousemove() while a user is in combat mode
+
Ballistic projectiles are now the only projectiles capable of emitting dinks.
+
Panic bunker toggling and bypassing is now logged in admin IRC
+
OOC and LOOC now use separate toggles. You can now use LOOC while OOC is globally toggled off, and admins now have the option to toggle LOOC off separately from OOC
+
also revamped and reorganized relevant looc adminverb code
+
The endgame narsie summon rune no longer requires 24 total sacrifices, and will now properly account for cultists that surround it
+
The succumb verb is now available in the IC tab
+
Lighting now uses a linear algorithm to calculate falloff instead of an inverse-square algorithm.
+
get_hearers_in_view() now actually caches the results of view() instead of calling view() twice
+
Goonchat's JS no longer contains checks related to a completely unused message filtering function, which should improve clientside performance quite a bit
+
The storage hud now properly takes into account the viewer's view size, meaning storage items with a large amount of storage slots will properly stretch across the bottom of the screen when running in widescreen.
+
Action buttons are now able to fill the entire screen in widescreen and other weird view sizes.
+
Omegastation's job changes will no longer be included at compile time.
+
The client update portion of /mob/Login() now double-checks to make sure client.player_details exists and is of the proper type. This should hopefully fix the "cannot read null.player_details" runtimes that can spontaneously cause clients to get kicked out and forced back to the lobby.
+
You can now quickly use unequipped items on objects by simply click-dragging the item onto the object with an empty active hand. Doing so will place the item in your hand, and then use that item on the object.
+
In an attempt to improve the performance of /mob/Stat(), various time-related procs now use defines instead of being procs that call procs that call other procs that call even more procs.
+
If a living mob has vore initialized but doesnt have voreprefs initialized, then client login will force voreprefs to load.
+
Hopefully fixed paper crash 2: electric boogaloo
+
Added unomos, which is basically listmos except gas mixtures only use one single list for handling their gasses. This is a significant performance improvement that also offers a mild memory improvement under normal circumstances.
+
Locomotion circuits are now restricted to jogging speed
+
MMI circuits and pAI circuits both now have 60 complexity, up from their original 29.
+
Biogenerators now have a sane limit for production
+
Fixed a fairly huge server crash exploit
+
Shield blobs no longer become completely invulnerable to all forms of damage after reaching a """weakened""" state
+
Taken care of what appeared to have been an oversight where shield blobs don't recover their armor after becoming weakened.
+
Nerfed concatenators by limiting the amount of characters they're able to output
+
The timer for stripping an item off of a spaceman is no longer interrupted by your active held item changing. This means you no longer have to worry about filling both of your hands when you're stripping items off of someone.
+
Ported the zulie cloak and blackredgold coat donor items from RP.
+
Normal mops now only use 2 stamina to mop a tile, nerfed from their previous value of 5 stamina per tile mopped.
+
Advanced mops now only use 1 stamina to mop turfs, from their former value of 2 stam.
+
The femur breaker now uses `*scream` instead of forced speech. This means that the femur breaker will no longer spam deadchat with "AAAAAAAAAHHHHHHHHHH!!"
+
The femur breaker will now guarantee that the victim falls into crit, which will make it harder to perform torture scenes with it since the victim can just succumb.
+
Fixed another runtime in warp whistles.
+
Spamming forged packets no longer crashes the server.
+
Things that access job_preferences now explicitly access keys, which means it no longer attempts to access invalid indices and runtimes as a result.
+
The taser's electrode has been reworked. Instead of being a strong knockdown that deals a heavy amount of stamloss, it now causes a weak knockdown, applies a debilitating status effect for 5 seconds, and deals 35 stamloss on hit up to a maximum 50 total stamloss.
+
Roundstart turrets now have a nonlethal projectile that gets used when they're set to stun and the target is resting
+
Hybrid tasers now have disablers set as their default mode.
+
There is now a 1% chance for the station's announcer to be the medibot voice instead of the classic TG announcer.
+
The map config system has been expanded to allow mappers to specify the map type, announcer voice, ingame year, and how often a given map can be voted at roundend.
+
The map vote system now takes into account map playercount limits properly.
+
Examining a spaceman, and other things that use get_examine_string(), will now actually properly show when an item is blood-stained.
+
Plasmaman tongues no longer have a maxHealth of "alien", and no longer cause the organ's on_life to always runtime.
+
Shooting a simplemob no longer causes runtimes prior to the blood effect being created.
+
Removing a filter from an object that lacks filters no longer causes runtimes.
-
WJohn updated:
+
deathride58 (Original PR by actioninja) updated:
-
Added zombies to boxstation's abandoned ship.
+
Disarm pushing (combat mode right click in disarm intent) will now actually push mobs away. Knockdowns from disarm pushing are no longer rng based on the target's staminaloss. Knockdowns from disarm pushing now only happen when you push someone into another mob, a table, or a wall. Pushes will now also temporarily stop targets from using firearms, and will disarm the firearm if performed a second time. Pushes still deal staminaloss to standing targets, and won't deal a single ounce of staminaloss to resting targets.
+
You can no longer displace mobs that are in harm intent by simply walking into them. Mobs that aren't in help intent have to be disarm pushed to actually be moved.
-
YPOQ updated:
+
dtfe3 updated:
-
AIs can take photos and print them at photocopiers again.
-
Cult floors will not deconstruct to space
-
Cult floors do not spawn rods when deconstructed
-
Footprints should no longer spread out of control
+
Increased music maxlines from 300 to 600
+
Made it so any oxygen tank can be used instead of only red ones.
+
Watcher wing Trophy's effect lasts 1 second instead of 0.5
+
Pink Panties
+
Twintails
+
Schoolgirl outfits for the loadout menu!
+
Now the fox ears are located in front of hair meaning they now behave much like cat ears, that being they are on-top of the hair layer.
-
zaracka updated:
+
izzyinbox updated:
-
blunt trauma causes brain damage while unconscious too
-
sharp weapons no longer count as blunt trauma in all cases
+
adds VoG orgasm command using words "orgasm", "cum", "squirt", "climax"
+
adds VoG dab command using words "dab" and "mood"
+
Generic dog body marking sprite
+
colormatrix dog sprites
+
lowered the player age for command jobs to 1/3 of their previous setting
+
*bark emote
-
-
10 August 2018
-
AnturK updated:
+
jtgsz updated:
-
Portable flashers won't burnout from failed flashes.
+
ported gang mode
-
Denton, Tlaltecuhtli updated:
+
kappa-sama updated:
-
Added cargo bounties that require cooperation with Atmospherics, Engineering and Mining.
-
-
Naksu updated:
-
-
Transformation diseases now properly check for job bans where applicable
-
Fixed a bunch of runtimes that result from transforming into a nonhuman from a human, or a noncarbon from a carbon.
-
-
SpaceManiac updated:
-
-
The map loader has been cleaned up and made more flexible.
-
-
nicbn updated:
-
-
BoxStation science changes: Circuitry lab is closer to RnD now; cannisters, portable vents, portable scrubbers, filters and mixers have been moved to Toxin Mixing Lab. There is now a firing range at the testing lab!
-
-
-
08 August 2018
-
Denton updated:
-
-
Added five new cargo packs: cargo supplies, circuitry starter pack, premium carpet, surgical supplies and wrapping paper.
-
Added one bag of L type blood to the blood pack crate. Added a chance for contraband crates to contain DonkSoft refill packs.
-
-
Iamgoofball updated:
-
-
The Stealth Implant was mistakenly made nuclear operatives only due to a misunderstanding of the code. This has been fixed.
-
-
Mark9013100 updated:
-
-
Pocket fire extinguishers can now be made in the autolathe.
-
-
SpaceManiac updated:
-
-
The power flow control console once again allows actually modifying APCs.
-
Gas meters will now prefer to target visible pipes if they share a turf with hidden pipes.
-
-
daklaj updated:
-
-
fixed beepsky and ED-209 cuffing their target successfully even when getting disabled (EMP'd) in the process
+
Removed racism
+
Teleporter calibration actually matters to all roundstart players
+
Slows down teleportation with the console/hub/teleporter setup if you care for your species.
+
Dedicated non-humans can now get hulk without having to become human.
+
seed
+
added obj/item/key to wallet whitelist
+
blood cult ritual daggers fit in jack/combat boots
+
voidcells can now unlock alien tech
+
rebalanced tech trees (not really)
+
hugbox (/s)
+
ashwalker spawn text now tells them "i" "c" not to leave lavaland
+
you can no longer have infinite ebows
+
kevinz forgot to nerf miasma research and cargo value after making it produce like 100x as much lmao
kevinz000 updated:
-
Catpeople are now a subspecies of human. Switch your character's species to "Felinid" to be one.
-
Oh yeah and they show up as felinids on health analyzers.
+
Hierophant now goes sicko mode, but hey, at least you can't be multi-hit by melee waves!
+
Racking shotguns is now more threatening.
+
Medibots no longer kill slimes when trying to heal their toxins.
+
The Syndicate started selling claymores to their agents.
+
Nerfed VTEC modules.
+
Neurotoxin no longer stuns non-carbons.
+
peacekeeper cyborgs now get a megaphone
+
Fixes storage bugs regarding reaching into things you shouldn't be able to reach into.
+
BYOND 513 preliminary support added.
+
Trashbags now only allow accessing the first 3 items. 5 for bluespace ones. experimental: Storage now allows for limiting of random access
-
-
07 August 2018
-
WJohnston updated:
+
kiwedespars updated:
-
Redesigned the pirate event ship to be much prettier and better fitting what it was meant to do.
+
regenerative materia to hallucination sting
+
mindbreaker toxin as an actual chemical to hallucination sting
-
-
06 August 2018
-
Basilman updated:
+
lolman360 updated:
-
Increased agent box cooldown to 10 seconds
+
NT has authorized shipments or Cotton to Megaseed Servitors. It's time to start picking, liggers.
+
missing durathread sprites
+
Added durathread jumpskirt
+
Duraskirt sprites and rolled down jumpsuit sprites.
+
Fixes an undocumented change to the naming of Plasmamen.
+
chainsaw kind of weapons and the mecha drill and the CLAMP can now be used with 100% accuracy for surgery
+
surgery tools now work on defines
+
advanced surgerytools can now switch types instead of just being faster
+
fixes bug with new surgerytools examine
-
Denton updated:
+
nicc updated:
-
Omegastation's Atmospherics lockdown button now has the proper access reqs.
-
Pubbystation's disposals conveyor belts now face the correct direction.
-
Pubby's service techfab is no longer stuck inside a wall.
-
Pubby's disposal loop is no longer broken.
-
The Lavaland seed vault chem dispenser now has upgraded stock parts.
-
Metastation: Extended protective grilles to partially cover the Supermatter cooling loop.
+
Exo-suit
+
SEVA suit
+
Flags for Goliath resistance and weakness
+
suit voucher
+
temp suit sprites
+
*dab
+
teg less gay maybe
-
Epoc updated:
+
ninjanomnom and WhoneedSpacee updated:
-
You can now show off your Attorney's Badge
+
Some rpg affixes now have special effects
+
New RPGLoot modifiers: Vampirism which heals you when you attack, Pyromantic which sets things you hit on fire. Shrapnel which causes projectiles fired from a gun to fire projectiles in a radius when they hit something. Finally, Summoning which summons mobs that sometimes aid you in combat.
-
Garen updated:
+
original by @randolfthemeh and @twaticus, port by sishen1542 updated:
-
Fixed AddComponent(target) not working when an instance is passed rather than a path
+
jumpskirts
+
more jumpskirts
+
jumpskirt/suit prefs
-
JJRcop updated:
+
original by Bumtickley00, port by sishen1542 updated:
-
Fixed some strange string handling in SDQL
+
Suit storage units will now also remove radiation from mobs.
-
Jared-Fogle updated:
+
original by GuyonBroadway, SkowronX, and Arizon5. port by sishen1542 and kerse updated:
-
Moths can now eat clothes.
+
Clockwork cultists may now summon forth Neovgre, the ratvrarian super weapon. This powerful mech can be summoned when applications scripture has been unlocked, boasts superior offensive and defensive capabilities, however once a pilot enters he cannot leave and is doomed to die with the mech.
+
Sexy Sprite work courtesy or SkowronX from /tg/
+
brass edits by Arizon5
+
steamy laser by kerse
-
JohnGinnane updated:
+
original by Skoglol, port by sishen1542 updated:
-
Users can now see their prayers (similar to PDA sending messages)
+
Added lots of new virus cures, made cure difficulty scale more consistently. Cures are now picked from a list of possible cures per resistance level, multiple diseases at the same level no longer always share a cure. Looking at you table salt.
+
Dynamic gamemode now more auto-deadmin friendly.
-
Mickyan updated:
+
original by TheChosenEvilOne, port by sishen1542 updated:
-
Drinking alcohol now improves your mood
+
Ported dynamic mode from /vg/, originally made by @DeityLink, @Kurfursten and @ShiftyRail
-
Shdorsh updated:
+
original by Tlaltecuhtli, port by sishen1542 updated:
-
The previously-added find-replace circuit now actually exists.
+
rcd disk that gives rcd computer frame and machine frame designs
+
upgraded rcd in CE lockers
+
moved deconstruction to the upgrade disk, ashwalker rcd comes upgraded
-
Tlaltecuhtli (and then Cobby) updated:
+
original by actioninja, port by sishen1542 updated:
-
Science Bounties are now available!
+
Medical and Security consoles now check access on worn or inhand ID instead of requiring an inserted ID
+
mining vendor now reads from ID in hand or on person instead of requiring an inserted ID
+
ORM is functional again (for real this time)
+
ORM claim points button transfers points to worn/inhand ID instead of to an inserted ID, no longer accepts insertions
+
Same for gulag consoles
-
WJohnston updated:
+
original by redmoogle, port by sishen1542 updated:
-
Rebalanced the simple animal syndies on the metastation ship to be a bit less destructive of their surroundings, and downgraded the smg guy to a pistol and upgraded the other guys to knives.
+
Added support for 3 new gasses; Tritium, Pluoxium, and BZ
-
Y0SH1 M4S73R updated:
+
original by: WJohnston, Antur, Arcane, plapatin, sprites by cogwerks and edited by mrdoombringer. port by sishen1542 updated:
-
windoors now have NTNet support. The "open" command toggles the windoor open and closed. The "touch" command, not usable by door remotes, functions identically to walking into the windoor, opening it and then closing it after some time.
+
THE GOOSE IS LOOSE
-
cyclowns updated:
+
r4d6 updated:
-
Fusion has been reworked to be a whole lot deadlier!
-
You can now use analyzers on gas mixtures holders (canisters, pipes, turfs, etc) that have undergone fusion to see the power of the fusion reaction that occurred.
-
Several gases' fusion power and fusion's gas creation has been reworked to make its tier system more linear and less cheese-able.
+
Added decoratives angel wings for Mammalians only
+
Added blindfolds to the Loadout list
+
Added Decorative Wings for Humans, Felinids, Slimepersons and Lizardpeoples.
+
Change the SEVA suit & Exo-suit's descriptions
+
Batteries are now Rad-Proof like the other stock parts
-
-
03 August 2018
-
ArcaneMusic updated:
+
tigercat2000@Paradise updated:
-
Added a new, shoutier RoundEnd Sound.
+
fixed invalid characters breaking chat output for that message
-
Basilman updated:
+
tinfoil hat wearer updated:
-
fixed agent box invisibility
+
Added a new alien technology disk to scientist and roboticist uplinks that allows them to research the heavily-guarded secrets of the Grays.
+
Alientech is now the only Hidden alien research. To compensate for this, alien_bio and alien_engi have had their research costs doubled and now require advanced surgery tools and experimental tools respectively to research. Their export price is also halved.
+
roboticists now have brainwashing disks AND alien technology added to their role-restricted uplink section. alien technology gives them brainwashing at a much later date, so brainwashing is the much cheaper option for instant power. makes logical sense because doctors get it as well because they do surgery, and roboticists can now either choose to brainwash people for less price but less power or emag borgs for higher prices, limited uses, but higher power.
-
Denton updated:
+
ursamedium updated:
-
Syndicate lavaland base: Added a grenade parts vendor and smoke machine board. The testing chamber now has a heatproof door and vents/scrubbers to replace air after testing gas grenades. Chemical/soda/beer vendors are emagged by default; the vault contains a set of valuable Syndicate documents.
-
Added a scrubber pipenet to the Lavaland mining base.
-
-
Garen updated:
-
-
mobs now call COMSIG_PARENT_ATTACKBY
-
-
JJRcop updated:
-
-
Deadchat can use emoji now, be sure to freak out scrying orb users.
-
-
Kmc2000 updated:
-
-
You can now attach 4 energy swords to a securiton assembly instead of a baton to create a 4 esword wielding nightmare-bot
-
-
Mickyan updated:
-
-
added sprites for camera when equipped or in hand
-
cameras are now equipped in the neck slot
-
-
SpaceManiac updated:
-
-
Traps now have their examine text back.
-
-
Supermichael777 updated:
-
-
Cigarettes now always transfer a valid amount of reagents.
-
Reagent order of operations is no longer completely insane
-
-
WJohnston updated:
-
-
Added a gun recharger to delta's white ship and toned it down from a "luxury" frigate to just a NT frigate, it's just not made for luxury!
-
-
XDTM updated:
-
-
Beheading now works while in hard crit, so it can be used against zombies.
-
You can now have fakedeath without also being unconscious. Existing sources of fakedeath still cause unconsciousness.
-
Zombies and skeletons now appear as dead. Don't trust zombies on the ground!
-
You can now make Ghoul Powder with Zombie Powder and epinephrine, which causes fakedeath without uncounsciousness.
-
-
granpawalton updated:
-
-
pubby round start atmos issues resolved
-
pubby departures lounge vent is no longer belonging to brig maint
-
pipe dispenser on pirate ship
-
-
ninjanomnom updated:
-
-
The first pod spawned had some issues with shuttle id and wouldn't move properly. This has been fixed.
-
-
-
01 August 2018
-
Basilman updated:
-
-
Added the stealth manual to the uplink, costs 8 TC. Find it under the implant section
-
-
Cobby updated:
-
-
Drone's Law 3 has been edited to explicitly state that it's for the site of activation (aka people do not get banned for going to upgrade station as derelict drones since it's explicitly clear now). See https://tgstation13.org/phpBB/viewtopic.php?f=33&t=18844&p=429944#p429944 for why this was PR'd
-
PENLITEs are now actually spawnable in techwebs. Reminder to make sure everything is committed before PRing haha!
-
-
Denton updated:
-
-
New bounties have been added for the Firefighter APLU mech, cat tails and the Cat/Liz o' Nine Tails weapons.
-
ExoNuclear mech reactors now noticably irradiate their environment.
-
Adjusted suit storage unit descriptions to mention that they can decontaminate irradiated equipment.
-
-
Hate9 updated:
-
-
Added tiny-sized circuits (called Devices)
-
added new icons for the Devices
-
-
Iamgoofball updated:
-
-
Buzzkill Grenade Box Cost: 5 -> 15
-
-
Shdorsh updated:
-
-
Text replacer circuit
-
-
SpaceManiac updated:
-
-
The bridge of the gulag shuttle now has a stacking machine console for ejecting sheets.
-
-
Time-Green updated:
-
-
You can now mount energy guns into emitters
-
portal guns no longer runtime when fired by turrets
-
-
barbedwireqtip updated:
-
-
Adds the security guard outfit from Half-Life to the secdrobe
-
-
granpawalton updated:
-
-
Removed old piping sections and replaced with Canister storage area in atmos incinerator
-
scrubber and distro pipes moved in atmos incinerator to make room for added piping
-
added filter at connector on scrubbing pipe in atmos incinerator
-
replaced vent in incinerator with scrubber in **Both** incinerators
-
mixer placed on pure loop at plasma
-
delta and pubby atmos incinerator air alarm is no longer locked at round start
-
pubby atmos incinerator now starts without atmos in it
-
-
kevinz000 updated:
-
-
Cameras now shoot from 1x1 to 7x7, fully customizable. Alt click on them to change the size of your photos. experimental: All photos, assuming the server host turns this feature on, will be logged to disk in round logs, with their data and path stored in a json. This allows for things like Statbus, and persistence features among other things to easily grab the data and load the photo.
-
Mappers are now able to add in photo albums and wall frames with persistence! This, obviously, requires photo logging to be turned on. If this is enabled and used, these albums and frames will save the ID of the photo(s) inside them and load it the next time they're loaded in! Like secret satchels, but for photos!
-
-
-
30 July 2018
-
Anonmare updated:
-
-
Upload boards and AI modules, in addition to Weapon Recharger boards, are now more expensive to manufacture
-
-
Basilman updated:
-
-
fixed BM Speedwagon offsets
-
-
Cobby (based off Wesoda25's idea) updated:
-
-
Adds the PENLITE holobarrier. A holographic barrier which halts individuals with bad diseases!
-
-
Denton updated:
-
-
Techweb nodes that are available to exofabs by roundstart have been moved to basic research technology.
-
Ripley APLU circuit boards are now printable by roundstart.
-
Odysseus, Gygax, Durand, H.O.N.K. and Phazon mech parts have to be researched before becoming printable (same as their circuit boards).
-
Arrivals shuttles no longer throw objects/players when docking.
-
Regular fedoras no longer spawn containing flasks.
-
Increased the range of handheld T-ray scanners.
-
Cargo bounties that request irreplaceable items have been removed.
-
-
Garen updated:
-
-
Throwers no longer deal damage
-
Flashlight circuits are now the same strength as a normal flashlight
-
Grabber circuits are now combat circuits
-
Removed smoke circuits
-
Removed all screens larger than small
-
Ntnet circuits can no longer specify the passkey used, it instead always uses the access
-
-
Hate9 updated:
-
-
Added pulse multiplexer circuits, to complete the list of data transfers.
-
-
Jared-Fogle updated:
-
-
NanoTrasen now officially recognizes Moth Week as a holiday.
-
Temporarily removes canvases until someone figures out how to fix them.
-
-
Mickyan updated:
-
-
Social anxiety trigger range decreased. Stay out of my personal space!
-
Social anxiety no longer triggers while nobody is around but you
-
-
WJohnston updated:
-
-
Redesigned the metastation white ship as a salvage vessel.
-
-
YoYoBatty updated:
-
-
SMES power terminals not actually deleting the terminal reference when by cutting the terminal itself rather than the SMES.
-
SMES now reconnect to the grid properly after construction.
-
SMES now uses wirecutter act to handle terminal deconstruction.
-
-
ninjanomnom updated:
-
-
Objects picked up from tables blocking throws will no longer be forever unthrowable
-
-
-
28 July 2018
-
CitrusGender updated:
-
-
Removed slippery component from water turf
-
-
Denton updated:
-
-
The Odysseus mech's movespeed has been increased.
-
Metastation: Spruced up the RnD circuitry lab; no gameplay changes.
-
Due to exemplary performance, NanoTrasen has awarded Shaft Miners with their very own bathroom, constructed at the mining station dormitories. Construction costs will be deducted from their salaries.
-
-
Mickyan updated:
-
-
insanity static is subtler
-
neutral mood icon is now light blue
-
-
SpaceManiac updated:
-
-
Cyborgs and AIs can now interact with items inside them again.
-
-
Tlaltecuhtli updated:
-
-
Mouse traps are craftable from cardboard and a metal rod.
-
-
WJohnston updated:
-
-
Syndicate and pirate simple animals should have stats that more closely resemble fighting a human in those suits, with appropriate health, sounds, and space movement limitations.
-
Pirates in space suits have more modern space suits.