The round has ended.")
+ if(LAZYLEN(GLOB.round_end_notifiees))
+ send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.")
+
+ for(var/client/C in GLOB.clients)
+ if(!C.credits)
+ C.RollCredits()
+ C.playtitlemusic(40)
+
+ display_report()
+
+ gather_roundend_feedback()
+
+ CHECK_TICK
+
+ //Set news report and mode result
+ mode.set_round_result()
+
+ send2irc("Server", "Round just ended.")
+
+ if(length(CONFIG_GET(keyed_string_list/cross_server)))
+ send_news_report()
+
+ CHECK_TICK
+
+ //These need update to actually reflect the real antagonists
+ //Print a list of antagonists to the server log
+ var/list/total_antagonists = list()
+ //Look into all mobs in world, dead or alive
+ for(var/datum/mind/Mind in minds)
+ var/temprole = Mind.special_role
+ if(temprole) //if they are an antagonist of some sort.
+ if(temprole in total_antagonists) //If the role exists already, add the name to it
+ total_antagonists[temprole] += ", [Mind.name]([Mind.key])"
+ else
+ total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob
+ total_antagonists[temprole] += ": [Mind.name]([Mind.key])"
+
+ CHECK_TICK
+
+ //Now print them all into the log!
+ log_game("Antagonists at round end were...")
+ for(var/i in total_antagonists)
+ log_game("[i]s[total_antagonists[i]].")
+
+ CHECK_TICK
+
+ //Collects persistence features
+ if(mode.allow_persistence_save)
+ SSpersistence.CollectData()
+
+ //stop collecting feedback during grifftime
+ SSblackbox.Seal()
+
+ sleep(50)
+ ready_for_reboot = TRUE
+ standard_reboot()
+
+/datum/controller/subsystem/ticker/proc/standard_reboot()
+ if(ready_for_reboot)
+ if(mode.station_was_nuked)
+ Reboot("Station destroyed by Nuclear Device.", "nuke")
+ else
+ Reboot("Round ended.", "proper completion")
+ else
+ CRASH("Attempted standard reboot without ticker roundend completion")
+
+//Common part of the report
+/datum/controller/subsystem/ticker/proc/build_roundend_report()
+ var/list/parts = list()
+
+ //Gamemode specific things. Should be empty most of the time.
+ parts += mode.special_report()
+
+ CHECK_TICK
+
+ //AI laws
+ parts += law_report()
+
+ CHECK_TICK
+
+ //Antagonists
+ parts += antag_report()
+
+ CHECK_TICK
+ //Medals
+ parts += medal_report()
+ //Station Goals
+ parts += goal_report()
+
+ listclearnulls(parts)
+
+ return parts.Join()
+
+
+/datum/controller/subsystem/ticker/proc/survivor_report()
+ var/list/parts = list()
+ var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
+ var/num_survivors = 0
+ var/num_escapees = 0
+ var/num_shuttle_escapees = 0
+
+ //Player status report
+ for(var/i in GLOB.mob_list)
+ var/mob/Player = i
+ if(Player.mind && !isnewplayer(Player))
+ if(Player.stat != DEAD && !isbrain(Player))
+ num_survivors++
+ if(station_evacuated) //If the shuttle has already left the station
+ var/list/area/shuttle_areas
+ if(SSshuttle && SSshuttle.emergency)
+ shuttle_areas = SSshuttle.emergency.shuttle_areas
+ if(Player.onCentCom() || Player.onSyndieBase())
+ num_escapees++
+ if(shuttle_areas[get_area(Player)])
+ num_shuttle_escapees++
+
+ //Round statistics report
+ var/datum/station_state/end_state = new /datum/station_state()
+ end_state.count()
+ var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
+
+ parts += "[GLOB.TAB]Shift Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]"
+ parts += "[GLOB.TAB]Station Integrity: [mode.station_was_nuked ? "Destroyed" : "[station_integrity]%"]"
+ var/total_players = GLOB.joined_player_list.len
+ if(total_players)
+ parts+= "[GLOB.TAB]Total Population: [total_players]"
+ if(station_evacuated)
+ parts += " [GLOB.TAB]Evacuation Rate: [num_escapees] ([PERCENT(num_escapees/total_players)]%)"
+ parts += "[GLOB.TAB](on emergency shuttle): [num_shuttle_escapees] ([PERCENT(num_shuttle_escapees/total_players)]%)"
+ parts += "[GLOB.TAB]Survival Rate: [num_survivors] ([PERCENT(num_survivors/total_players)]%)"
+ return parts.Join(" ")
+
+/datum/controller/subsystem/ticker/proc/show_roundend_report(client/C,common_report)
+ var/list/report_parts = list()
+
+ report_parts += personal_report(C)
+ report_parts += common_report
+
+ var/datum/browser/roundend_report = new(C, "roundend")
+ roundend_report.width = 800
+ roundend_report.height = 600
+ roundend_report.set_content(report_parts.Join())
+ roundend_report.stylesheets = list()
+ roundend_report.add_stylesheet("roundend",'html/browser/roundend.css')
+
+ roundend_report.open(0)
+
+/datum/controller/subsystem/ticker/proc/personal_report(client/C)
+ var/list/parts = list()
+ var/mob/M = C.mob
+ if(M.mind && !isnewplayer(M))
+ if(M.stat != DEAD && !isbrain(M))
+ if(EMERGENCY_ESCAPED_OR_ENDGAMED)
+ if(!M.onCentCom() || !M.onSyndieBase())
+ parts += "
"
+ parts += "You managed to survive, but were marooned on [station_name()]..."
+ else
+ parts += "
"
+ parts += "You managed to survive the events on [station_name()] as [M.real_name]."
+ else
+ parts += "
"
+ parts += "You managed to survive the events on [station_name()] as [M.real_name]."
+
+ else
+ parts += "
"
+ parts += "You did not survive the events on [station_name()]..."
+ else
+ parts += "
"
+ parts += " "
+ if(GLOB.survivor_report)
+ parts += GLOB.survivor_report
+ else
+ parts += survivor_report()
+
+ parts += "
"
+
+ return parts.Join()
+
+/datum/controller/subsystem/ticker/proc/display_report()
+ GLOB.common_report = build_roundend_report()
+ for(var/client/C in GLOB.clients)
+ show_roundend_report(C,GLOB.common_report)
+ give_show_report_button(C)
+ CHECK_TICK
+
+/datum/controller/subsystem/ticker/proc/law_report()
+ var/list/parts = list()
+ //Silicon laws report
+ for (var/i in GLOB.ai_list)
+ var/mob/living/silicon/ai/aiPlayer = i
+ if(aiPlayer.mind)
+ parts += "[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws [aiPlayer.stat != DEAD ? "at the end of the round" : "when it was deactivated"] were:"
+ parts += aiPlayer.laws.get_law_list(include_zeroth=TRUE)
+
+ parts += "Total law changes: [aiPlayer.law_change_counter]"
+
+ if (aiPlayer.connected_robots.len)
+ var/robolist = "[aiPlayer.real_name]'s minions were: "
+ for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
+ if(robo.mind)
+ robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.mind.key]), ":" (Played by: [robo.mind.key]), "]"
+ parts += "[robolist]"
+
+ for (var/mob/living/silicon/robot/robo in GLOB.silicon_mobs)
+ if (!robo.connected_ai && robo.mind)
+ if (robo.stat != DEAD)
+ parts += "[robo.name] (Played by: [robo.mind.key]) survived as an AI-less borg! Its laws were:"
+ else
+ parts += "[robo.name] (Played by: [robo.mind.key]) was unable to survive the rigors of being a cyborg without an AI. Its laws were:"
+
+ if(robo) //How the hell do we lose robo between here and the world messages directly above this?
+ parts += robo.laws.get_law_list(include_zeroth=TRUE)
+ if(parts.len)
+ return "
[parts.Join(" ")]
"
+ else
+ return ""
+
+/datum/controller/subsystem/ticker/proc/goal_report()
+ var/list/parts = list()
+ if(mode.station_goals.len)
+ for(var/V in mode.station_goals)
+ var/datum/station_goal/G = V
+ parts += G.get_result()
+ return "
[parts.Join()]
"
+
+/datum/controller/subsystem/ticker/proc/medal_report()
+ if(GLOB.commendations.len)
+ var/list/parts = list()
+ parts += "Medal Commendations:"
+ for (var/com in GLOB.commendations)
+ parts += com
+ return "
[parts.Join(" ")]
"
+ return ""
+
+/datum/controller/subsystem/ticker/proc/antag_report()
+ var/list/result = list()
+ var/list/all_teams = list()
+ var/list/all_antagonists = list()
+
+ for(var/datum/antagonist/A in GLOB.antagonists)
+ all_teams |= A.get_team()
+ all_antagonists += A
+
+ for(var/datum/objective_team/T in all_teams)
+ result += T.roundend_report()
+ for(var/datum/antagonist/X in all_antagonists)
+ if(X.get_team() == T)
+ all_antagonists -= X
+ result += " "//newline between teams
+
+ var/currrent_category
+ var/datum/antagonist/previous_category
+
+ sortTim(all_antagonists, /proc/cmp_antag_category)
+
+ for(var/datum/antagonist/A in all_antagonists)
+ if(!A.show_in_roundend)
+ continue
+ if(A.roundend_category != currrent_category)
+ if(previous_category)
+ result += previous_category.roundend_report_footer()
+ result += "
"
+ result += "
"
+ result += A.roundend_report_header()
+ currrent_category = A.roundend_category
+ previous_category = A
+ result += A.roundend_report()
+ result += "
"
+
+ if(all_antagonists.len)
+ var/datum/antagonist/last = all_antagonists[all_antagonists.len]
+ result += last.roundend_report_footer()
+ result += "
"
+
+ return result.Join()
+
+/proc/cmp_antag_category(datum/antagonist/A,datum/antagonist/B)
+ return sorttext(B.roundend_category,A.roundend_category)
+
+
+/datum/controller/subsystem/ticker/proc/give_show_report_button(client/C)
+ var/datum/action/report/R = new
+ C.player_details.player_actions += R
+ R.Grant(C.mob)
+ to_chat(C,"Show roundend report again")
+
+/datum/action/report
+ name = "Show roundend report"
+ button_icon_state = "vote"
+
+/datum/action/report/Trigger()
+ if(owner && GLOB.common_report && SSticker.current_state == GAME_STATE_FINISHED)
+ SSticker.show_roundend_report(owner.client,GLOB.common_report)
+
+/datum/action/report/IsAvailable()
+ return 1
+
+/datum/action/report/Topic(href,href_list)
+ if(usr != owner)
+ return
+ if(href_list["report"])
+ Trigger()
+ return
+
+
+/proc/printplayer(datum/mind/ply, fleecheck)
+ var/text = "[ply.key] was [ply.name] the [ply.assigned_role] and"
+ if(ply.current)
+ if(ply.current.stat == DEAD)
+ text += " died"
+ else
+ text += " survived"
+ if(fleecheck)
+ var/turf/T = get_turf(ply.current)
+ if(!T || !(T.z in GLOB.station_z_levels))
+ text += " while fleeing the station"
+ if(ply.current.real_name != ply.name)
+ text += " as [ply.current.real_name]"
+ else
+ text += " had their body destroyed"
+ return text
+
+/proc/printplayerlist(list/players,fleecheck)
+ var/list/parts = list()
+
+ parts += "
"
+ for(var/datum/mind/M in players)
+ parts += "
[printplayer(M,fleecheck)]
"
+ parts += "
"
+ return parts.Join()
+
+
+/proc/printobjectives(datum/mind/ply)
+ var/list/objective_parts = list()
+ var/count = 1
+ for(var/datum/objective/objective in ply.objectives)
+ if(objective.check_completion())
+ objective_parts += "Objective #[count]: [objective.explanation_text] Success!"
+ else
+ objective_parts += "Objective #[count]: [objective.explanation_text] Fail."
+ count++
+ return objective_parts.Join(" ")
diff --git a/code/__HELPERS/type2type.dm b/code/__HELPERS/type2type.dm
index bae773b27e..2eeee95d09 100644
--- a/code/__HELPERS/type2type.dm
+++ b/code/__HELPERS/type2type.dm
@@ -139,7 +139,6 @@
return NORTH
//returns the north-zero clockwise angle in degrees, given a direction
-
/proc/dir2angle(D)
switch(D)
if(NORTH)
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 9ec23fa966..da7d2134a1 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -199,6 +199,8 @@ Turf and target are separate in case you want to teleport some distance from a t
newname = C.prefs.custom_names[role]
else
switch(role)
+ if("human")
+ newname = random_unique_name(gender)
if("clown")
newname = pick(GLOB.clown_names)
if("mime")
@@ -524,7 +526,7 @@ Turf and target are separate in case you want to teleport some distance from a t
processing_list.Cut(1, 2)
//Byond does not allow things to be in multiple contents, or double parent-child hierarchies, so only += is needed
//This is also why we don't need to check against assembled as we go along
- processing_list += A.contents
+ processing_list += A.contents
assembled += A
return assembled
@@ -1492,6 +1494,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
var/time_low = num2hex(world.time, 3)
var/time_clock = num2hex(TICK_DELTA_TO_MS(world.tick_usage), 3)
+
return "{[time_high]-[time_mid]-[GUID_VERSION][time_low]-[GUID_VARIANT][time_clock]-[node_id]}"
// \ref behaviour got changed in 512 so this is necesary to replicate old behaviour.
diff --git a/code/_globalvars/game_modes.dm b/code/_globalvars/game_modes.dm
index 9c3af923f1..3822f7077d 100644
--- a/code/_globalvars/game_modes.dm
+++ b/code/_globalvars/game_modes.dm
@@ -1,18 +1,12 @@
GLOBAL_VAR_INIT(master_mode, "traitor") //"extended"
GLOBAL_VAR_INIT(secret_force_mode, "secret") // if this is anything but "secret", the secret rotation will forceably choose this mode
+GLOBAL_VAR(common_report) //Contains commmon part of roundend report
+GLOBAL_VAR(survivor_report) //Contains shared surivor report for roundend report (part of personal report)
+
GLOBAL_VAR_INIT(wavesecret, 0) // meteor mode, delays wave progression, terrible name
GLOBAL_DATUM(start_state, /datum/station_state) // Used in round-end report
-// Cult, needs to be global so admin cultists are functional
-GLOBAL_VAR_INIT(blood_target, null) // Cult Master's target or Construct's Master
-GLOBAL_DATUM(blood_target_image, /image)
-GLOBAL_VAR_INIT(blood_target_reset_timer, null)
-GLOBAL_DATUM(sac_mind, /datum/mind)
-GLOBAL_VAR_INIT(sac_image, null)
-GLOBAL_VAR_INIT(cult_vote_called, FALSE)
-GLOBAL_VAR_INIT(cult_mastered, FALSE)
-GLOBAL_VAR_INIT(reckoning_complete, FALSE)
-GLOBAL_VAR_INIT(sac_complete, FALSE)
-GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
-GLOBAL_LIST_EMPTY(summon_spots)
\ No newline at end of file
+
+//TODO clear this one up too
+GLOBAL_DATUM(cult_narsie, /obj/singularity/narsie/large/cult)
\ No newline at end of file
diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm
index bb86b4cbb0..8b8b817586 100644
--- a/code/_globalvars/misc.dm
+++ b/code/_globalvars/misc.dm
@@ -16,3 +16,5 @@ GLOBAL_VAR_INIT(CHARGELEVEL, 0.001) // Cap for how fast cells charge, as a perce
GLOBAL_LIST_EMPTY(powernets)
GLOBAL_VAR_INIT(bsa_unlock, FALSE) //BSA unlocked by head ID swipes
+
+GLOBAL_LIST_EMPTY(player_details) // ckey -> /datum/player_details
\ No newline at end of file
diff --git a/code/_js/byjax.dm b/code/_js/byjax.dm
index 5557440d32..9d96bbc412 100644
--- a/code/_js/byjax.dm
+++ b/code/_js/byjax.dm
@@ -45,3 +45,4 @@ Be sure to include required js functions in your page, or it'll raise an excepti
receiver << output(argums,"[control_id]:replaceContent")
return
+
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index dc06d17819..6d941589d3 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -104,7 +104,7 @@
#define ui_health "EAST-1:28,CENTER-1:15"
#define ui_internal "EAST-1:28,CENTER:17"
-//borgs
+//borgs
#define ui_borg_health "EAST-1:28,CENTER-1:15" //borgs have the health display where humans have the pressure damage indicator.
//aliens
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
index 0006d72d3b..2ad2eb76f5 100644
--- a/code/_onclick/hud/alert.dm
+++ b/code/_onclick/hud/alert.dm
@@ -302,32 +302,41 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
/obj/screen/alert/bloodsense/process()
var/atom/blood_target
- if(GLOB.blood_target)
- if(!get_turf(GLOB.blood_target))
- GLOB.blood_target = null
+
+ var/datum/antagonist/cult/antag = mob_viewer.mind.has_antag_datum(/datum/antagonist/cult,TRUE)
+ if(!antag)
+ return
+ var/datum/objective/sacrifice/sac_objective = locate() in antag.cult_team.objectives
+
+ if(antag.cult_team.blood_target)
+ if(!get_turf(antag.cult_team.blood_target))
+ antag.cult_team.blood_target = null
else
- blood_target = GLOB.blood_target
+ blood_target = antag.cult_team.blood_target
if(Cviewer && Cviewer.seeking && Cviewer.master)
blood_target = Cviewer.master
desc = "Your blood sense is leading you to [Cviewer.master]"
if(!blood_target)
- if(!GLOB.sac_complete)
+ if(sac_objective && !sac_objective.check_completion())
if(icon_state == "runed_sense0")
return
animate(src, transform = null, time = 1, loop = 0)
angle = 0
cut_overlays()
icon_state = "runed_sense0"
- desc = "Nar-Sie demands that [GLOB.sac_mind] be sacrificed before the summoning ritual can begin."
- add_overlay(GLOB.sac_image)
+ desc = "Nar-Sie demands that [sac_objective.target] be sacrificed before the summoning ritual can begin."
+ add_overlay(sac_objective.sac_image)
else
+ var/datum/objective/eldergod/summon_objective = locate() in antag.cult_team.objectives
+ if(!summon_objective)
+ return
if(icon_state == "runed_sense1")
return
animate(src, transform = null, time = 1, loop = 0)
angle = 0
cut_overlays()
icon_state = "runed_sense1"
- desc = "The sacrifice is complete, summon Nar-Sie! The summoning can only take place in [english_list(GLOB.summon_spots)]!"
+ desc = "The sacrifice is complete, summon Nar-Sie! The summoning can only take place in [english_list(summon_objective.summon_spots)]!"
add_overlay(narnar)
return
var/turf/P = get_turf(blood_target)
@@ -388,11 +397,13 @@ or shoot a gun to move around via Newton's 3rd Law of Motion."
desc = "CHETR NYY HAGEHUGF-NAQ-UBABE RATVAR."
else
var/servants = 0
- var/list/textlist
+ var/list/textlist = list()
for(var/mob/living/L in GLOB.alive_mob_list)
if(is_servant_of_ratvar(L))
servants++
- textlist = list("[SSticker.mode.eminence ? "There is an Eminence." : "There is no Eminence! Get one ASAP!"] ")
+ var/datum/antagonist/clockcult/C = mob_viewer.mind.has_antag_datum(/datum/antagonist/clockcult,TRUE)
+ if(C && C.clock_team)
+ textlist += "[C.clock_team.eminence ? "There is an Eminence." : "There is no Eminence! Get one ASAP!"] "
textlist += "There are currently [servants] servant[servants > 1 ? "s" : ""] of Ratvar. "
for(var/i in SSticker.scripture_states)
if(i != SCRIPTURE_DRIVER) //ignore the always-unlocked stuff
diff --git a/code/_onclick/hud/credits.dm b/code/_onclick/hud/credits.dm
new file mode 100644
index 0000000000..dfdbf390c1
--- /dev/null
+++ b/code/_onclick/hud/credits.dm
@@ -0,0 +1,69 @@
+#define CREDIT_ROLL_SPEED 125
+#define CREDIT_SPAWN_SPEED 10
+#define CREDIT_ANIMATE_HEIGHT (14 * world.icon_size)
+#define CREDIT_EASE_DURATION 22
+#define CREDITS_PATH "[GLOB.config_dir]contributors.dmi"
+
+/client/proc/RollCredits()
+ set waitfor = FALSE
+ if(!fexists(CREDITS_PATH))
+ return
+ var/icon/credits_icon = new(CREDITS_PATH)
+ LAZYINITLIST(credits)
+ var/list/_credits = credits
+ verbs += /client/proc/ClearCredits
+ var/static/list/credit_order_for_this_round
+ if(isnull(credit_order_for_this_round))
+ credit_order_for_this_round = list("Thanks for playing!") + (shuffle(icon_states(credits_icon)) - "Thanks for playing!")
+ for(var/I in credit_order_for_this_round)
+ if(!credits)
+ return
+ _credits += new /obj/screen/credit(null, I, src, credits_icon)
+ sleep(CREDIT_SPAWN_SPEED)
+ sleep(CREDIT_ROLL_SPEED - CREDIT_SPAWN_SPEED)
+ verbs -= /client/proc/ClearCredits
+ qdel(credits_icon)
+
+/client/proc/ClearCredits()
+ set name = "Hide Credits"
+ set category = "OOC"
+ verbs -= /client/proc/ClearCredits
+ QDEL_LIST(credits)
+ credits = null
+
+/obj/screen/credit
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ alpha = 0
+ screen_loc = "12,1"
+ layer = SPLASHSCREEN_LAYER
+ var/client/parent
+ var/matrix/target
+
+/obj/screen/credit/Initialize(mapload, credited, client/P, icon/I)
+ . = ..()
+ icon = I
+ parent = P
+ icon_state = credited
+ maptext = credited
+ maptext_x = world.icon_size + 8
+ maptext_y = (world.icon_size / 2) - 4
+ maptext_width = world.icon_size * 3
+ var/matrix/M = matrix(transform)
+ M.Translate(0, CREDIT_ANIMATE_HEIGHT)
+ animate(src, transform = M, time = CREDIT_ROLL_SPEED)
+ target = M
+ animate(src, alpha = 255, time = CREDIT_EASE_DURATION, flags = ANIMATION_PARALLEL)
+ addtimer(CALLBACK(src, .proc/FadeOut), CREDIT_ROLL_SPEED - CREDIT_EASE_DURATION)
+ QDEL_IN(src, CREDIT_ROLL_SPEED)
+ P.screen += src
+
+/obj/screen/credit/Destroy()
+ var/client/P = parent
+ P.screen -= src
+ icon = null
+ LAZYREMOVE(P.credits, src)
+ parent = null
+ return ..()
+
+/obj/screen/credit/proc/FadeOut()
+ animate(src, alpha = 0, transform = target, time = CREDIT_EASE_DURATION)
diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm
index 2047225589..65c4bd23c2 100644
--- a/code/_onclick/hud/fullscreen.dm
+++ b/code/_onclick/hud/fullscreen.dm
@@ -1,3 +1,4 @@
+
/mob
var/list/screens = list()
@@ -174,4 +175,3 @@
layer = LIGHTING_LAYER
blend_mode = BLEND_ADD
show_when_dead = TRUE
-
diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm
index 903f3c0790..87354d6f0b 100644
--- a/code/_onclick/telekinesis.dm
+++ b/code/_onclick/telekinesis.dm
@@ -78,7 +78,7 @@
var/mob/living/carbon/tk_user = null
/obj/item/tk_grab/Initialize()
- ..()
+ . = ..()
START_PROCESSING(SSfastprocess, src)
/obj/item/tk_grab/Destroy()
diff --git a/code/controllers/configuration/config_entry.dm b/code/controllers/configuration/config_entry.dm
index 92dcb9baf0..28643bea20 100644
--- a/code/controllers/configuration/config_entry.dm
+++ b/code/controllers/configuration/config_entry.dm
@@ -9,7 +9,7 @@
var/value
var/default //read-only, just set value directly
- var/resident_file //the file which this belongs to, must be set
+ var/resident_file //the file which this was loaded from, if any
var/modified = FALSE //set to TRUE if the default has been overridden by a config entry
var/protection = NONE
@@ -18,8 +18,6 @@
var/dupes_allowed = FALSE
/datum/config_entry/New()
- if(!resident_file)
- CRASH("Config entry [type] has no resident_file set")
if(type == abstract_type)
CRASH("Abstract config entry [type] instatiated!")
name = lowertext(type2top(type))
@@ -55,8 +53,9 @@
. = !(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "ValidateAndSet" && GLOB.LastAdminCalledTargetRef == "[REF(src)]")
if(!.)
log_admin_private("Config set of [type] to [str_val] attempted by [key_name(usr)]")
-
+
/datum/config_entry/proc/ValidateAndSet(str_val)
+ VASProcCallGuard(str_val)
CRASH("Invalid config entry type!")
/datum/config_entry/proc/ValidateKeyedList(str_val, list_mode, splitter)
@@ -80,12 +79,12 @@
if(LIST_MODE_TEXT)
temp = key_value
continue_check = temp
- if(continue_check && ValidateKeyName(key_name))
+ if(continue_check && ValidateListEntry(key_name, temp))
value[key_name] = temp
return TRUE
return FALSE
-/datum/config_entry/proc/ValidateKeyName(key_name)
+/datum/config_entry/proc/ValidateListEntry(key_name, key_value)
return TRUE
/datum/config_entry/string
@@ -97,6 +96,8 @@
return var_name != "auto_trim" && ..()
/datum/config_entry/string/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
value = auto_trim ? trim(str_val) : str_val
return TRUE
@@ -108,6 +109,8 @@
var/min_val = -INFINITY
/datum/config_entry/number/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
var/temp = text2num(trim(str_val))
if(!isnull(temp))
value = Clamp(integer ? round(temp) : temp, min_val, max_val)
@@ -125,6 +128,8 @@
abstract_type = /datum/config_entry/flag
/datum/config_entry/flag/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
value = text2num(trim(str_val)) != 0
return TRUE
@@ -133,6 +138,8 @@
value = list()
/datum/config_entry/number_list/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
str_val = trim(str_val)
var/list/new_list = list()
var/list/values = splittext(str_val," ")
@@ -152,6 +159,8 @@
dupes_allowed = TRUE
/datum/config_entry/keyed_flag_list/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
return ValidateKeyedList(str_val, LIST_MODE_FLAG, " ")
/datum/config_entry/keyed_number_list
@@ -164,6 +173,8 @@
return var_name != "splitter" && ..()
/datum/config_entry/keyed_number_list/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
return ValidateKeyedList(str_val, LIST_MODE_NUM, splitter)
/datum/config_entry/keyed_string_list
@@ -176,6 +187,8 @@
return var_name != "splitter" && ..()
/datum/config_entry/keyed_string_list/ValidateAndSet(str_val)
+ if(!VASProcCallGuard(str_val))
+ return FALSE
return ValidateKeyedList(str_val, LIST_MODE_TEXT, splitter)
#undef LIST_MODE_NUM
diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm
index e9c0aa71b8..f411bd65d3 100644
--- a/code/controllers/configuration/configuration.dm
+++ b/code/controllers/configuration/configuration.dm
@@ -20,10 +20,13 @@ GLOBAL_PROTECT(config_dir)
/datum/controller/configuration/New()
config = src
- var/list/config_files = InitEntries()
+ InitEntries()
LoadModes()
- for(var/I in config_files)
- LoadEntries(I)
+ if(!LoadEntries("config.txt"))
+ log_config("No $include directives found in config.txt! Loading legacy game_options/dbconfig/comms files...")
+ LoadEntries("game_options.txt")
+ LoadEntries("dbconfig.txt")
+ LoadEntries("comms.txt")
loadmaplist(CONFIG_MAPS_FILE)
/datum/controller/configuration/Destroy()
@@ -42,8 +45,6 @@ GLOBAL_PROTECT(config_dir)
var/list/_entries_by_type = list()
entries_by_type = _entries_by_type
- . = list()
-
for(var/I in typesof(/datum/config_entry)) //typesof is faster in this case
var/datum/config_entry/E = I
if(initial(E.abstract_type) == I)
@@ -57,24 +58,30 @@ GLOBAL_PROTECT(config_dir)
continue
_entries[esname] = E
_entries_by_type[I] = E
- .[E.resident_file] = TRUE
/datum/controller/configuration/proc/RemoveEntry(datum/config_entry/CE)
entries -= CE.name
entries_by_type -= CE.type
-/datum/controller/configuration/proc/LoadEntries(filename)
+/datum/controller/configuration/proc/LoadEntries(filename, list/stack = list())
+ var/filename_to_test = world.system_type == MS_WINDOWS ? lowertext(filename) : filename
+ if(filename_to_test in stack)
+ log_config("Warning: Config recursion detected ([english_list(stack)]), breaking!")
+ return
+ stack = stack + filename_to_test
+
log_config("Loading config file [filename]...")
var/list/lines = world.file2list("[GLOB.config_dir][filename]")
var/list/_entries = entries
for(var/L in lines)
if(!L)
continue
-
- if(copytext(L, 1, 2) == "#")
+
+ var/firstchar = copytext(L, 1, 2)
+ if(firstchar == "#")
continue
- var/lockthis = copytext(L, 1, 2) == "@"
+ var/lockthis = firstchar == "@"
if(lockthis)
L = copytext(L, 2)
@@ -91,14 +98,17 @@ GLOBAL_PROTECT(config_dir)
if(!entry)
continue
+ if(entry == "$include")
+ if(!value)
+ log_config("Warning: Invalid $include directive: [value]")
+ else
+ LoadEntries(value, stack)
+ continue
+
var/datum/config_entry/E = _entries[entry]
if(!E)
log_config("Unknown setting in configuration: '[entry]'")
continue
-
- if(filename != E.resident_file)
- log_config("Found [entry] in [filename] when it should have been in [E.resident_file]! Ignoring.")
- continue
if(lockthis)
E.protection |= CONFIG_ENTRY_LOCKED
@@ -107,10 +117,14 @@ GLOBAL_PROTECT(config_dir)
if(!validated)
log_config("Failed to validate setting \"[value]\" for [entry]")
else if(E.modified && !E.dupes_allowed)
- log_config("Duplicate setting for [entry] ([value]) detected! Using latest.")
+ log_config("Duplicate setting for [entry] ([value], [E.resident_file]) detected! Using latest.")
+
+ E.resident_file = filename
if(validated)
E.modified = TRUE
+
+ . = TRUE
/datum/controller/configuration/can_vv_get(var_name)
return (var_name != "entries_by_type" || !hiding_entries_by_type) && ..()
diff --git a/code/controllers/configuration/entries/comms.dm b/code/controllers/configuration/entries/comms.dm
index bf099f6cb6..e720ed93fd 100644
--- a/code/controllers/configuration/entries/comms.dm
+++ b/code/controllers/configuration/entries/comms.dm
@@ -1,22 +1,28 @@
-#define CURRENT_RESIDENT_FILE "comms.txt"
-
-CONFIG_DEF(string/comms_key)
+/datum/config_entry/string/comms_key
protection = CONFIG_ENTRY_HIDDEN
/datum/config_entry/string/comms_key/ValidateAndSet(str_val)
- return str_val != "default_pwd" && length(str_val) > 6 && ..()
+ return str_val != "default_pwd" && length(str_val) > 6 && ..()
-CONFIG_DEF(string/cross_server_address)
+/datum/config_entry/keyed_string_list/cross_server
protection = CONFIG_ENTRY_LOCKED
-/datum/config_entry/string/cross_server_address/ValidateAndSet(str_val)
- return str_val != "byond:\\address:port" && ..()
+/datum/config_entry/keyed_string_list/cross_server/ValidateAndSet(str_val)
+ . = ..()
+ if(.)
+ var/list/newv = list()
+ for(var/I in value)
+ newv[replacetext(I, "+", " ")] = value[I]
+ value = newv
-CONFIG_DEF(string/cross_comms_name)
+/datum/config_entry/keyed_string_list/cross_server/ValidateListEntry(key_name, key_value)
+ return key_value != "byond:\\address:port" && ..()
+
+/datum/config_entry/string/cross_comms_name
GLOBAL_VAR_INIT(medals_enabled, TRUE) //will be auto set to false if the game fails contacting the medal hub to prevent unneeded calls.
-CONFIG_DEF(string/medal_hub_address)
+/datum/config_entry/string/medal_hub_address
-CONFIG_DEF(string/medal_hub_password)
+/datum/config_entry/string/medal_hub_password
protection = CONFIG_ENTRY_HIDDEN
\ No newline at end of file
diff --git a/code/controllers/configuration/entries/dbconfig.dm b/code/controllers/configuration/entries/dbconfig.dm
index c46880686a..1ac4d85419 100644
--- a/code/controllers/configuration/entries/dbconfig.dm
+++ b/code/controllers/configuration/entries/dbconfig.dm
@@ -1,28 +1,26 @@
-#define CURRENT_RESIDENT_FILE "dbconfig.txt"
-
-CONFIG_DEF(flag/sql_enabled) // for sql switching
+/datum/config_entry/flag/sql_enabled // for sql switching
protection = CONFIG_ENTRY_LOCKED
-CONFIG_DEF(string/address)
+/datum/config_entry/string/address
value = "localhost"
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
-CONFIG_DEF(number/port)
+/datum/config_entry/number/port
value = 3306
min_val = 0
max_val = 65535
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
-CONFIG_DEF(string/feedback_database)
+/datum/config_entry/string/feedback_database
value = "test"
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
-CONFIG_DEF(string/feedback_login)
+/datum/config_entry/string/feedback_login
value = "root"
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
-CONFIG_DEF(string/feedback_password)
+/datum/config_entry/string/feedback_password
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
-CONFIG_DEF(string/feedback_tableprefix)
+/datum/config_entry/string/feedback_tableprefix
protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm
index b04d7845f5..0f7e65ec13 100644
--- a/code/controllers/configuration/entries/game_options.dm
+++ b/code/controllers/configuration/entries/game_options.dm
@@ -1,253 +1,253 @@
-#define CURRENT_RESIDENT_FILE "game_options.txt"
+/datum/config_entry/number_list/repeated_mode_adjust
-CONFIG_DEF(number_list/repeated_mode_adjust)
+/datum/config_entry/keyed_number_list/probability
-CONFIG_DEF(keyed_number_list/probability)
-
-/datum/config_entry/keyed_number_list/probability/ValidateKeyName(key_name)
+/datum/config_entry/keyed_number_list/probability/ValidateListEntry(key_name)
return key_name in config.modes
-CONFIG_DEF(keyed_number_list/max_pop)
+/datum/config_entry/keyed_number_list/max_pop
-/datum/config_entry/keyed_number_list/max_pop/ValidateKeyName(key_name)
+/datum/config_entry/keyed_number_list/max_pop/ValidateListEntry(key_name)
return key_name in config.modes
-CONFIG_DEF(keyed_number_list/min_pop)
+/datum/config_entry/keyed_number_list/min_pop
-/datum/config_entry/keyed_number_list/min_pop/ValidateKeyName(key_name)
+/datum/config_entry/keyed_number_list/min_pop/ValidateListEntry(key_name, key_value)
return key_name in config.modes
-CONFIG_DEF(keyed_flag_list/continuous) // which roundtypes continue if all antagonists die
+/datum/config_entry/keyed_flag_list/continuous // which roundtypes continue if all antagonists die
-/datum/config_entry/keyed_flag_list/continuous/ValidateKeyName(key_name)
+/datum/config_entry/keyed_flag_list/continuous/ValidateListEntry(key_name, key_value)
return key_name in config.modes
-CONFIG_DEF(keyed_flag_list/midround_antag) // which roundtypes use the midround antagonist system
+/datum/config_entry/keyed_flag_list/midround_antag // which roundtypes use the midround antagonist system
-/datum/config_entry/keyed_flag_list/midround_antag/ValidateKeyName(key_name)
+/datum/config_entry/keyed_flag_list/midround_antag/ValidateListEntry(key_name, key_value)
return key_name in config.modes
-CONFIG_DEF(keyed_string_list/policy)
+/datum/config_entry/keyed_string_list/policy
-CONFIG_DEF(number/damage_multiplier)
+/datum/config_entry/number/damage_multiplier
value = 1
integer = FALSE
-CONFIG_DEF(number/minimal_access_threshold) //If the number of players is larger than this threshold, minimal access will be turned on.
+/datum/config_entry/number/minimal_access_threshold //If the number of players is larger than this threshold, minimal access will be turned on.
min_val = 0
-CONFIG_DEF(flag/jobs_have_minimal_access) //determines whether jobs use minimal access or expanded access.
+/datum/config_entry/flag/jobs_have_minimal_access //determines whether jobs use minimal access or expanded access.
-CONFIG_DEF(flag/assistants_have_maint_access)
+/datum/config_entry/flag/assistants_have_maint_access
-CONFIG_DEF(flag/security_has_maint_access)
+/datum/config_entry/flag/security_has_maint_access
-CONFIG_DEF(flag/everyone_has_maint_access)
+/datum/config_entry/flag/everyone_has_maint_access
-CONFIG_DEF(flag/sec_start_brig) //makes sec start in brig instead of dept sec posts
+/datum/config_entry/flag/sec_start_brig //makes sec start in brig instead of dept sec posts
-CONFIG_DEF(flag/force_random_names)
+/datum/config_entry/flag/force_random_names
-CONFIG_DEF(flag/humans_need_surnames)
+/datum/config_entry/flag/humans_need_surnames
-CONFIG_DEF(flag/allow_ai) // allow ai job
+/datum/config_entry/flag/allow_ai // allow ai job
-CONFIG_DEF(flag/disable_secborg) // disallow secborg module to be chosen.
+/datum/config_entry/flag/disable_secborg // disallow secborg module to be chosen.
-CONFIG_DEF(flag/disable_peaceborg)
+/datum/config_entry/flag/disable_peaceborg
-CONFIG_DEF(number/traitor_scaling_coeff) //how much does the amount of players get divided by to determine traitors
+/datum/config_entry/number/traitor_scaling_coeff //how much does the amount of players get divided by to determine traitors
value = 6
min_val = 1
-CONFIG_DEF(number/brother_scaling_coeff) //how many players per brother team
+/datum/config_entry/number/brother_scaling_coeff //how many players per brother team
value = 25
min_val = 1
-CONFIG_DEF(number/changeling_scaling_coeff) //how much does the amount of players get divided by to determine changelings
+/datum/config_entry/number/changeling_scaling_coeff //how much does the amount of players get divided by to determine changelings
value = 6
min_val = 1
-CONFIG_DEF(number/security_scaling_coeff) //how much does the amount of players get divided by to determine open security officer positions
+/datum/config_entry/number/security_scaling_coeff //how much does the amount of players get divided by to determine open security officer positions
value = 8
min_val = 1
-CONFIG_DEF(number/abductor_scaling_coeff) //how many players per abductor team
+/datum/config_entry/number/abductor_scaling_coeff //how many players per abductor team
value = 15
min_val = 1
-CONFIG_DEF(number/traitor_objectives_amount)
+/datum/config_entry/number/traitor_objectives_amount
value = 2
min_val = 0
-CONFIG_DEF(number/brother_objectives_amount)
+/datum/config_entry/number/brother_objectives_amount
value = 2
min_val = 0
-CONFIG_DEF(flag/reactionary_explosions) //If we use reactionary explosions, explosions that react to walls and doors
+/datum/config_entry/flag/reactionary_explosions //If we use reactionary explosions, explosions that react to walls and doors
-CONFIG_DEF(flag/protect_roles_from_antagonist) //If security and such can be traitor/cult/other
+/datum/config_entry/flag/protect_roles_from_antagonist //If security and such can be traitor/cult/other
-CONFIG_DEF(flag/protect_assistant_from_antagonist) //If assistants can be traitor/cult/other
+/datum/config_entry/flag/protect_assistant_from_antagonist //If assistants can be traitor/cult/other
-CONFIG_DEF(flag/enforce_human_authority) //If non-human species are barred from joining as a head of staff
+/datum/config_entry/flag/enforce_human_authority //If non-human species are barred from joining as a head of staff
-CONFIG_DEF(flag/allow_latejoin_antagonists) // If late-joining players can be traitor/changeling
+/datum/config_entry/flag/allow_latejoin_antagonists // If late-joining players can be traitor/changeling
-CONFIG_DEF(number/midround_antag_time_check) // How late (in minutes) you want the midround antag system to stay on, setting this to 0 will disable the system
+/datum/config_entry/number/midround_antag_time_check // How late (in minutes you want the midround antag system to stay on, setting this to 0 will disable the system)
value = 60
min_val = 0
-CONFIG_DEF(number/midround_antag_life_check) // A ratio of how many people need to be alive in order for the round not to immediately end in midround antagonist
+/datum/config_entry/number/midround_antag_life_check // A ratio of how many people need to be alive in order for the round not to immediately end in midround antagonist
value = 0.7
integer = FALSE
min_val = 0
max_val = 1
-CONFIG_DEF(number/shuttle_refuel_delay)
+/datum/config_entry/number/shuttle_refuel_delay
value = 12000
min_val = 0
-CONFIG_DEF(flag/show_game_type_odds) //if set this allows players to see the odds of each roundtype on the get revision screen
+/datum/config_entry/flag/show_game_type_odds //if set this allows players to see the odds of each roundtype on the get revision screen
-CONFIG_DEF(keyed_flag_list/roundstart_races) //races you can play as from the get go.
+/datum/config_entry/keyed_flag_list/roundstart_races //races you can play as from the get go.
-CONFIG_DEF(flag/join_with_mutant_humans) //players can pick mutant bodyparts for humans before joining the game
+/datum/config_entry/flag/join_with_mutant_humans //players can pick mutant bodyparts for humans before joining the game
-CONFIG_DEF(flag/no_summon_guns) //No
+/datum/config_entry/flag/no_summon_guns //No
-CONFIG_DEF(flag/no_summon_magic) //Fun
+/datum/config_entry/flag/no_summon_magic //Fun
-CONFIG_DEF(flag/no_summon_events) //Allowed
+/datum/config_entry/flag/no_summon_events //Allowed
-CONFIG_DEF(flag/no_intercept_report) //Whether or not to send a communications intercept report roundstart. This may be overriden by gamemodes.
+/datum/config_entry/flag/no_intercept_report //Whether or not to send a communications intercept report roundstart. This may be overriden by gamemodes.
-CONFIG_DEF(number/arrivals_shuttle_dock_window) //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station
+/datum/config_entry/number/arrivals_shuttle_dock_window //Time from when a player late joins on the arrivals shuttle to when the shuttle docks on the station
value = 55
min_val = 30
-CONFIG_DEF(flag/arrivals_shuttle_require_undocked) //Require the arrivals shuttle to be undocked before latejoiners can join
+/datum/config_entry/flag/arrivals_shuttle_require_undocked //Require the arrivals shuttle to be undocked before latejoiners can join
-CONFIG_DEF(flag/arrivals_shuttle_require_safe_latejoin) //Require the arrivals shuttle to be operational in order for latejoiners to join
+/datum/config_entry/flag/arrivals_shuttle_require_safe_latejoin //Require the arrivals shuttle to be operational in order for latejoiners to join
-CONFIG_DEF(string/alert_green)
+/datum/config_entry/string/alert_green
value = "All threats to the station have passed. Security may not have weapons visible, privacy laws are once again fully enforced."
-CONFIG_DEF(string/alert_blue_upto)
+/datum/config_entry/string/alert_blue_upto
value = "The station has received reliable information about possible hostile activity on the station. Security staff may have weapons visible, random searches are permitted."
-CONFIG_DEF(string/alert_blue_downto)
+/datum/config_entry/string/alert_blue_downto
value = "The immediate threat has passed. Security may no longer have weapons drawn at all times, but may continue to have them visible. Random searches are still allowed."
-CONFIG_DEF(string/alert_red_upto)
+/datum/config_entry/string/alert_red_upto
value = "There is an immediate serious threat to the station. Security may have weapons unholstered at all times. Random searches are allowed and advised."
-CONFIG_DEF(string/alert_red_downto)
+/datum/config_entry/string/alert_red_downto
value = "The station's destruction has been averted. There is still however an immediate serious threat to the station. Security may have weapons unholstered at all times, random searches are allowed and advised."
-CONFIG_DEF(string/alert_delta)
+/datum/config_entry/string/alert_delta
value = "Destruction of the station is imminent. All crew are instructed to obey all instructions given by heads of staff. Any violations of these orders can be punished by death. This is not a drill."
-CONFIG_DEF(flag/revival_pod_plants)
+/datum/config_entry/flag/revival_pod_plants
-CONFIG_DEF(flag/revival_cloning)
+/datum/config_entry/flag/revival_cloning
-CONFIG_DEF(number/revival_brain_life)
+/datum/config_entry/number/revival_brain_life
value = -1
min_val = -1
-CONFIG_DEF(flag/rename_cyborg)
+/datum/config_entry/flag/rename_cyborg
-CONFIG_DEF(flag/ooc_during_round)
+/datum/config_entry/flag/ooc_during_round
-CONFIG_DEF(flag/emojis)
+/datum/config_entry/flag/emojis
-CONFIG_DEF(number/run_delay) //Used for modifying movement speed for mobs.
+/datum/config_entry/number/run_delay //Used for modifying movement speed for mobs.
var/static/value_cache = 0
-CONFIG_TWEAK(number/run_delay/ValidateAndSet())
+/datum/config_entry/number/run_delay/ValidateAndSet()
. = ..()
if(.)
value_cache = value
-CONFIG_DEF(number/walk_delay)
+/datum/config_entry/number/walk_delay
var/static/value_cache = 0
-CONFIG_TWEAK(number/walk_delay/ValidateAndSet())
+/datum/config_entry/number/walk_delay/ValidateAndSet()
. = ..()
if(.)
value_cache = value
-CONFIG_DEF(number/human_delay) //Mob specific modifiers. NOTE: These will affect different mob types in different ways
-CONFIG_DEF(number/robot_delay)
-CONFIG_DEF(number/monkey_delay)
-CONFIG_DEF(number/alien_delay)
-CONFIG_DEF(number/slime_delay)
-CONFIG_DEF(number/animal_delay)
+/datum/config_entry/number/human_delay //Mob specific modifiers. NOTE: These will affect different mob types in different ways
+/datum/config_entry/number/robot_delay
+/datum/config_entry/number/monkey_delay
+/datum/config_entry/number/alien_delay
+/datum/config_entry/number/slime_delay
+/datum/config_entry/number/animal_delay
-CONFIG_DEF(number/gateway_delay) //How long the gateway takes before it activates. Default is half an hour.
+/datum/config_entry/number/gateway_delay //How long the gateway takes before it activates. Default is half an hour.
value = 18000
min_val = 0
-CONFIG_DEF(flag/ghost_interaction)
+/datum/config_entry/flag/ghost_interaction
-CONFIG_DEF(flag/silent_ai)
-CONFIG_DEF(flag/silent_borg)
+/datum/config_entry/flag/silent_ai
+/datum/config_entry/flag/silent_borg
-CONFIG_DEF(flag/sandbox_autoclose) // close the sandbox panel after spawning an item, potentially reducing griff
+/datum/config_entry/flag/sandbox_autoclose // close the sandbox panel after spawning an item, potentially reducing griff
-CONFIG_DEF(number/default_laws) //Controls what laws the AI spawns with.
+/datum/config_entry/number/default_laws //Controls what laws the AI spawns with.
value = 0
min_val = 0
max_val = 3
-CONFIG_DEF(number/silicon_max_law_amount)
+/datum/config_entry/number/silicon_max_law_amount
value = 12
min_val = 0
-CONFIG_DEF(keyed_flag_list/random_laws)
+/datum/config_entry/keyed_flag_list/random_laws
-CONFIG_DEF(keyed_number_list/law_weight)
+/datum/config_entry/keyed_number_list/law_weight
splitter = ","
-CONFIG_DEF(number/assistant_cap)
+/datum/config_entry/number/assistant_cap
value = -1
min_val = -1
-CONFIG_DEF(flag/starlight)
-CONFIG_DEF(flag/grey_assistants)
+/datum/config_entry/flag/starlight
+/datum/config_entry/flag/grey_assistants
-CONFIG_DEF(number/lavaland_budget)
+/datum/config_entry/number/lavaland_budget
value = 60
min_val = 0
-CONFIG_DEF(number/space_budget)
+/datum/config_entry/number/space_budget
value = 16
min_val = 0
-CONFIG_DEF(flag/allow_random_events) // Enables random events mid-round when set
+/datum/config_entry/flag/allow_random_events // Enables random events mid-round when set
-CONFIG_DEF(number/events_min_time_mul) // Multipliers for random events minimal starting time and minimal players amounts
+/datum/config_entry/number/events_min_time_mul // Multipliers for random events minimal starting time and minimal players amounts
value = 1
min_val = 0
integer = FALSE
-CONFIG_DEF(number/events_min_players_mul)
+/datum/config_entry/number/events_min_players_mul
value = 1
min_val = 0
integer = FALSE
-CONFIG_DEF(number/mice_roundstart)
+/datum/config_entry/number/mice_roundstart
value = 10
min_val = 0
-CONFIG_DEF(number/bombcap)
+/datum/config_entry/number/bombcap
value = 14
min_val = 4
-CONFIG_DEF(flag/allow_crew_objectives)
-CONFIG_DEF(flag/allow_miscreants)
-CONFIG_DEF(flag/allow_extended_miscreants)
+/datum/config_entry/flag/allow_crew_objectives
+
+/datum/config_entry/flag/allow_miscreants
+
+/datum/config_entry/flag/allow_extended_miscreants
/datum/config_entry/number/bombcap/ValidateAndSet(str_val)
. = ..()
@@ -258,9 +258,9 @@ CONFIG_DEF(flag/allow_extended_miscreants)
GLOB.MAX_EX_FLASH_RANGE = value
GLOB.MAX_EX_FLAME_RANGE = value
-CONFIG_DEF(number/emergency_shuttle_autocall_threshold)
+/datum/config_entry/number/emergency_shuttle_autocall_threshold
min_val = 0
max_val = 1
integer = FALSE
-CONFIG_DEF(flag/ic_printing)
+/datum/config_entry/flag/ic_printing
diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm
new file mode 100644
index 0000000000..e6b3695033
--- /dev/null
+++ b/code/controllers/configuration/entries/general.dm
@@ -0,0 +1,388 @@
+/datum/config_entry/flag/autoadmin // if autoadmin is enabled
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/string/autoadmin_rank // the rank for autoadmins
+ value = "Game Master"
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/string/servername // server name (the name of the game window)
+
+/datum/config_entry/string/serversqlname // short form server name used for the DB
+
+/datum/config_entry/string/stationname // station name (the name of the station in-game)
+
+/datum/config_entry/number/lobby_countdown // In between round countdown.
+ value = 120
+ min_val = 0
+
+/datum/config_entry/number/round_end_countdown // Post round murder death kill countdown
+ value = 25
+ min_val = 0
+
+/datum/config_entry/flag/hub // if the game appears on the hub or not
+
+/datum/config_entry/flag/log_ooc // log OOC channel
+
+/datum/config_entry/flag/log_access // log login/logout
+
+/datum/config_entry/flag/log_say // log client say
+
+/datum/config_entry/flag/log_admin // log admin actions
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/log_prayer // log prayers
+
+/datum/config_entry/flag/log_law // log lawchanges
+
+/datum/config_entry/flag/log_game // log game events
+
+/datum/config_entry/flag/log_vote // log voting
+
+/datum/config_entry/flag/log_whisper // log client whisper
+
+/datum/config_entry/flag/log_attack // log attack messages
+
+/datum/config_entry/flag/log_emote // log emotes
+
+/datum/config_entry/flag/log_adminchat // log admin chat messages
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/log_pda // log pda messages
+
+/datum/config_entry/flag/log_twitter // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
+
+/datum/config_entry/flag/log_world_topic // log all world.Topic() calls
+
+/datum/config_entry/flag/log_manifest // log crew manifest to seperate file
+
+/datum/config_entry/flag/allow_admin_ooccolor // Allows admins with relevant permissions to have their own ooc colour
+
+/datum/config_entry/flag/allow_vote_restart // allow votes to restart
+
+/datum/config_entry/flag/allow_vote_mode // allow votes to change mode
+
+/datum/config_entry/number/vote_delay // minimum time between voting sessions (deciseconds, 10 minute default)
+ value = 6000
+ min_val = 0
+
+/datum/config_entry/number/vote_period // length of voting period (deciseconds, default 1 minute)
+ value = 600
+ min_val = 0
+
+/datum/config_entry/flag/default_no_vote // vote does not default to nochange/norestart
+
+/datum/config_entry/flag/no_dead_vote // dead people can't vote
+
+/datum/config_entry/flag/allow_metadata // Metadata is supported.
+
+/datum/config_entry/flag/popup_admin_pm // adminPMs to non-admins show in a pop-up 'reply' window when set
+
+/datum/config_entry/number/fps
+ value = 20
+ min_val = 1
+ max_val = 100 //byond will start crapping out at 50, so this is just ridic
+ var/sync_validate = FALSE
+
+/datum/config_entry/number/fps/ValidateAndSet(str_val)
+ . = ..()
+ if(.)
+ sync_validate = TRUE
+ var/datum/config_entry/number/ticklag/TL = config.entries_by_type[/datum/config_entry/number/ticklag]
+ if(!TL.sync_validate)
+ TL.ValidateAndSet(10 / value)
+ sync_validate = FALSE
+
+/datum/config_entry/number/ticklag
+ integer = FALSE
+ var/sync_validate = FALSE
+
+/datum/config_entry/number/ticklag/New() //ticklag weirdly just mirrors fps
+ var/datum/config_entry/CE = /datum/config_entry/number/fps
+ value = 10 / initial(CE.value)
+ ..()
+
+/datum/config_entry/number/ticklag/ValidateAndSet(str_val)
+ . = text2num(str_val) > 0 && ..()
+ if(.)
+ sync_validate = TRUE
+ var/datum/config_entry/number/fps/FPS = config.entries_by_type[/datum/config_entry/number/fps]
+ if(!FPS.sync_validate)
+ FPS.ValidateAndSet(10 / value)
+ sync_validate = FALSE
+
+/datum/config_entry/flag/allow_holidays
+
+/datum/config_entry/number/tick_limit_mc_init //SSinitialization throttling
+ value = TICK_LIMIT_MC_INIT_DEFAULT
+ min_val = 0 //oranges warned us
+ integer = FALSE
+
+/datum/config_entry/flag/admin_legacy_system //Defines whether the server uses the legacy admin system with admins.txt or the SQL system
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/string/hostedby
+
+/datum/config_entry/flag/norespawn
+
+/datum/config_entry/flag/guest_jobban
+
+/datum/config_entry/flag/usewhitelist
+
+/datum/config_entry/flag/ban_legacy_system //Defines whether the server uses the legacy banning system with the files in /data or the SQL system.
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/use_age_restriction_for_jobs //Do jobs use account age restrictions? --requires database
+
+/datum/config_entry/flag/use_account_age_for_jobs //Uses the time they made the account for the job restriction stuff. New player joining alerts should be unaffected.
+
+/datum/config_entry/flag/use_exp_tracking
+
+/datum/config_entry/flag/use_exp_restrictions_heads
+
+/datum/config_entry/number/use_exp_restrictions_heads_hours
+ value = 0
+ min_val = 0
+
+/datum/config_entry/flag/use_exp_restrictions_heads_department
+
+/datum/config_entry/flag/use_exp_restrictions_other
+
+/datum/config_entry/flag/use_exp_restrictions_admin_bypass
+
+/datum/config_entry/string/server
+
+/datum/config_entry/string/banappeals
+
+/datum/config_entry/string/wikiurl
+ value = "http://www.tgstation13.org/wiki"
+
+/datum/config_entry/string/forumurl
+ value = "http://tgstation13.org/phpBB/index.php"
+
+/datum/config_entry/string/rulesurl
+ value = "http://www.tgstation13.org/wiki/Rules"
+
+/datum/config_entry/string/githuburl
+ value = "https://www.github.com/tgstation/-tg-station"
+
+/datum/config_entry/number/githubrepoid
+ value = null
+ min_val = 0
+
+/datum/config_entry/flag/guest_ban
+
+/datum/config_entry/number/id_console_jobslot_delay
+ value = 30
+ min_val = 0
+
+/datum/config_entry/number/inactivity_period //time in ds until a player is considered inactive
+ value = 3000
+ min_val = 0
+
+/datum/config_entry/number/inactivity_period/ValidateAndSet(str_val)
+ . = ..()
+ if(.)
+ value *= 10 //documented as seconds in config.txt
+
+/datum/config_entry/number/afk_period //time in ds until a player is considered inactive
+ value = 3000
+ min_val = 0
+
+/datum/config_entry/number/afk_period/ValidateAndSet(str_val)
+ . = ..()
+ if(.)
+ value *= 10 //documented as seconds in config.txt
+
+/datum/config_entry/flag/kick_inactive //force disconnect for inactive players
+
+/datum/config_entry/flag/load_jobs_from_txt
+
+/datum/config_entry/flag/forbid_singulo_possession
+
+/datum/config_entry/flag/automute_on //enables automuting/spam prevention
+
+/datum/config_entry/string/panic_server_name
+
+/datum/config_entry/string/panic_server_name/ValidateAndSet(str_val)
+ return str_val != "\[Put the name here\]" && ..()
+
+/datum/config_entry/string/panic_server_address //Reconnect a player this linked server if this server isn't accepting new players
+
+/datum/config_entry/string/panic_server_address/ValidateAndSet(str_val)
+ return str_val != "byond://address:port" && ..()
+
+/datum/config_entry/string/invoke_youtubedl
+ protection = CONFIG_ENTRY_LOCKED | CONFIG_ENTRY_HIDDEN
+
+/datum/config_entry/flag/show_irc_name
+
+/datum/config_entry/flag/see_own_notes //Can players see their own admin notes
+
+/datum/config_entry/number/note_fresh_days
+ value = null
+ min_val = 0
+ integer = FALSE
+
+/datum/config_entry/number/note_stale_days
+ value = null
+ min_val = 0
+ integer = FALSE
+
+/datum/config_entry/flag/maprotation
+
+/datum/config_entry/number/maprotatechancedelta
+ value = 0.75
+ min_val = 0
+ max_val = 1
+ integer = FALSE
+
+/datum/config_entry/number/soft_popcap
+ value = null
+ min_val = 0
+
+/datum/config_entry/number/hard_popcap
+ value = null
+ min_val = 0
+
+/datum/config_entry/number/extreme_popcap
+ value = null
+ min_val = 0
+
+/datum/config_entry/string/soft_popcap_message
+ value = "Be warned that the server is currently serving a high number of users, consider using alternative game servers."
+
+/datum/config_entry/string/hard_popcap_message
+ value = "The server is currently serving a high number of users, You cannot currently join. You may wait for the number of living crew to decline, observe, or find alternative servers."
+
+/datum/config_entry/string/extreme_popcap_message
+ value = "The server is currently serving a high number of users, find alternative servers."
+
+/datum/config_entry/flag/panic_bunker // prevents people the server hasn't seen before from connecting
+
+/datum/config_entry/number/notify_new_player_age // how long do we notify admins of a new player
+ min_val = -1
+
+/datum/config_entry/number/notify_new_player_account_age // how long do we notify admins of a new byond account
+ min_val = 0
+
+/datum/config_entry/flag/irc_first_connection_alert // do we notify the irc channel when somebody is connecting for the first time?
+
+/datum/config_entry/flag/check_randomizer
+
+/datum/config_entry/string/ipintel_email
+
+/datum/config_entry/string/ipintel_email/ValidateAndSet(str_val)
+ return str_val != "ch@nge.me" && ..()
+
+/datum/config_entry/number/ipintel_rating_bad
+ value = 1
+ integer = FALSE
+ min_val = 0
+ max_val = 1
+
+/datum/config_entry/number/ipintel_save_good
+ value = 12
+ min_val = 0
+
+/datum/config_entry/number/ipintel_save_bad
+ value = 1
+ min_val = 0
+
+/datum/config_entry/string/ipintel_domain
+ value = "check.getipintel.net"
+
+/datum/config_entry/flag/aggressive_changelog
+
+/datum/config_entry/flag/autoconvert_notes //if all connecting player's notes should attempt to be converted to the database
+ protection = CONFIG_ENTRY_LOCKED
+
+/datum/config_entry/flag/allow_webclient
+
+/datum/config_entry/flag/webclient_only_byond_members
+
+/datum/config_entry/flag/announce_admin_logout
+
+/datum/config_entry/flag/announce_admin_login
+
+/datum/config_entry/flag/allow_map_voting
+
+/datum/config_entry/flag/generate_minimaps
+
+/datum/config_entry/number/client_warn_version
+ value = null
+ min_val = 500
+ max_val = DM_VERSION - 1
+
+/datum/config_entry/string/client_warn_message
+ value = "Your version of byond may have issues or be blocked from accessing this server in the future."
+
+/datum/config_entry/flag/client_warn_popup
+
+/datum/config_entry/number/client_error_version
+ value = null
+ min_val = 500
+ max_val = DM_VERSION - 1
+
+/datum/config_entry/string/client_error_message
+ value = "Your version of byond is too old, may have issues, and is blocked from accessing this server."
+
+/datum/config_entry/number/minute_topic_limit
+ value = null
+ min_val = 0
+
+/datum/config_entry/number/second_topic_limit
+ value = null
+ min_val = 0
+
+/datum/config_entry/number/error_cooldown // The "cooldown" time for each occurrence of a unique error
+ value = 600
+ min_val = 0
+
+/datum/config_entry/number/error_limit // How many occurrences before the next will silence them
+ value = 50
+
+/datum/config_entry/number/error_silence_time // How long a unique error will be silenced for
+ value = 6000
+
+/datum/config_entry/number/error_msg_delay // How long to wait between messaging admins about occurrences of a unique error
+ value = 50
+
+/datum/config_entry/flag/irc_announce_new_game
+
+/datum/config_entry/flag/debug_admin_hrefs
+
+/datum/config_entry/number/mc_tick_rate/base_mc_tick_rate
+ integer = FALSE
+ value = 1
+
+/datum/config_entry/number/mc_tick_rate/high_pop_mc_tick_rate
+ integer = FALSE
+ value = 1.1
+
+/datum/config_entry/number/mc_tick_rate/high_pop_mc_mode_amount
+ value = 65
+
+/datum/config_entry/number/mc_tick_rate/disable_high_pop_mc_mode_amount
+ value = 60
+
+/datum/config_entry/number/mc_tick_rate
+ abstract_type = /datum/config_entry/number/mc_tick_rate
+
+/datum/config_entry/number/mc_tick_rate/ValidateAndSet(str_val)
+ . = ..()
+ if (.)
+ Master.UpdateTickRate()
+
+/datum/config_entry/flag/resume_after_initializations
+
+/datum/config_entry/flag/resume_after_initializations/ValidateAndSet(str_val)
+ . = ..()
+ if(. && Master.current_runlevel)
+ world.sleep_offline = !value
+
+/datum/config_entry/number/rounds_until_hard_restart
+ value = -1
+ min_val = 0
+
+/datum/config_entry/string/default_view
+ value = "15x15"
diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm
index 59b6fc34ef..93230b3e37 100644
--- a/code/controllers/subsystem/air.dm
+++ b/code/controllers/subsystem/air.dm
@@ -394,4 +394,4 @@ SUBSYSTEM_DEF(air)
#undef SSAIR_EXCITEDGROUPS
#undef SSAIR_HIGHPRESSURE
#undef SSAIR_HOTSPOT
-#undef SSAIR_SUPERCONDUCTIVITY
\ No newline at end of file
+#undef SSAIR_SUPERCONDUCTIVITY
diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm
index 941fcbbcd6..485e4e7fd3 100644
--- a/code/controllers/subsystem/blackbox.dm
+++ b/code/controllers/subsystem/blackbox.dm
@@ -8,11 +8,11 @@ SUBSYSTEM_DEF(blackbox)
var/list/feedback = list() //list of datum/feedback_variable
var/triggertime = 0
var/sealed = FALSE //time to stop tracking stats?
- var/list/research_levels = list() //list of highest tech levels attained that isn't lost lost by destruction of RD computers
- var/list/versions = list("time_dilation_current" = 2,
+ var/list/versions = list("antagonists" = 3,
+ "admin_secrets_fun_used" = 2,
+ "time_dilation_current" = 3,
"science_techweb_unlock" = 2) //associative list of any feedback variables that have had their format changed since creation and their current version, remember to update this
-
/datum/controller/subsystem/blackbox/Initialize()
triggertime = world.time
. = ..()
@@ -62,8 +62,6 @@ SUBSYSTEM_DEF(blackbox)
record_feedback("tally", "radio_usage", MS.pda_msgs.len, "PDA")
if (MS.rc_msgs.len)
record_feedback("tally", "radio_usage", MS.rc_msgs.len, "request console")
- if(research_levels.len)
- SSblackbox.record_feedback("associative", "high_research_level", 1, research_levels)
if (!SSdbcore.Connect())
return
@@ -90,39 +88,35 @@ SUBSYSTEM_DEF(blackbox)
sealed = TRUE
return TRUE
-/datum/controller/subsystem/blackbox/proc/log_research(tech, level)
- if(!(tech in research_levels) || research_levels[tech] < level)
- research_levels[tech] = level
-
/datum/controller/subsystem/blackbox/proc/LogBroadcast(freq)
if(sealed)
return
switch(freq)
- if(1459)
+ if(FREQ_COMMON)
record_feedback("tally", "radio_usage", 1, "common")
- if(GLOB.SCI_FREQ)
+ if(FREQ_SCIENCE)
record_feedback("tally", "radio_usage", 1, "science")
- if(GLOB.COMM_FREQ)
+ if(FREQ_COMMAND)
record_feedback("tally", "radio_usage", 1, "command")
- if(GLOB.MED_FREQ)
+ if(FREQ_MEDICAL)
record_feedback("tally", "radio_usage", 1, "medical")
- if(GLOB.ENG_FREQ)
+ if(FREQ_ENGINEERING)
record_feedback("tally", "radio_usage", 1, "engineering")
- if(GLOB.SEC_FREQ)
+ if(FREQ_SECURITY)
record_feedback("tally", "radio_usage", 1, "security")
- if(GLOB.SYND_FREQ)
+ if(FREQ_SYNDICATE)
record_feedback("tally", "radio_usage", 1, "syndicate")
- if(GLOB.SERV_FREQ)
+ if(FREQ_SERVICE)
record_feedback("tally", "radio_usage", 1, "service")
- if(GLOB.SUPP_FREQ)
+ if(FREQ_SUPPLY)
record_feedback("tally", "radio_usage", 1, "supply")
- if(GLOB.CENTCOM_FREQ)
+ if(FREQ_CENTCOM)
record_feedback("tally", "radio_usage", 1, "centcom")
- if(GLOB.AIPRIV_FREQ)
+ if(FREQ_AI_PRIVATE)
record_feedback("tally", "radio_usage", 1, "ai private")
- if(GLOB.REDTEAM_FREQ)
+ if(FREQ_CTF_RED)
record_feedback("tally", "radio_usage", 1, "CTF red team")
- if(GLOB.BLUETEAM_FREQ)
+ if(FREQ_CTF_BLUE)
record_feedback("tally", "radio_usage", 1, "CTF blue team")
else
record_feedback("tally", "radio_usage", 1, "other")
@@ -192,7 +186,7 @@ Versioning
"gun_fired" = 2)
*/
/datum/controller/subsystem/blackbox/proc/record_feedback(key_type, key, increment, data, overwrite)
- if(sealed || !key_type || !istext(key) || !isnum(increment || !data))
+ if(sealed || !key_type || !istext(key) || !isnum(increment) || !data)
return
var/datum/feedback_variable/FV = find_feedback_datum(key, key_type)
switch(key_type)
@@ -225,7 +219,10 @@ Versioning
var/pos = length(FV.json["data"]) + 1
FV.json["data"]["[pos]"] = list() //in 512 "pos" can be replaced with "[FV.json["data"].len+1]"
for(var/i in data)
- FV.json["data"]["[pos]"]["[i]"] = "[data[i]]" //and here with "[FV.json["data"].len]"
+ if(islist(data[i]))
+ FV.json["data"]["[pos]"]["[i]"] = data[i] //and here with "[FV.json["data"].len]"
+ else
+ FV.json["data"]["[pos]"]["[i]"] = "[data[i]]"
else
CRASH("Invalid feedback key_type: [key_type]")
diff --git a/code/controllers/subsystem/input.dm b/code/controllers/subsystem/input.dm
new file mode 100644
index 0000000000..f4763a74ed
--- /dev/null
+++ b/code/controllers/subsystem/input.dm
@@ -0,0 +1,12 @@
+SUBSYSTEM_DEF(input)
+ name = "Input"
+ wait = 1 //SS_TICKER means this runs every tick
+ flags = SS_TICKER | SS_NO_INIT | SS_KEEP_TIMING
+ priority = 151
+ runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
+
+/datum/controller/subsystem/input/fire()
+ var/list/clients = GLOB.clients // Let's sing the list cache song
+ for(var/i in 1 to clients.len)
+ var/client/C = clients[i]
+ C.keyLoop()
\ No newline at end of file
diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm
index 5cfbeb9414..756a22174a 100644
--- a/code/controllers/subsystem/job.dm
+++ b/code/controllers/subsystem/job.dm
@@ -107,9 +107,6 @@ SUBSYSTEM_DEF(job)
if(player.mind && job.title in player.mind.restricted_roles)
Debug("FOC incompatible with antagonist role, Player: [player]")
continue
- if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
- Debug("FOC non-human failed, Player: [player]")
- continue
if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
Debug("FOC pass, Player: [player], Level:[level]")
candidates += player
@@ -144,11 +141,6 @@ SUBSYSTEM_DEF(job)
Debug("GRJ incompatible with antagonist role, Player: [player], Job: [job.title]")
continue
- if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
- Debug("GRJ non-human failed, Player: [player]")
- continue
-
-
if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)
Debug("GRJ Random job given, Player: [player], Job: [job]")
if(AssignRole(player, job.title))
@@ -319,10 +311,6 @@ SUBSYSTEM_DEF(job)
Debug("DO incompatible with antagonist role, Player: [player], Job:[job.title]")
continue
- if(CONFIG_GET(flag/enforce_human_authority) && !player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features))
- Debug("DO non-human failed, Player: [player], Job:[job.title]")
- continue
-
// If the player wants that job on this level, then try give it to him.
if(player.client.prefs.GetJobDepartment(job, level) & job.flag)
diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm
index 43565846fb..1ad3a8ab15 100644
--- a/code/controllers/subsystem/lighting.dm
+++ b/code/controllers/subsystem/lighting.dm
@@ -22,7 +22,7 @@ SUBSYSTEM_DEF(lighting)
create_all_lighting_objects()
initialized = TRUE
-
+
fire(FALSE, TRUE)
..()
diff --git a/code/controllers/subsystem/machines.dm b/code/controllers/subsystem/machines.dm
index db6af6d686..e235afaaa4 100644
--- a/code/controllers/subsystem/machines.dm
+++ b/code/controllers/subsystem/machines.dm
@@ -62,4 +62,4 @@ SUBSYSTEM_DEF(machines)
if (istype(SSmachines.processing))
processing = SSmachines.processing
if (istype(SSmachines.powernets))
- powernets = SSmachines.powernets
\ No newline at end of file
+ powernets = SSmachines.powernets
diff --git a/code/controllers/subsystem/npcpool.dm b/code/controllers/subsystem/npcpool.dm
index 6ee4626f25..63ceb15ab8 100644
--- a/code/controllers/subsystem/npcpool.dm
+++ b/code/controllers/subsystem/npcpool.dm
@@ -135,12 +135,12 @@ SUBSYSTEM_DEF(npcpool)
if(facCount == 1 && helpProb)
helpProb = 100
-
+
if(prob(helpProb) && candidate.takeDelegate(check,FALSE))
--canBeUsed.len
candidate.eye_color = "yellow"
candidate.update_icons()
-
+
if(!currentrun.len || MC_TICK_CHECK) //don't change SS state if it isn't necessary
return
diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm
index d310f46d2a..b98be937fc 100644
--- a/code/controllers/subsystem/persistence.dm
+++ b/code/controllers/subsystem/persistence.dm
@@ -250,4 +250,4 @@ SUBSYSTEM_DEF(persistence)
var/list/file_data = list()
file_data["data"] = saved_modes
fdel(json_file)
- WRITE_FILE(json_file, json_encode(file_data))
\ No newline at end of file
+ WRITE_FILE(json_file, json_encode(file_data))
diff --git a/code/controllers/subsystem/radio.dm b/code/controllers/subsystem/radio.dm
index 43803aa647..8299709392 100644
--- a/code/controllers/subsystem/radio.dm
+++ b/code/controllers/subsystem/radio.dm
@@ -14,35 +14,22 @@ SUBSYSTEM_DEF(radio)
/datum/controller/subsystem/radio/proc/add_object(obj/device, new_frequency as num, filter = null as text|null)
var/f_text = num2text(new_frequency)
var/datum/radio_frequency/frequency = frequencies[f_text]
-
if(!frequency)
- frequency = new
- frequency.frequency = new_frequency
- frequencies[f_text] = frequency
-
+ frequencies[f_text] = frequency = new(new_frequency)
frequency.add_listener(device, filter)
return frequency
/datum/controller/subsystem/radio/proc/remove_object(obj/device, old_frequency)
var/f_text = num2text(old_frequency)
var/datum/radio_frequency/frequency = frequencies[f_text]
-
if(frequency)
frequency.remove_listener(device)
-
- if(frequency.devices.len == 0)
- qdel(frequency)
- frequencies -= f_text
-
+ // let's don't delete frequencies in case a non-listener keeps a reference
return 1
/datum/controller/subsystem/radio/proc/return_frequency(new_frequency as num)
var/f_text = num2text(new_frequency)
var/datum/radio_frequency/frequency = frequencies[f_text]
-
if(!frequency)
- frequency = new
- frequency.frequency = new_frequency
- frequencies[f_text] = frequency
-
+ frequencies[f_text] = frequency = new(new_frequency)
return frequency
diff --git a/code/controllers/subsystem/research.dm b/code/controllers/subsystem/research.dm
index d1bcf31885..a2dc4b9c74 100644
--- a/code/controllers/subsystem/research.dm
+++ b/code/controllers/subsystem/research.dm
@@ -54,6 +54,7 @@ SUBSYSTEM_DEF(research)
bitcoins = single_server_income
break //Just need one to work.
var/income_time_difference = world.time - last_income
+ science_tech.last_bitcoins = bitcoins // Doesn't take tick drift into account
bitcoins *= income_time_difference / 10
science_tech.research_points += bitcoins
last_income = world.time
diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm
index c80bc17047..24e31e3c7c 100644
--- a/code/controllers/subsystem/shuttle.dm
+++ b/code/controllers/subsystem/shuttle.dm
@@ -158,7 +158,7 @@ SUBSYSTEM_DEF(shuttle)
break
/datum/controller/subsystem/shuttle/proc/CheckAutoEvac()
- if(emergencyNoEscape || emergencyNoRecall || !emergency)
+ if(emergencyNoEscape || emergencyNoRecall || !emergency || !SSticker.HasRoundStarted())
return
var/threshold = CONFIG_GET(number/emergency_shuttle_autocall_threshold)
@@ -261,7 +261,7 @@ SUBSYSTEM_DEF(shuttle)
if(!admiral_message)
admiral_message = pick(GLOB.admiral_messages)
- var/intercepttext = "NanoTrasen Update: Request For Shuttle.\
+ var/intercepttext = "Nanotrasen Update: Request For Shuttle.\
To whom it may concern:
\
We have taken note of the situation upon [station_name()] and have come to the \
conclusion that it does not warrant the abandonment of the station. \
@@ -382,7 +382,7 @@ SUBSYSTEM_DEF(shuttle)
emergency.setTimer(emergencyDockTime)
priority_announce("Hostile environment resolved. \
You have 3 minutes to board the Emergency Shuttle.",
- null, 'sound/AI/shuttledock.ogg', "Priority")
+ null, 'sound/ai/shuttledock.ogg', "Priority")
//try to move/request to dockHome if possible, otherwise dockAway. Mainly used for admin buttons
/datum/controller/subsystem/shuttle/proc/toggleShuttle(shuttleId, dockHome, dockAway, timed)
diff --git a/code/controllers/subsystem/squeak.dm b/code/controllers/subsystem/squeak.dm
index 0148011e8b..022b659d8a 100644
--- a/code/controllers/subsystem/squeak.dm
+++ b/code/controllers/subsystem/squeak.dm
@@ -1,6 +1,6 @@
// The Squeak
// because this is about placement of mice mobs, and nothing to do with
-// mice - the computer peripheral
+// mice - the computer peripheral
SUBSYSTEM_DEF(squeak)
name = "Squeak"
diff --git a/code/controllers/subsystem/stickyban.dm b/code/controllers/subsystem/stickyban.dm
index 8251df0039..371cf22b3b 100644
--- a/code/controllers/subsystem/stickyban.dm
+++ b/code/controllers/subsystem/stickyban.dm
@@ -27,6 +27,6 @@ SUBSYSTEM_DEF(stickyban)
ban["existing_user_matches_this_round"] = list()
ban["admin_matches_this_round"] = list()
cache[ckey] = ban
-
+
for (var/bannedckey in cache)
world.SetConfig("ban", bannedckey, list2stickyban(cache[bannedckey]))
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index 881bb7fcb7..54b693d543 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -398,204 +398,6 @@ SUBSYSTEM_DEF(ticker)
var/mob/living/L = I
L.notransform = FALSE
-/datum/controller/subsystem/ticker/proc/declare_completion()
- set waitfor = FALSE
- var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
- var/num_survivors = 0
- var/num_escapees = 0
- var/num_shuttle_escapees = 0
- var/list/successfulCrew = list()
- var/list/miscreants = list()
-
- to_chat(world, "
The round has ended.")
- if(LAZYLEN(GLOB.round_end_notifiees))
- send2irc("Notice", "[GLOB.round_end_notifiees.Join(", ")] the round has ended.")
-
-/* var/nocredits = config.no_credits_round_end
- for(var/client/C in GLOB.clients)
- if(!C.credits && !nocredits)
- C.RollCredits()
- C.playtitlemusic(40)*/
-
- //Player status report
- for(var/i in GLOB.mob_list)
- var/mob/Player = i
- if(Player.mind && !isnewplayer(Player))
- if(Player.stat != DEAD && !isbrain(Player))
- num_survivors++
- if(station_evacuated) //If the shuttle has already left the station
- var/list/area/shuttle_areas
- if(SSshuttle && SSshuttle.emergency)
- shuttle_areas = SSshuttle.emergency.shuttle_areas
- if(!Player.onCentCom() && !Player.onSyndieBase())
- to_chat(Player, "You managed to survive, but were marooned on [station_name()]...")
- else
- num_escapees++
- to_chat(Player, "You managed to survive the events on [station_name()] as [Player.real_name].")
- if(shuttle_areas[get_area(Player)])
- num_shuttle_escapees++
- else
- to_chat(Player, "You managed to survive the events on [station_name()] as [Player.real_name].")
- else
- to_chat(Player, "You did not survive the events on [station_name()]...")
-
- CHECK_TICK
-
- //Round statistics report
- var/datum/station_state/end_state = new /datum/station_state()
- end_state.count()
- var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
-
- to_chat(world, " [GLOB.TAB]Shift Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]")
- to_chat(world, " [GLOB.TAB]Station Integrity: [mode.station_was_nuked ? "Destroyed" : "[station_integrity]%"]")
- if(mode.station_was_nuked)
- SSticker.news_report = STATION_DESTROYED_NUKE
- var/total_players = GLOB.joined_player_list.len
- if(total_players)
- to_chat(world, " [GLOB.TAB]Total Population: [total_players]")
- if(station_evacuated)
- to_chat(world, " [GLOB.TAB]Evacuation Rate: [num_escapees] ([PERCENT(num_escapees/total_players)]%)")
- to_chat(world, " [GLOB.TAB](on emergency shuttle): [num_shuttle_escapees] ([PERCENT(num_shuttle_escapees/total_players)]%)")
- news_report = STATION_EVACUATED
- if(SSshuttle.emergency.is_hijacked())
- news_report = SHUTTLE_HIJACK
- to_chat(world, " [GLOB.TAB]Survival Rate: [num_survivors] ([PERCENT(num_survivors/total_players)]%)")
- to_chat(world, " ")
-
- CHECK_TICK
-
- //Silicon laws report
- for (var/i in GLOB.ai_list)
- var/mob/living/silicon/ai/aiPlayer = i
- if (aiPlayer.stat != DEAD && aiPlayer.mind)
- to_chat(world, "[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws at the end of the round were:")
- aiPlayer.show_laws(1)
- else if (aiPlayer.mind) //if the dead ai has a mind, use its key instead
- to_chat(world, "[aiPlayer.name] (Played by: [aiPlayer.mind.key])'s laws when it was deactivated were:")
- aiPlayer.show_laws(1)
-
- to_chat(world, "Total law changes: [aiPlayer.law_change_counter]")
-
- if (aiPlayer.connected_robots.len)
- var/robolist = "[aiPlayer.real_name]'s minions were: "
- for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
- if(robo.mind)
- robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.mind.key]), ":" (Played by: [robo.mind.key]), "]"
- to_chat(world, "[robolist]")
-
- CHECK_TICK
-
- for (var/mob/living/silicon/robot/robo in GLOB.silicon_mobs)
- if (!robo.connected_ai && robo.mind)
- if (robo.stat != DEAD)
- to_chat(world, "[robo.name] (Played by: [robo.mind.key]) survived as an AI-less borg! Its laws were:")
- else
- to_chat(world, "[robo.name] (Played by: [robo.mind.key]) was unable to survive the rigors of being a cyborg without an AI. Its laws were:")
-
- if(robo) //How the hell do we lose robo between here and the world messages directly above this?
- robo.laws.show_laws(world)
-
- CHECK_TICK
-
- mode.declare_completion()//To declare normal completion.
-
- CHECK_TICK
-
- //calls auto_declare_completion_* for all modes
- for(var/handler in typesof(/datum/game_mode/proc))
- if (findtext("[handler]","auto_declare_completion_"))
- call(mode, handler)(force_ending)
-
- CHECK_TICK
-
- if(CONFIG_GET(string/cross_server_address))
- send_news_report()
-
- CHECK_TICK
-
- //Print a list of antagonists to the server log
- var/list/total_antagonists = list()
- //Look into all mobs in world, dead or alive
- for(var/datum/mind/Mind in minds)
- var/temprole = Mind.special_role
- if(temprole) //if they are an antagonist of some sort.
- if(temprole in total_antagonists) //If the role exists already, add the name to it
- total_antagonists[temprole] += ", [Mind.name]([Mind.key])"
- else
- total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob
- total_antagonists[temprole] += ": [Mind.name]([Mind.key])"
-
- CHECK_TICK
-
- //Now print them all into the log!
- log_game("Antagonists at round end were...")
- for(var/i in total_antagonists)
- log_game("[i]s[total_antagonists[i]].")
-
- CHECK_TICK
-
- for(var/datum/mind/crewMind in minds)
- if(!crewMind.current || !crewMind.objectives.len)
- continue
- for(var/datum/objective/miscreant/MO in crewMind.objectives)
- miscreants += "[crewMind.current.real_name] (Played by: [crewMind.key]) Objective: [MO.explanation_text] (Optional)"
- for(var/datum/objective/crew/CO in crewMind.objectives)
- if(CO.check_completion())
- to_chat(crewMind.current, " Your optional objective: [CO.explanation_text] Success!")
- successfulCrew += "[crewMind.current.real_name] (Played by: [crewMind.key]) Objective: [CO.explanation_text] Success! (Optional)"
- else
- to_chat(crewMind.current, " Your optional objective: [CO.explanation_text] Failed.")
-
- if (successfulCrew.len)
- var/completedObjectives = "The following crew members completed their Crew Objectives: "
- for(var/i in successfulCrew)
- completedObjectives += "[i] "
- to_chat(world, "[completedObjectives] ")
- else
- if(CONFIG_GET(flag/allow_crew_objectives))
- to_chat(world, "Nobody completed their Crew Objectives! ")
-
- CHECK_TICK
-
- if (miscreants.len)
- var/miscreantObjectives = "The following crew members were miscreants: "
- for(var/i in miscreants)
- miscreantObjectives += "[i] "
- to_chat(world, "[miscreantObjectives] ")
-
- CHECK_TICK
-
- mode.declare_station_goal_completion()
-
- CHECK_TICK
- //medals, placed far down so that people can actually see the commendations.
- if(GLOB.commendations.len)
- to_chat(world, "Medal Commendations:")
- for (var/com in GLOB.commendations)
- to_chat(world, com)
-
- CHECK_TICK
-
- //Collects persistence features
- if(mode.allow_persistence_save)
- SSpersistence.CollectData()
-
- //stop collecting feedback during grifftime
- SSblackbox.Seal()
-
- sleep(50)
- ready_for_reboot = TRUE
- standard_reboot()
-
-/datum/controller/subsystem/ticker/proc/standard_reboot()
- if(ready_for_reboot)
- if(mode.station_was_nuked)
- Reboot("Station destroyed by Nuclear Device.", "nuke")
- else
- Reboot("Round ended.", "proper completion")
- else
- CRASH("Attempted standard reboot without ticker roundend completion")
-
/datum/controller/subsystem/ticker/proc/send_tip_of_the_round()
var/m
if(selected_tip)
@@ -829,6 +631,7 @@ SUBSYSTEM_DEF(ticker)
world.Reboot()
/datum/controller/subsystem/ticker/Shutdown()
+ gather_newscaster() //called here so we ensure the log is created even upon admin reboot
if(!round_end_sound)
round_end_sound = pick(\
'sound/roundend/newroundsexy.ogg',
diff --git a/code/controllers/subsystem/time_track.dm b/code/controllers/subsystem/time_track.dm
index 17cfa6fc06..3b19ae31cd 100644
--- a/code/controllers/subsystem/time_track.dm
+++ b/code/controllers/subsystem/time_track.dm
@@ -35,4 +35,4 @@ SUBSYSTEM_DEF(time_track)
last_tick_realtime = current_realtime
last_tick_byond_time = current_byondtime
last_tick_tickcount = current_tickcount
- SSblackbox.record_feedback("associative", "time_dilation_current", 1, list("[time_dilation_current]" = "[SQLtime()]"))
+ SSblackbox.record_feedback("associative", "time_dilation_current", 1, list("[SQLtime()]" = list("current" = "[time_dilation_current]", "avg_fast" = "[time_dilation_avg_fast]", "avg" = "[time_dilation_avg]", "avg_slow" = "[time_dilation_avg_slow]")))
diff --git a/code/controllers/subsystem/timer.dm b/code/controllers/subsystem/timer.dm
index 3a2ca82bcd..938cd86396 100644
--- a/code/controllers/subsystem/timer.dm
+++ b/code/controllers/subsystem/timer.dm
@@ -1,5 +1,6 @@
#define BUCKET_LEN (world.fps*1*60) //how many ticks should we keep in the bucket. (1 minutes worth)
-#define BUCKET_POS(timer) (round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) + 1)
+#define BUCKET_POS(timer) ((round((timer.timeToRun - SStimer.head_offset) / world.tick_lag) % BUCKET_LEN) + 1)
+#define TIMER_MAX (world.time + TICKS2DS(min(BUCKET_LEN-(SStimer.practical_offset-DS2TICKS(world.time - SStimer.head_offset))-1, BUCKET_LEN-1)))
#define TIMER_ID_MAX (2**24) //max float with integer precision
SUBSYSTEM_DEF(timer)
@@ -9,11 +10,11 @@ SUBSYSTEM_DEF(timer)
flags = SS_TICKER|SS_NO_INIT
- var/list/datum/timedevent/processing = list()
+ var/list/datum/timedevent/second_queue = list() //awe, yes, you've had first queue, but what about second queue?
var/list/hashes = list()
var/head_offset = 0 //world.time of the first entry in the the bucket.
- var/practical_offset = 0 //index of the first non-empty item in the bucket.
+ var/practical_offset = 1 //index of the first non-empty item in the bucket.
var/bucket_resolution = 0 //world.tick_lag the bucket was designed for
var/bucket_count = 0 //how many timers are in the buckets
@@ -27,13 +28,19 @@ SUBSYSTEM_DEF(timer)
var/static/last_invoke_warning = 0
var/static/bucket_auto_reset = TRUE
+/datum/controller/subsystem/timer/PreInit()
+ bucket_list.len = BUCKET_LEN
+ head_offset = world.time
+ bucket_resolution = world.tick_lag
+
/datum/controller/subsystem/timer/stat_entry(msg)
- ..("B:[bucket_count] P:[length(processing)] H:[length(hashes)] C:[length(clienttime_timers)]")
+ ..("B:[bucket_count] P:[length(second_queue)] H:[length(hashes)] C:[length(clienttime_timers)] S:[length(timer_id_dict)]")
/datum/controller/subsystem/timer/fire(resumed = FALSE)
var/lit = last_invoke_tick
var/last_check = world.time - TIMER_NO_INVOKE_WARNING
var/list/bucket_list = src.bucket_list
+
if(!bucket_count)
last_invoke_tick = world.time
@@ -50,9 +57,9 @@ SUBSYSTEM_DEF(timer)
var/datum/timedevent/bucket_head = bucket_list[i]
if (!bucket_head)
continue
-
+
log_world("Active timers at index [i]:")
-
+
var/datum/timedevent/bucket_node = bucket_head
var/anti_loop_check = 1000
do
@@ -60,50 +67,62 @@ SUBSYSTEM_DEF(timer)
bucket_node = bucket_node.next
anti_loop_check--
while(bucket_node && bucket_node != bucket_head && anti_loop_check)
- log_world("Active timers in the processing queue:")
- for(var/I in processing)
+ log_world("Active timers in the second_queue queue:")
+ for(var/I in second_queue)
log_world(get_timer_debug_string(I))
- while(length(clienttime_timers))
- var/datum/timedevent/ctime_timer = clienttime_timers[clienttime_timers.len]
- if (ctime_timer.timeToRun <= REALTIMEOFDAY)
- --clienttime_timers.len
- var/datum/callback/callBack = ctime_timer.callBack
- ctime_timer.spent = REALTIMEOFDAY
- callBack.InvokeAsync()
- qdel(ctime_timer)
- else
- break //None of the rest are ready to run
+ var/next_clienttime_timer_index = 0
+ var/len = length(clienttime_timers)
+
+ for (next_clienttime_timer_index in 1 to len)
if (MC_TICK_CHECK)
- return
+ next_clienttime_timer_index--
+ break
+ var/datum/timedevent/ctime_timer = clienttime_timers[next_clienttime_timer_index]
+ if (ctime_timer.timeToRun > REALTIMEOFDAY)
+ next_clienttime_timer_index--
+ break
+
+ var/datum/callback/callBack = ctime_timer.callBack
+ if (!callBack)
+ clienttime_timers.Cut(next_clienttime_timer_index,next_clienttime_timer_index+1)
+ CRASH("Invalid timer: [get_timer_debug_string(ctime_timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset], REALTIMEOFDAY: [REALTIMEOFDAY]")
+
+ ctime_timer.spent = REALTIMEOFDAY
+ callBack.InvokeAsync()
+ qdel(ctime_timer)
+
+
+ if (next_clienttime_timer_index)
+ clienttime_timers.Cut(1,next_clienttime_timer_index+1)
+
+ if (MC_TICK_CHECK)
+ return
var/static/list/spent = list()
var/static/datum/timedevent/timer
- var/static/datum/timedevent/head
+ if (practical_offset > BUCKET_LEN)
+ head_offset += TICKS2DS(BUCKET_LEN)
+ practical_offset = 1
+ resumed = FALSE
- if (practical_offset > BUCKET_LEN || (!resumed && length(bucket_list) != BUCKET_LEN || world.tick_lag != bucket_resolution))
- shift_buckets()
+ if ((length(bucket_list) != BUCKET_LEN) || (world.tick_lag != bucket_resolution))
+ reset_buckets()
bucket_list = src.bucket_list
resumed = FALSE
if (!resumed)
timer = null
- head = null
- while (practical_offset <= BUCKET_LEN && head_offset + (practical_offset*world.tick_lag) <= world.time && !MC_TICK_CHECK)
+ while (practical_offset <= BUCKET_LEN && head_offset + (practical_offset*world.tick_lag) <= world.time)
+ var/datum/timedevent/head = bucket_list[practical_offset]
if (!timer || !head || timer == head)
head = bucket_list[practical_offset]
- if (!head)
- practical_offset++
- if (MC_TICK_CHECK)
- break
- continue
timer = head
- do
+ while (timer)
var/datum/callback/callBack = timer.callBack
if (!callBack)
- qdel(timer)
bucket_resolution = null //force bucket recreation
CRASH("Invalid timer: [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
@@ -113,15 +132,68 @@ SUBSYSTEM_DEF(timer)
callBack.InvokeAsync()
last_invoke_tick = world.time
- timer = timer.next
-
if (MC_TICK_CHECK)
return
- while (timer && timer != head)
- timer = null
+
+ timer = timer.next
+ if (timer == head)
+ break
+
+
bucket_list[practical_offset++] = null
- if (MC_TICK_CHECK)
- return
+
+ //we freed up a bucket, lets see if anything in second_queue needs to be shifted to that bucket.
+ var/i = 0
+ var/L = length(second_queue)
+ for (i in 1 to L)
+ timer = second_queue[i]
+ if (timer.timeToRun >= TIMER_MAX)
+ i--
+ break
+
+ if (timer.timeToRun < head_offset)
+ bucket_resolution = null //force bucket recreation
+ CRASH("[i] Invalid timer state: Timer in long run queue with a time to run less then head_offset. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
+
+ if (timer.callBack && !timer.spent)
+ timer.callBack.InvokeAsync()
+ spent += timer
+ bucket_count++
+ else if(!QDELETED(timer))
+ qdel(timer)
+ continue
+
+ if (timer.timeToRun < head_offset + TICKS2DS(practical_offset))
+ bucket_resolution = null //force bucket recreation
+ CRASH("[i] Invalid timer state: Timer in long run queue that would require a backtrack to transfer to short run queue. [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
+ if (timer.callBack && !timer.spent)
+ timer.callBack.InvokeAsync()
+ spent += timer
+ bucket_count++
+ else if(!QDELETED(timer))
+ qdel(timer)
+ continue
+
+ bucket_count++
+ var/bucket_pos = max(1, BUCKET_POS(timer))
+
+ var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
+ if (!bucket_head)
+ bucket_list[bucket_pos] = timer
+ timer.next = null
+ timer.prev = null
+ continue
+
+ if (!bucket_head.prev)
+ bucket_head.prev = bucket_head
+ timer.next = bucket_head
+ timer.prev = bucket_head.prev
+ timer.next.prev = timer
+ timer.prev.next = timer
+ if (i)
+ second_queue.Cut(1, i+1)
+
+ timer = null
bucket_count -= length(spent)
@@ -141,7 +213,7 @@ SUBSYSTEM_DEF(timer)
if(!TE.callBack)
. += ", NO CALLBACK"
-/datum/controller/subsystem/timer/proc/shift_buckets()
+/datum/controller/subsystem/timer/proc/reset_buckets()
var/list/bucket_list = src.bucket_list
var/list/alltimers = list()
//collect the timers currently in the bucket
@@ -162,7 +234,7 @@ SUBSYSTEM_DEF(timer)
head_offset = world.time
bucket_resolution = world.tick_lag
- alltimers += processing
+ alltimers += second_queue
if (!length(alltimers))
return
@@ -173,22 +245,26 @@ SUBSYSTEM_DEF(timer)
if (head.timeToRun < head_offset)
head_offset = head.timeToRun
- var/list/timers_to_remove = list()
-
- for (var/thing in alltimers)
- var/datum/timedevent/timer = thing
+ var/new_bucket_count
+ var/i = 1
+ for (i in 1 to length(alltimers))
+ var/datum/timedevent/timer = alltimers[1]
if (!timer)
- timers_to_remove += timer
continue
var/bucket_pos = BUCKET_POS(timer)
- if (bucket_pos > BUCKET_LEN)
+ if (timer.timeToRun >= TIMER_MAX)
+ i--
break
- timers_to_remove += timer //remove it from the big list once we are done
+
if (!timer.callBack || timer.spent)
+ WARNING("Invalid timer: [get_timer_debug_string(timer)] world.time: [world.time], head_offset: [head_offset], practical_offset: [practical_offset]")
+ if (timer.callBack)
+ qdel(timer)
continue
- bucket_count++
+
+ new_bucket_count++
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
if (!bucket_head)
bucket_list[bucket_pos] = timer
@@ -202,12 +278,14 @@ SUBSYSTEM_DEF(timer)
timer.prev = bucket_head.prev
timer.next.prev = timer
timer.prev.next = timer
-
- processing = (alltimers - timers_to_remove)
+ if (i)
+ alltimers.Cut(1, i+1)
+ second_queue = alltimers
+ bucket_count = new_bucket_count
/datum/controller/subsystem/timer/Recover()
- processing |= SStimer.processing
+ second_queue |= SStimer.second_queue
hashes |= SStimer.hashes
timer_id_dict |= SStimer.timer_id_dict
bucket_list |= SStimer.bucket_list
@@ -224,8 +302,6 @@ SUBSYSTEM_DEF(timer)
var/datum/timedevent/next
var/datum/timedevent/prev
- var/static/nextid = 1
-
/datum/timedevent/New(datum/callback/callBack, timeToRun, flags, hash)
id = TIMER_ID_NULL
src.callBack = callBack
@@ -235,56 +311,65 @@ SUBSYSTEM_DEF(timer)
if (flags & TIMER_UNIQUE)
SStimer.hashes[hash] = src
+
if (flags & TIMER_STOPPABLE)
- do
- if (nextid >= TIMER_ID_MAX)
- nextid = 1
- id = nextid++
- while(SStimer.timer_id_dict["timerid" + num2text(id, 8)])
- SStimer.timer_id_dict["timerid" + num2text(id, 8)] = src
+ id = GUID()
+ SStimer.timer_id_dict[id] = src
- name = "Timer: " + num2text(id, 8) + ", TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT")), ", ")], callBack: [REF(callBack)], callBack.object: [callBack.object][REF(callBack.object)]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])"
+ name = "Timer: [id] (\ref[src]), TTR: [timeToRun], Flags: [jointext(bitfield2list(flags, list("TIMER_UNIQUE", "TIMER_OVERRIDE", "TIMER_CLIENT_TIME", "TIMER_STOPPABLE", "TIMER_NO_HASH_WAIT")), ", ")], callBack: \ref[callBack], callBack.object: [callBack.object]\ref[callBack.object]([getcallingtype()]), callBack.delegate:[callBack.delegate]([callBack.arguments ? callBack.arguments.Join(", ") : ""])"
- if (spent)
- CRASH("HOLY JESUS. WHAT IS THAT? WHAT THE FUCK IS THAT?")
+ if ((timeToRun < world.time || timeToRun < SStimer.head_offset) && !(flags & TIMER_CLIENT_TIME))
+ CRASH("Invalid timer state: Timer created that would require a backtrack to run (addtimer would never let this happen): [SStimer.get_timer_debug_string(src)]")
if (callBack.object != GLOBAL_PROC)
LAZYADD(callBack.object.active_timers, src)
+
+ var/list/L
+
if (flags & TIMER_CLIENT_TIME)
- //sorted insert
- var/list/ctts = SStimer.clienttime_timers
- var/cttl = length(ctts)
+ L = SStimer.clienttime_timers
+ else if (timeToRun >= TIMER_MAX)
+ L = SStimer.second_queue
+
+
+ if (L)
+ //binary search sorted insert
+ var/cttl = length(L)
if(cttl)
- var/datum/timedevent/Last = ctts[cttl]
- if(Last.timeToRun >= timeToRun)
- ctts += src
- else
- for(var/i in cttl to 1 step -1)
- var/datum/timedevent/E = ctts[i]
- if(E.timeToRun <= timeToRun)
- ctts.Insert(i, src)
- break
+ var/left = 1
+ var/right = cttl
+ var/mid = (left+right) >> 1 //rounded divide by two for hedgehogs
+
+ var/datum/timedevent/item
+ while (left < right)
+ item = L[mid]
+ if (item.timeToRun <= timeToRun)
+ left = mid+1
+ else
+ right = mid
+ mid = (left+right) >> 1
+
+ item = L[mid]
+ mid = item.timeToRun > timeToRun ? mid : mid+1
+ L.Insert(mid, src)
+
else
- ctts += src
+ L += src
return
//get the list of buckets
var/list/bucket_list = SStimer.bucket_list
+
//calculate our place in the bucket list
var/bucket_pos = BUCKET_POS(src)
- //we are too far aways from needing to run to be in the bucket list, shift_buckets() will handle us.
- if (bucket_pos > length(bucket_list))
- SStimer.processing += src
- return
+
//get the bucket for our tick
var/datum/timedevent/bucket_head = bucket_list[bucket_pos]
SStimer.bucket_count++
//empty bucket, we will just add ourselves
if (!bucket_head)
bucket_list[bucket_pos] = src
- if (bucket_pos < SStimer.practical_offset)
- SStimer.practical_offset = bucket_pos
return
//other wise, lets do a simplified linked list add.
if (!bucket_head.prev)
@@ -296,10 +381,9 @@ SUBSYSTEM_DEF(timer)
/datum/timedevent/Destroy()
..()
- if (flags & TIMER_UNIQUE)
+ if (flags & TIMER_UNIQUE && hash)
SStimer.hashes -= hash
-
if (callBack && callBack.object && callBack.object != GLOBAL_PROC && callBack.object.active_timers)
callBack.object.active_timers -= src
UNSETEMPTY(callBack.object.active_timers)
@@ -307,13 +391,33 @@ SUBSYSTEM_DEF(timer)
callBack = null
if (flags & TIMER_STOPPABLE)
- SStimer.timer_id_dict -= "timerid" + num2text(id, 8)
+ SStimer.timer_id_dict -= id
if (flags & TIMER_CLIENT_TIME)
- SStimer.clienttime_timers -= src
+ if (!spent)
+ spent = world.time
+ SStimer.clienttime_timers -= src
return QDEL_HINT_IWILLGC
if (!spent)
+ spent = world.time
+ var/bucketpos = BUCKET_POS(src)
+ var/datum/timedevent/buckethead
+ var/list/bucket_list = SStimer.bucket_list
+ if (bucketpos > 0)
+ buckethead = bucket_list[bucketpos]
+
+ if (buckethead == src)
+ bucket_list[bucketpos] = next
+ SStimer.bucket_count--
+ else if (timeToRun < TIMER_MAX || next || prev)
+ SStimer.bucket_count--
+ else
+ var/l = length(SStimer.second_queue)
+ SStimer.second_queue -= src
+ if (l == length(SStimer.second_queue))
+ SStimer.bucket_count--
+
if (prev == next && next)
next.prev = null
prev.next = null
@@ -322,19 +426,6 @@ SUBSYSTEM_DEF(timer)
prev.next = next
if (next)
next.prev = prev
-
- var/bucketpos = BUCKET_POS(src)
- var/datum/timedevent/buckethead
- var/list/bucket_list = SStimer.bucket_list
-
- if (bucketpos > 0 && bucketpos <= length(bucket_list))
- buckethead = bucket_list[bucketpos]
- SStimer.bucket_count--
- else
- SStimer.processing -= src
-
- if (buckethead == src)
- bucket_list[bucketpos] = next
else
if (prev && prev.next == src)
prev.next = next
@@ -351,9 +442,16 @@ SUBSYSTEM_DEF(timer)
else
. = "[callBack.object.type]"
-/proc/addtimer(datum/callback/callback, wait, flags)
+/proc/addtimer(datum/callback/callback, wait = 0, flags = 0)
if (!callback)
- return
+ CRASH("addtimer called without a callback")
+
+ if (wait < 0)
+ stack_trace("Addtimer called with a negitive wait. Converting to 0")
+
+ //alot of things add short timers on themselves in their destroy, we ignore those cases
+ if (wait >= 1 && callback && callback.object && callback.object != GLOBAL_PROC && QDELETED(callback.object))
+ stack_trace("Add timer called with a callback assigned to a qdeleted object")
wait = max(wait, 0)
@@ -374,11 +472,10 @@ SUBSYSTEM_DEF(timer)
var/datum/timedevent/hash_timer = SStimer.hashes[hash]
if(hash_timer)
if (hash_timer.spent) //it's pending deletion, pretend it doesn't exist.
- hash_timer.hash = null
- SStimer.hashes -= hash
+ hash_timer.hash = null //but keep it from accidentally deleting us
else
-
if (flags & TIMER_OVERRIDE)
+ hash_timer.hash = null //no need having it delete it's hash if we are going to replace it
qdel(hash_timer)
else
if (hash_timer.flags & TIMER_STOPPABLE)
@@ -403,7 +500,7 @@ SUBSYSTEM_DEF(timer)
qdel(id)
return TRUE
//id is string
- var/datum/timedevent/timer = SStimer.timer_id_dict["timerid[id]"]
+ var/datum/timedevent/timer = SStimer.timer_id_dict[id]
if (timer && !timer.spent)
qdel(timer)
return TRUE
@@ -412,3 +509,5 @@ SUBSYSTEM_DEF(timer)
#undef BUCKET_LEN
#undef BUCKET_POS
+#undef TIMER_MAX
+#undef TIMER_ID_MAX
\ No newline at end of file
diff --git a/code/controllers/subsystem/title.dm b/code/controllers/subsystem/title.dm
index 4f1dbc37c7..a0bcb5feec 100644
--- a/code/controllers/subsystem/title.dm
+++ b/code/controllers/subsystem/title.dm
@@ -36,7 +36,7 @@ SUBSYSTEM_DEF(title)
break
file_path = "config/title_screens/images/[pick(title_screens)]"
-
+
icon = new(fcopy_rsc(file_path))
if(splash_turf)
diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm
index 37811c183f..acb873dd5b 100644
--- a/code/controllers/subsystem/vote.dm
+++ b/code/controllers/subsystem/vote.dm
@@ -206,6 +206,7 @@ SUBSYSTEM_DEF(vote)
var/datum/action/vote/V = new
if(question)
V.name = "Vote: [question]"
+ C.player_details.player_actions += V
V.Grant(C.mob)
generated_actions += V
return 1
@@ -299,6 +300,7 @@ SUBSYSTEM_DEF(vote)
for(var/v in generated_actions)
var/datum/action/vote/V = v
if(!QDELETED(V))
+ V.remove_from_client()
V.Remove(V.owner)
generated_actions = list()
@@ -318,7 +320,16 @@ SUBSYSTEM_DEF(vote)
/datum/action/vote/Trigger()
if(owner)
owner.vote()
+ remove_from_client()
Remove(owner)
/datum/action/vote/IsAvailable()
return 1
+
+/datum/action/vote/proc/remove_from_client()
+ if(owner.client)
+ owner.client.player_details.player_actions -= src
+ else if(owner.ckey)
+ var/datum/player_details/P = GLOB.player_details[owner.ckey]
+ if(P)
+ P.player_actions -= src
\ No newline at end of file
diff --git a/code/datums/action.dm b/code/datums/action.dm
index f941a00a54..f14945fa24 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -170,14 +170,15 @@
..(current_button)
else if(target && current_button.appearance_cache != target.appearance) //replace with /ref comparison if this is not valid.
var/obj/item/I = target
- current_button.appearance_cache = I.appearance
var/old_layer = I.layer
var/old_plane = I.plane
I.layer = FLOAT_LAYER //AAAH
I.plane = FLOAT_PLANE //^ what that guy said
- current_button.overlays = list(I)
+ current_button.cut_overlays()
+ current_button.add_overlay(I)
I.layer = old_layer
I.plane = old_plane
+ current_button.appearance_cache = I.appearance
/datum/action/item_action/toggle_light
name = "Toggle Light"
diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm
index 8d86507271..c12a08a792 100644
--- a/code/datums/ai_laws.dm
+++ b/code/datums/ai_laws.dm
@@ -373,32 +373,9 @@
ion = list()
/datum/ai_laws/proc/show_laws(who)
-
- if (devillaws && devillaws.len) //Yes, devil laws go in FRONT of zeroth laws, as the devil must still obey it's ban/obligation.
- for(var/i in devillaws)
- to_chat(who, "666. [i]")
-
- if (zeroth)
- to_chat(who, "0. [zeroth]")
-
- for (var/index = 1, index <= ion.len, index++)
- var/law = ion[index]
- var/num = ionnum()
- to_chat(who, "[num]. [law]")
-
- var/number = 1
- for (var/index = 1, index <= inherent.len, index++)
- var/law = inherent[index]
-
- if (length(law) > 0)
- to_chat(who, "[number]. [law]")
- number++
-
- for (var/index = 1, index <= supplied.len, index++)
- var/law = supplied[index]
- if (length(law) > 0)
- to_chat(who, "[number]. [law]")
- number++
+ var/list/printable_laws = get_law_list(include_zeroth = TRUE)
+ for(var/law in printable_laws)
+ to_chat(who,law)
/datum/ai_laws/proc/clear_zeroth_law(force) //only removes zeroth from antag ai if force is 1
if(force)
diff --git a/code/datums/antagonists/abductor.dm b/code/datums/antagonists/abductor.dm
index 8d13c48e7c..3b8935d9fa 100644
--- a/code/datums/antagonists/abductor.dm
+++ b/code/datums/antagonists/abductor.dm
@@ -1,5 +1,6 @@
/datum/antagonist/abductor
name = "Abductor"
+ roundend_category = "abductors"
job_rank = ROLE_ABDUCTOR
var/datum/objective_team/abductor_team/team
var/sub_role
@@ -70,3 +71,65 @@
var/mob/living/carbon/human/H = owner.current
var/datum/species/abductor/A = H.dna.species
A.scientist = TRUE
+
+
+/datum/objective_team/abductor_team
+ member_name = "abductor"
+ var/team_number
+ var/list/datum/mind/abductees = list()
+
+/datum/objective_team/abductor_team/is_solo()
+ return FALSE
+
+/datum/objective_team/abductor_team/proc/add_objective(datum/objective/O)
+ O.team = src
+ O.update_explanation_text()
+ objectives += O
+
+/datum/objective_team/abductor_team/roundend_report()
+ var/list/result = list()
+
+ var/won = TRUE
+ for(var/datum/objective/O in objectives)
+ if(!O.check_completion())
+ won = FALSE
+ if(won)
+ result += "[name] team fulfilled its mission!"
+ else
+ result += "[name] team failed its mission."
+
+ result += "The abductors of [name] were:"
+ for(var/datum/mind/abductor_mind in members)
+ result += printplayer(abductor_mind)
+ result += printobjectives(abductor_mind)
+
+ return result.Join(" ")
+
+
+/datum/antagonist/abductee
+ name = "Abductee"
+ roundend_category = "abductees"
+
+/datum/antagonist/abductee/on_gain()
+ give_objective()
+ . = ..()
+
+/datum/antagonist/abductee/greet()
+ to_chat(owner, "Your mind snaps!")
+ to_chat(owner, "You can't remember how you got here...")
+ owner.announce_objectives()
+
+/datum/antagonist/abductee/proc/give_objective()
+ var/mob/living/carbon/human/H = owner.current
+ if(istype(H))
+ H.gain_trauma_type(BRAIN_TRAUMA_MILD)
+ 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)
+ SSticker.mode.update_abductor_icons_added(mob_override ? mob_override.mind : owner)
+
+/datum/antagonist/abductee/remove_innate_effects(mob/living/mob_override)
+ SSticker.mode.update_abductor_icons_removed(mob_override ? mob_override.mind : owner)
\ No newline at end of file
diff --git a/code/datums/antagonists/antag_datum.dm b/code/datums/antagonists/antag_datum.dm
index 0a7b2aa22f..6b5a573eff 100644
--- a/code/datums/antagonists/antag_datum.dm
+++ b/code/datums/antagonists/antag_datum.dm
@@ -2,6 +2,8 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist
var/name = "Antagonist"
+ var/roundend_category = "other antagonists" //Section of roundend report, datums with same category will be displayed together, also default header for the section
+ var/show_in_roundend = TRUE //Set to false to hide the antagonists from roundend report
var/datum/mind/owner //Mind that owns this datum
var/silent = FALSE //Silent will prevent the gain/lose texts to show
var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum
@@ -9,6 +11,7 @@ GLOBAL_LIST_EMPTY(antagonists)
var/delete_on_mind_deletion = TRUE
var/job_rank
var/replace_banned = TRUE //Should replace jobbaned player with ghosts if granted.
+ var/list/objectives = list()
/datum/antagonist/New(datum/mind/new_owner)
GLOB.antagonists += src
@@ -96,9 +99,62 @@ GLOBAL_LIST_EMPTY(antagonists)
/datum/antagonist/proc/get_team()
return
+//Individual roundend report
+/datum/antagonist/proc/roundend_report()
+ var/list/report = list()
+
+ if(!owner)
+ CRASH("antagonist datum without owner")
+
+ report += printplayer(owner)
+
+ var/objectives_complete = TRUE
+ if(owner.objectives.len)
+ report += printobjectives(owner)
+ for(var/datum/objective/objective in owner.objectives)
+ if(!objective.check_completion())
+ objectives_complete = FALSE
+ break
+
+ if(owner.objectives.len == 0 || objectives_complete)
+ report += "The [name] was successful!"
+ else
+ report += "The [name] has failed!"
+
+ return report.Join(" ")
+
+//Displayed at the start of roundend_category section, default to roundend_category header
+/datum/antagonist/proc/roundend_report_header()
+ return "The [roundend_category] were: "
+
+//Displayed at the end of roundend_category section
+/datum/antagonist/proc/roundend_report_footer()
+ return
+
//Should probably be on ticker or job ss ?
/proc/get_antagonists(antag_type,specific = FALSE)
. = list()
for(var/datum/antagonist/A in GLOB.antagonists)
if(!specific && istype(A,antag_type) || specific && A.type == antag_type)
- . += A.owner
\ No newline at end of file
+ . += A.owner
+
+
+
+//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
+
+/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
\ No newline at end of file
diff --git a/code/datums/antagonists/blob.dm b/code/datums/antagonists/blob.dm
new file mode 100644
index 0000000000..5689e6a567
--- /dev/null
+++ b/code/datums/antagonists/blob.dm
@@ -0,0 +1,59 @@
+/datum/antagonist/blob
+ name = "Blob"
+ roundend_category = "blobs"
+ job_rank = ROLE_BLOB
+
+ var/datum/action/innate/blobpop/pop_action
+ var/starting_points_human_blob = 60
+ var/point_rate_human_blob = 2
+
+/datum/antagonist/blob/roundend_report()
+ var/basic_report = ..()
+ //Display max blobpoints for blebs that lost
+ if(isovermind(owner.current)) //embarrasing if not
+ var/mob/camera/blob/overmind = owner.current
+ if(!overmind.victory_in_progress) //if it won this doesn't really matter
+ var/point_report = " [owner.name] took over [overmind.max_count] tiles at the height of its growth."
+ return basic_report+point_report
+ return basic_report
+
+/datum/antagonist/blob/greet()
+ if(!isovermind(owner.current))
+ to_chat(owner,"You feel bloated.")
+
+/datum/antagonist/blob/on_gain()
+ create_objectives()
+ . = ..()
+
+/datum/antagonist/blob/proc/create_objectives()
+ 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))
+ if(!pop_action)
+ pop_action = new
+ pop_action.Grant(owner.current)
+
+/datum/objective/blob_takeover
+ explanation_text = "Reach critical mass!"
+
+//Non-overminds get this on blob antag assignment
+/datum/action/innate/blobpop
+ name = "Pop"
+ desc = "Unleash the blob"
+ icon_icon = 'icons/mob/blob.dmi'
+ button_icon_state = "blob"
+
+/datum/action/innate/blobpop/Activate()
+ var/mob/old_body = owner
+ var/datum/antagonist/blob/blobtag = owner.mind.has_antag_datum(/datum/antagonist/blob)
+ if(!blobtag)
+ Remove()
+ return
+ var/mob/camera/blob/B = new /mob/camera/blob(get_turf(old_body), blobtag.starting_points_human_blob)
+ owner.mind.transfer_to(B)
+ old_body.gib()
+ B.place_blob_core(blobtag.point_rate_human_blob, pop_override = TRUE)
\ No newline at end of file
diff --git a/code/datums/antagonists/brother.dm b/code/datums/antagonists/brother.dm
index 6458e6da09..dd3bdef9d2 100644
--- a/code/datums/antagonists/brother.dm
+++ b/code/datums/antagonists/brother.dm
@@ -55,3 +55,71 @@
/datum/antagonist/brother/proc/finalize_brother()
SSticker.mode.update_brother_icons_added(owner)
+
+
+/datum/objective_team/brother_team
+ name = "brotherhood"
+ member_name = "blood brother"
+ var/meeting_area
+
+/datum/objective_team/brother_team/is_solo()
+ return FALSE
+
+/datum/objective_team/brother_team/proc/update_name()
+ var/list/last_names = list()
+ for(var/datum/mind/M in members)
+ var/list/split_name = splittext(M.name," ")
+ last_names += split_name[split_name.len]
+
+ name = last_names.Join(" & ")
+
+/datum/objective_team/brother_team/roundend_report()
+ var/list/parts = list()
+
+ parts += "The blood brothers of [name] were:"
+ for(var/datum/mind/M in members)
+ parts += printplayer(M)
+ var/win = TRUE
+ var/objective_count = 1
+ for(var/datum/objective/objective in objectives)
+ if(objective.check_completion())
+ parts += "Objective #[objective_count]: [objective.explanation_text] Success!"
+ else
+ parts += "Objective #[objective_count]: [objective.explanation_text] Fail."
+ win = FALSE
+ objective_count++
+ if(win)
+ parts += "The blood brothers were successful!"
+ else
+ parts += "The blood brothers have failed!"
+
+ return "
[parts.Join(" ")]
"
+
+/datum/objective_team/brother_team/proc/add_objective(datum/objective/O, needs_target = FALSE)
+ O.team = src
+ if(needs_target)
+ O.find_target()
+ O.update_explanation_text()
+ objectives += O
+
+/datum/objective_team/brother_team/proc/forge_brother_objectives()
+ objectives = list()
+ var/is_hijacker = prob(10)
+ for(var/i = 1 to max(1, CONFIG_GET(number/brother_objectives_amount) + (members.len > 2) - is_hijacker))
+ forge_single_objective()
+ if(is_hijacker)
+ if(!locate(/datum/objective/hijack) in objectives)
+ add_objective(new/datum/objective/hijack)
+ else if(!locate(/datum/objective/escape) in objectives)
+ add_objective(new/datum/objective/escape)
+
+/datum/objective_team/brother_team/proc/forge_single_objective()
+ if(prob(50))
+ if(LAZYLEN(active_ais()) && prob(100/GLOB.joined_player_list.len))
+ add_objective(new/datum/objective/destroy, TRUE)
+ else if(prob(30))
+ add_objective(new/datum/objective/maroon, TRUE)
+ else
+ add_objective(new/datum/objective/assassinate, TRUE)
+ else
+ add_objective(new/datum/objective/steal, TRUE)
\ No newline at end of file
diff --git a/code/datums/antagonists/changeling.dm b/code/datums/antagonists/changeling.dm
index e98bfed782..83886a98ad 100644
--- a/code/datums/antagonists/changeling.dm
+++ b/code/datums/antagonists/changeling.dm
@@ -4,11 +4,11 @@
/datum/antagonist/changeling
name = "Changeling"
+ roundend_category = "changelings"
job_rank = ROLE_CHANGELING
var/you_are_greet = TRUE
var/give_objectives = TRUE
- var/list/objectives = list()
var/team_mode = FALSE //Should assign team objectives ?
//Changeling Stuff
@@ -78,7 +78,7 @@
. = ..()
/datum/antagonist/changeling/on_removal()
- remove_changeling_powers(FALSE)
+ remove_changeling_powers()
owner.objectives -= objectives
. = ..()
@@ -100,11 +100,11 @@
chem_recharge_slowdown = initial(chem_recharge_slowdown)
mimicing = ""
-/datum/antagonist/changeling/proc/remove_changeling_powers(keep_free_powers=0)
+/datum/antagonist/changeling/proc/remove_changeling_powers()
if(ishuman(owner.current) || ismonkey(owner.current))
reset_properties()
for(var/obj/effect/proc_holder/changeling/p in purchasedpowers)
- if((p.dna_cost == 0 && keep_free_powers) || p.always_keep)
+ if(p.always_keep)
continue
purchasedpowers -= p
p.on_refund(owner.current)
@@ -116,13 +116,13 @@
/datum/antagonist/changeling/proc/reset_powers()
if(purchasedpowers)
- remove_changeling_powers(TRUE)
- //Purchase free powers.
+ remove_changeling_powers()
+ //Repurchase free powers.
for(var/path in all_powers)
var/obj/effect/proc_holder/changeling/S = new path()
if(!S.dna_cost)
if(!has_sting(S))
- purchasedpowers+=S
+ purchasedpowers += S
S.on_purchase(owner.current,TRUE)
/datum/antagonist/changeling/proc/has_sting(obj/effect/proc_holder/changeling/power)
@@ -478,4 +478,35 @@
/datum/antagonist/changeling/xenobio
name = "Xenobio Changeling"
give_objectives = FALSE
+ show_in_roundend = FALSE //These are here for admin tracking purposes only
you_are_greet = FALSE
+
+/datum/antagonist/changeling/roundend_report()
+ var/list/parts = list()
+
+ var/changelingwin = 1
+ if(!owner.current)
+ changelingwin = 0
+
+ parts += printplayer(owner)
+
+ //Removed sanity if(changeling) because we -want- a runtime to inform us that the changelings list is incorrect and needs to be fixed.
+ parts += "Changeling ID: [changelingID]."
+ parts += "Genomes Extracted: [absorbedcount]"
+ parts += " "
+ if(objectives.len)
+ var/count = 1
+ for(var/datum/objective/objective in objectives)
+ if(objective.check_completion())
+ parts += "Objective #[count]: [objective.explanation_text] Success!"
+ else
+ parts += "Objective #[count]: [objective.explanation_text] Fail."
+ changelingwin = 0
+ count++
+
+ if(changelingwin)
+ parts += "The changeling was successful!"
+ else
+ parts += "The changeling has failed."
+
+ return parts.Join(" ")
\ No newline at end of file
diff --git a/code/datums/antagonists/clockcult.dm b/code/datums/antagonists/clockcult.dm
index 8cc1c9e9a7..5f99ccc5dd 100644
--- a/code/datums/antagonists/clockcult.dm
+++ b/code/datums/antagonists/clockcult.dm
@@ -1,8 +1,11 @@
//CLOCKCULT PROOF OF CONCEPT
/datum/antagonist/clockcult
name = "Clock Cultist"
- var/datum/action/innate/hierophant/hierophant_network = new()
+ roundend_category = "clock cultists"
job_rank = ROLE_SERVANT_OF_RATVAR
+ var/datum/action/innate/hierophant/hierophant_network = new()
+ var/datum/objective_team/clockcult/clock_team
+ var/make_team = TRUE //This should be only false for tutorial scarabs
/datum/antagonist/clockcult/silent
silent = TRUE
@@ -11,6 +14,22 @@
qdel(hierophant_network)
return ..()
+/datum/antagonist/clockcult/get_team()
+ return clock_team
+
+/datum/antagonist/clockcult/create_team(datum/objective_team/clockcult/new_team)
+ if(!new_team && make_team)
+ //TODO blah blah same as the others, allow multiple
+ for(var/datum/antagonist/clockcult/H in GLOB.antagonists)
+ if(H.clock_team)
+ clock_team = H.clock_team
+ return
+ clock_team = new /datum/objective_team/clockcult
+ return
+ if(make_team && !istype(new_team))
+ stack_trace("Wrong team type passed to [type] initialization.")
+ clock_team = new_team
+
/datum/antagonist/clockcult/can_be_owned(datum/mind/new_owner)
. = ..()
if(.)
@@ -164,3 +183,35 @@
if(iscyborg(owner.current))
to_chat(owner.current, "Despite your freedom from Ratvar's influence, you are still irreparably damaged and no longer possess certain functions such as AI linking.")
. = ..()
+
+
+/datum/objective_team/clockcult
+ name = "Clockcult"
+ var/list/objective
+ var/datum/mind/eminence
+
+/datum/objective_team/clockcult/proc/check_clockwork_victory()
+ if(GLOB.clockwork_gateway_activated)
+ return TRUE
+ return FALSE
+
+/datum/objective_team/clockcult/roundend_report()
+ var/list/parts = list()
+
+ if(check_clockwork_victory())
+ parts += "Ratvar's servants defended the Ark until its activation!"
+ else
+ parts += "The Ark was destroyed! Ratvar will rust away for all eternity!"
+ parts += " "
+ parts += "The servants' objective was: [CLOCKCULT_OBJECTIVE]."
+ parts += "Construction Value(CV) was: [GLOB.clockwork_construction_value]"
+ for(var/i in SSticker.scripture_states)
+ if(i != SCRIPTURE_DRIVER)
+ parts += "[i] scripture was: [SSticker.scripture_states[i] ? "UN":""]LOCKED"
+ if(eminence)
+ parts += "The Eminence was: [printplayer(eminence)]"
+ if(members.len)
+ parts += "Ratvar's servants were:"
+ parts += printplayerlist(members - eminence)
+
+ return "
[parts.Join(" ")]
"
\ No newline at end of file
diff --git a/code/datums/antagonists/cult.dm b/code/datums/antagonists/cult.dm
index c26b0f8108..bce9123fb3 100644
--- a/code/datums/antagonists/cult.dm
+++ b/code/datums/antagonists/cult.dm
@@ -2,84 +2,103 @@
/datum/antagonist/cult
name = "Cultist"
+ roundend_category = "cultists"
var/datum/action/innate/cult/comm/communion = new
var/datum/action/innate/cult/mastervote/vote = new
job_rank = ROLE_CULTIST
var/ignore_implant = FALSE
+ var/give_equipment = FALSE
+
+ var/datum/objective_team/cult/cult_team
+
+/datum/antagonist/cult/get_team()
+ return cult_team
+
+/datum/antagonist/cult/create_team(datum/objective_team/cult/new_team)
+ if(!new_team)
+ //todo remove this and allow admin buttons to create more than one cult
+ for(var/datum/antagonist/cult/H in GLOB.antagonists)
+ if(H.cult_team)
+ cult_team = H.cult_team
+ return
+ cult_team = new /datum/objective_team/cult
+ cult_team.setup_objectives()
+ return
+ if(!istype(new_team))
+ stack_trace("Wrong team type passed to [type] initialization.")
+ cult_team = new_team
+
+/datum/antagonist/cult/proc/add_objectives()
+ objectives |= cult_team.objectives
+ owner.objectives |= objectives
+
+/datum/antagonist/cult/proc/remove_objectives()
+ owner.objectives -= objectives
/datum/antagonist/cult/Destroy()
QDEL_NULL(communion)
QDEL_NULL(vote)
return ..()
-/datum/antagonist/cult/proc/add_objectives()
- var/list/target_candidates = list()
- for(var/mob/living/carbon/human/player in GLOB.player_list)
- if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && !is_convertable_to_cult(player) && (player != owner) && player.stat != DEAD)
- target_candidates += player.mind
- if(target_candidates.len == 0)
- message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.")
- for(var/mob/living/carbon/human/player in GLOB.player_list)
- if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && (player != owner) && player.stat != DEAD)
- target_candidates += player.mind
- listclearnulls(target_candidates)
- if(LAZYLEN(target_candidates))
- GLOB.sac_mind = pick(target_candidates)
- if(!GLOB.sac_mind)
- message_admins("Cult Sacrifice: ERROR - Null target chosen!")
- else
- var/datum/job/sacjob = SSjob.GetJob(GLOB.sac_mind.assigned_role)
- var/datum/preferences/sacface = GLOB.sac_mind.current.client.prefs
- var/icon/reshape = get_flat_human_icon(null, sacjob, sacface)
- reshape.Shift(SOUTH, 4)
- reshape.Shift(EAST, 1)
- reshape.Crop(7,4,26,31)
- reshape.Crop(-5,-3,26,30)
- GLOB.sac_image = reshape
- else
- message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!")
- GLOB.sac_complete = TRUE
- SSticker.mode.cult_objectives += "sacrifice"
- if(!GLOB.summon_spots.len)
- while(GLOB.summon_spots.len < SUMMON_POSSIBILITIES)
- var/area/summon = pick(GLOB.sortedAreas - GLOB.summon_spots)
- if(summon && (summon.z in GLOB.station_z_levels) && summon.valid_territory)
- GLOB.summon_spots += summon
- SSticker.mode.cult_objectives += "eldergod"
-
-/datum/antagonist/cult/proc/cult_memorization(datum/mind/cult_mind)
- var/mob/living/current = cult_mind.current
- for(var/obj_count = 1,obj_count <= SSticker.mode.cult_objectives.len,obj_count++)
- var/explanation
- switch(SSticker.mode.cult_objectives[obj_count])
- if("sacrifice")
- if(GLOB.sac_mind)
- explanation = "Sacrifice [GLOB.sac_mind], the [GLOB.sac_mind.assigned_role] via invoking a Sacrifice rune with them on it and three acolytes around it."
- else
- explanation = "The veil has already been weakened here, proceed to the final objective."
- GLOB.sac_complete = TRUE
- if("eldergod")
- explanation = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie'. The summoning can only be accomplished in [english_list(GLOB.summon_spots)] - where the veil is weak enough for the ritual to begin."
- if(!silent)
- to_chat(current, "Objective #[obj_count]: [explanation]")
- cult_mind.memory += "Objective #[obj_count]: [explanation] "
-
/datum/antagonist/cult/can_be_owned(datum/mind/new_owner)
. = ..()
if(. && !ignore_implant)
- . = is_convertable_to_cult(new_owner.current)
+ . = is_convertable_to_cult(new_owner.current,cult_team)
+
+/datum/antagonist/cult/greet()
+ to_chat(owner, "You are a member of the cult!")
+ owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/bloodcult.ogg', 100, FALSE, pressure_affected = FALSE)//subject to change
+ owner.announce_objectives()
/datum/antagonist/cult/on_gain()
. = ..()
var/mob/living/current = owner.current
- if(!LAZYLEN(SSticker.mode.cult_objectives))
- add_objectives()
+ add_objectives()
+ if(give_equipment)
+ equip_cultist()
SSticker.mode.cult += owner // Only add after they've been given objectives
- cult_memorization(owner)
SSticker.mode.update_cult_icons_added(owner)
current.log_message("Has been converted to the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG)
- if(GLOB.blood_target && GLOB.blood_target_image && current.client)
- current.client.images += GLOB.blood_target_image
+
+ if(cult_team.blood_target && cult_team.blood_target_image && current.client)
+ current.client.images += cult_team.blood_target_image
+
+
+/datum/antagonist/cult/proc/equip_cultist(tome=FALSE)
+ var/mob/living/carbon/H = owner.current
+ if(!istype(H))
+ return
+ if (owner.assigned_role == "Clown")
+ to_chat(owner, "Your training has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
+ H.dna.remove_mutation(CLOWNMUT)
+
+ if(tome)
+ . += cult_give_item(/obj/item/tome, H)
+ else
+ . += cult_give_item(/obj/item/paper/talisman/supply, H)
+ to_chat(owner, "These will help you start the cult on this station. Use them well, and remember - you are not the only one.")
+
+
+/datum/antagonist/cult/proc/cult_give_item(obj/item/item_path, mob/living/carbon/human/mob)
+ var/list/slots = list(
+ "backpack" = slot_in_backpack,
+ "left pocket" = slot_l_store,
+ "right pocket" = slot_r_store
+ )
+
+ var/T = new item_path(mob)
+ var/item_name = initial(item_path.name)
+ var/where = mob.equip_in_one_of_slots(T, slots)
+ if(!where)
+ to_chat(mob, "Unfortunately, you weren't able to get a [item_name]. This is very bad and you should adminhelp immediately (press F1).")
+ return 0
+ else
+ to_chat(mob, "You have a [item_name] in your [where].")
+ if(where == "backpack")
+ var/obj/item/storage/B = mob.back
+ B.orient2hud(mob)
+ B.show_to(mob)
+ return 1
/datum/antagonist/cult/apply_innate_effects(mob/living/mob_override)
. = ..()
@@ -89,7 +108,7 @@
current.faction |= "cult"
current.grant_language(/datum/language/narsie)
current.verbs += /mob/living/proc/cult_help
- if(!GLOB.cult_mastered)
+ if(!cult_team.cult_mastered)
vote.Grant(current)
communion.Grant(current)
current.throw_alert("bloodsense", /obj/screen/alert/bloodsense)
@@ -107,6 +126,7 @@
current.clear_alert("bloodsense")
/datum/antagonist/cult/on_removal()
+ remove_objectives()
owner.wipe_memory()
SSticker.mode.cult -= owner
SSticker.mode.update_cult_icons_removed(owner)
@@ -114,8 +134,8 @@
owner.current.visible_message("[owner.current] looks like [owner.current.p_they()] just reverted to their old faith!", ignored_mob = owner.current)
to_chat(owner.current, "An unfamiliar white light flashes through your mind, cleansing the taint of the Geometer and all your memories as her servant.")
owner.current.log_message("Has renounced the cult of Nar'Sie!", INDIVIDUAL_ATTACK_LOG)
- if(GLOB.blood_target && GLOB.blood_target_image && owner.current.client)
- owner.current.client.images -= GLOB.blood_target_image
+ if(cult_team.blood_target && cult_team.blood_target_image && owner.current.client)
+ owner.current.client.images -= cult_team.blood_target_image
. = ..()
/datum/antagonist/cult/master
@@ -145,7 +165,7 @@
var/mob/living/current = owner.current
if(mob_override)
current = mob_override
- if(!GLOB.reckoning_complete)
+ if(!cult_team.reckoning_complete)
reckoning.Grant(current)
bloodmark.Grant(current)
throwing.Grant(current)
@@ -162,3 +182,118 @@
throwing.Remove(current)
current.update_action_buttons_icon()
current.remove_status_effect(/datum/status_effect/cult_master)
+
+/datum/objective_team/cult
+ name = "Cult"
+
+ var/blood_target
+ var/image/blood_target_image
+ var/blood_target_reset_timer
+
+ var/cult_vote_called = FALSE
+ var/cult_mastered = FALSE
+ var/reckoning_complete = FALSE
+
+
+/datum/objective_team/cult/proc/setup_objectives()
+ //SAC OBJECTIVE , todo: move this to objective internals
+ var/list/target_candidates = list()
+ var/datum/objective/sacrifice/sac_objective = new
+ sac_objective.team = src
+
+ for(var/mob/living/carbon/human/player in GLOB.player_list)
+ if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && !is_convertable_to_cult(player) && player.stat != DEAD)
+ target_candidates += player.mind
+
+ if(target_candidates.len == 0)
+ message_admins("Cult Sacrifice: Could not find unconvertable target, checking for convertable target.")
+ for(var/mob/living/carbon/human/player in GLOB.player_list)
+ if(player.mind && !player.mind.has_antag_datum(ANTAG_DATUM_CULT) && player.stat != DEAD)
+ target_candidates += player.mind
+ listclearnulls(target_candidates)
+ if(LAZYLEN(target_candidates))
+ sac_objective.target = pick(target_candidates)
+ sac_objective.update_explanation_text()
+
+ var/datum/job/sacjob = SSjob.GetJob(sac_objective.target.assigned_role)
+ var/datum/preferences/sacface = sac_objective.target.current.client.prefs
+ var/icon/reshape = get_flat_human_icon(null, sacjob, sacface)
+ reshape.Shift(SOUTH, 4)
+ reshape.Shift(EAST, 1)
+ reshape.Crop(7,4,26,31)
+ reshape.Crop(-5,-3,26,30)
+ sac_objective.sac_image = reshape
+
+ objectives += sac_objective
+ else
+ message_admins("Cult Sacrifice: Could not find unconvertable or convertable target. WELP!")
+
+
+ //SUMMON OBJECTIVE
+
+ var/datum/objective/eldergod/summon_objective = new()
+ summon_objective.team = src
+ objectives += summon_objective
+
+/datum/objective/sacrifice
+ var/sacced = FALSE
+ var/sac_image
+
+/datum/objective/sacrifice/check_completion()
+ return sacced || completed
+
+/datum/objective/sacrifice/update_explanation_text()
+ if(target && !sacced)
+ explanation_text = "Sacrifice [target], the [target.assigned_role] via invoking a Sacrifice rune with them on it and three acolytes around it."
+ else
+ explanation_text = "The veil has already been weakened here, proceed to the final objective."
+
+/datum/objective/eldergod
+ var/summoned = FALSE
+ var/list/summon_spots = list()
+
+/datum/objective/eldergod/New()
+ ..()
+ var/sanity = 0
+ while(summon_spots.len < SUMMON_POSSIBILITIES && sanity < 100)
+ var/area/summon = pick(GLOB.sortedAreas - summon_spots)
+ if(summon && (summon.z in GLOB.station_z_levels) && summon.valid_territory)
+ summon_spots += summon
+ sanity++
+ update_explanation_text()
+
+/datum/objective/eldergod/update_explanation_text()
+ explanation_text = "Summon Nar-Sie by invoking the rune 'Summon Nar-Sie'. The summoning can only be accomplished in [english_list(summon_spots)] - where the veil is weak enough for the ritual to begin."
+
+/datum/objective/eldergod/check_completion()
+ return summoned || completed
+
+/datum/objective_team/cult/proc/check_cult_victory()
+ for(var/datum/objective/O in objectives)
+ if(!O.check_completion())
+ return FALSE
+ return TRUE
+
+/datum/objective_team/cult/roundend_report()
+ var/list/parts = list()
+
+ if(check_cult_victory())
+ parts += "The cult has succeeded! Nar-sie has snuffed out another torch in the void!"
+ else
+ parts += "The staff managed to stop the cult! Dark words and heresy are no match for Nanotrasen's finest!"
+
+ if(objectives.len)
+ parts += "The cultists' objectives were:"
+ var/count = 1
+ for(var/datum/objective/objective in objectives)
+ if(objective.check_completion())
+ parts += "Objective #[count]: [objective.explanation_text] Success!"
+ else
+ parts += "Objective #[count]: [objective.explanation_text] Fail."
+ count++
+
+ if(members.len)
+ parts += "The cultists were:"
+ parts += printplayerlist(members)
+
+ return "
[parts.Join(" ")]
"
\ No newline at end of file
diff --git a/code/datums/antagonists/datum_traitor.dm b/code/datums/antagonists/datum_traitor.dm
index d386c79c25..80487f69e8 100644
--- a/code/datums/antagonists/datum_traitor.dm
+++ b/code/datums/antagonists/datum_traitor.dm
@@ -1,5 +1,6 @@
/datum/antagonist/traitor
name = "Traitor"
+ roundend_category = "traitors"
job_rank = ROLE_TRAITOR
var/should_specialise = FALSE //do we split into AI and human, set to true on inital assignment only
var/ai_datum = ANTAG_DATUM_TRAITOR_AI
@@ -8,7 +9,6 @@
var/employer = "The Syndicate"
var/give_objectives = TRUE
var/should_give_codewords = TRUE
- var/list/objectives_given = list()
/datum/antagonist/traitor/human
var/should_equip = TRUE
@@ -52,9 +52,9 @@
if(should_specialise)
return ..()//we never did any of this anyway
SSticker.mode.traitors -= owner
- for(var/O in objectives_given)
+ for(var/O in objectives)
owner.objectives -= O
- objectives_given = list()
+ objectives = list()
if(!silent && owner.current)
to_chat(owner.current," You are no longer the [special_role]! ")
owner.special_role = null
@@ -71,11 +71,11 @@
/datum/antagonist/traitor/proc/add_objective(var/datum/objective/O)
owner.objectives += O
- objectives_given += O
+ objectives += O
/datum/antagonist/traitor/proc/remove_objective(var/datum/objective/O)
owner.objectives -= O
- objectives_given -= O
+ objectives -= O
/datum/antagonist/traitor/proc/forge_traitor_objectives()
return
@@ -127,6 +127,7 @@
if(prob(30))
objective_count += forge_single_objective()
+
for(var/i = objective_count, i < CONFIG_GET(number/traitor_objectives_amount), i++)
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = owner
@@ -152,11 +153,6 @@
maroon_objective.owner = owner
maroon_objective.find_target()
add_objective(maroon_objective)
- else if(prob(50))
- var/datum/objective/assassinate/late/late_objective = new
- late_objective.owner = owner
- late_objective.find_target()
- add_objective(late_objective)
else
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = owner
@@ -294,3 +290,53 @@
where = "In your [equipped_slot]"
to_chat(mob, "
[where] is a folder containing secret documents that another Syndicate group wants. We have set up a meeting with one of their agents on station to make an exchange. Exercise extreme caution as they cannot be trusted and may be hostile. ")
+//TODO Collate
+/datum/antagonist/traitor/roundend_report()
+ var/list/result = list()
+
+ var/traitorwin = TRUE
+
+ result += printplayer(owner)
+
+ var/TC_uses = 0
+ var/uplink_true = FALSE
+ var/purchases = ""
+ for(var/datum/component/uplink/H in GLOB.uplinks)
+ if(H.owner && H.owner == owner.key)
+ TC_uses += H.purchase_log.total_spent
+ uplink_true = TRUE
+ purchases += H.purchase_log.generate_render(FALSE)
+
+ var/objectives_text = ""
+ if(objectives.len)//If the traitor had no objectives, don't need to process this.
+ var/count = 1
+ for(var/datum/objective/objective in objectives)
+ if(objective.check_completion())
+ objectives_text += " Objective #[count]: [objective.explanation_text] Success!"
+ else
+ objectives_text += " Objective #[count]: [objective.explanation_text] Fail."
+ traitorwin = FALSE
+ count++
+
+ if(uplink_true)
+ var/uplink_text = "(used [TC_uses] TC) [purchases]"
+ if(TC_uses==0 && traitorwin)
+ var/static/icon/badass = icon('icons/badass.dmi', "badass")
+ uplink_text += "[icon2html(badass, world)]"
+ result += uplink_text
+
+ result += objectives_text
+
+ var/special_role_text = lowertext(name)
+
+ if(traitorwin)
+ result += "The [special_role_text] was successful!"
+ else
+ result += "The [special_role_text] has failed!"
+ SEND_SOUND(owner.current, 'sound/ambience/ambifailure.ogg')
+
+ return result.Join(" ")
+
+/datum/antagonist/traitor/roundend_report_footer()
+ return " The code phrases were:[GLOB.syndicate_code_phrase] \
+ The code responses were:[GLOB.syndicate_code_response] "
\ No newline at end of file
diff --git a/code/datums/antagonists/devil.dm b/code/datums/antagonists/devil.dm
index 416a8f3752..97e0d8c18a 100644
--- a/code/datums/antagonists/devil.dm
+++ b/code/datums/antagonists/devil.dm
@@ -86,6 +86,7 @@ GLOBAL_LIST_INIT(devil_syllable, list("hal", "ve", "odr", "neit", "ci", "quon",
GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master", ", the Lord of all things", ", Jr."))
/datum/antagonist/devil
name = "Devil"
+ roundend_category = "devils"
job_rank = ROLE_DEVIL
//Don't delete upon mind destruction, otherwise soul re-selling will break.
delete_on_mind_deletion = FALSE
@@ -508,6 +509,35 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
owner.RemoveSpell(S)
.=..()
+/datum/antagonist/devil/proc/printdevilinfo()
+ var/list/parts = list()
+ parts += "The devil's true name is: [truename]"
+ parts += "The devil's bans were:"
+ parts += "[GLOB.TAB][GLOB.lawlorify[LORE][ban]]"
+ parts += "[GLOB.TAB][GLOB.lawlorify[LORE][bane]]"
+ parts += "[GLOB.TAB][GLOB.lawlorify[LORE][obligation]]"
+ parts += "[GLOB.TAB][GLOB.lawlorify[LORE][banish]]"
+ return parts.Join(" ")
+
+/datum/antagonist/devil/roundend_report()
+ var/list/parts = list()
+ parts += printplayer(owner)
+ parts += printdevilinfo()
+ parts += printobjectives(owner)
+ return parts.Join(" ")
+
+/datum/antagonist/devil/roundend_report_footer()
+ //sintouched go here for now as a hack , TODO proper antag datum for these
+ var/list/parts = list()
+ if(SSticker.mode.sintouched.len)
+ parts += "The sintouched were:"
+ var/list/sintouchedUnique = uniqueList(SSticker.mode.sintouched)
+ for(var/S in sintouchedUnique)
+ var/datum/mind/sintouched_mind = S
+ parts += printplayer(sintouched_mind)
+ parts += printobjectives(sintouched_mind)
+ return parts.Join(" ")
+
//A simple super light weight datum for the codex gigas.
/datum/fakeDevil
var/truename
diff --git a/code/datums/antagonists/ninja.dm b/code/datums/antagonists/ninja.dm
index ab4822dd79..8201cd879d 100644
--- a/code/datums/antagonists/ninja.dm
+++ b/code/datums/antagonists/ninja.dm
@@ -37,19 +37,20 @@
else if(M.assigned_role in GLOB.command_positions)
possible_targets[M] = 1 //good-guy
- var/list/objectives = list(1,2,3,4)
- while(owner.objectives.len < quantity)
- switch(pick_n_take(objectives))
+ var/list/possible_objectives = list(1,2,3,4)
+
+ while(objectives.len < quantity)
+ switch(pick_n_take(possible_objectives))
if(1) //research
var/datum/objective/download/O = new /datum/objective/download()
O.owner = owner
O.gen_amount_goal()
- owner.objectives += O
+ objectives += O
if(2) //steal
var/datum/objective/steal/special/O = new /datum/objective/steal/special()
O.owner = owner
- owner.objectives += O
+ objectives += O
if(3) //protect/kill
if(!possible_targets.len) continue
@@ -63,13 +64,13 @@
O.owner = owner
O.target = M
O.explanation_text = "Slay \the [M.current.real_name], the [M.assigned_role]."
- owner.objectives += O
+ objectives += O
else //protect
var/datum/objective/protect/O = new /datum/objective/protect()
O.owner = owner
O.target = M
O.explanation_text = "Protect \the [M.current.real_name], the [M.assigned_role], from harm."
- owner.objectives += O
+ objectives += O
if(4) //debrain/capture
if(!possible_targets.len) continue
var/selected = rand(1,possible_targets.len)
@@ -82,17 +83,17 @@
O.owner = owner
O.target = M
O.explanation_text = "Steal the brain of [M.current.real_name]."
- owner.objectives += O
+ objectives += O
else //capture
var/datum/objective/capture/O = new /datum/objective/capture()
O.owner = owner
O.gen_amount_goal()
- owner.objectives += O
+ objectives += O
else
break
var/datum/objective/O = new /datum/objective/survive()
O.owner = owner
- owner.objectives += O
+ owner.objectives |= objectives
/proc/remove_ninja(mob/living/L)
diff --git a/code/datums/antagonists/nukeop.dm b/code/datums/antagonists/nukeop.dm
new file mode 100644
index 0000000000..30d00ac3dd
--- /dev/null
+++ b/code/datums/antagonists/nukeop.dm
@@ -0,0 +1,322 @@
+#define NUKE_RESULT_FLUKE 0
+#define NUKE_RESULT_NUKE_WIN 1
+#define NUKE_RESULT_CREW_WIN 2
+#define NUKE_RESULT_CREW_WIN_SYNDIES_DEAD 3
+#define NUKE_RESULT_DISK_LOST 4
+#define NUKE_RESULT_DISK_STOLEN 5
+#define NUKE_RESULT_NOSURVIVORS 6
+#define NUKE_RESULT_WRONG_STATION 7
+#define NUKE_RESULT_WRONG_STATION_DEAD 8
+
+/datum/antagonist/nukeop
+ name = "Nuclear Operative"
+ roundend_category = "syndicate operatives" //just in case
+ job_rank = ROLE_OPERATIVE
+ var/datum/objective_team/nuclear/nuke_team
+ var/always_new_team = FALSE //If not assigned a team by default ops will try to join existing ones, set this to TRUE to always create new team.
+ var/send_to_spawnpoint = TRUE //Should the user be moved to default spawnpoint.
+ var/nukeop_outfit = /datum/outfit/syndicate
+
+/datum/antagonist/nukeop/proc/update_synd_icons_added(mob/living/M)
+ var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS]
+ opshud.join_hud(M)
+ set_antag_hud(M, "synd")
+
+/datum/antagonist/nukeop/proc/update_synd_icons_removed(mob/living/M)
+ var/datum/atom_hud/antag/opshud = GLOB.huds[ANTAG_HUD_OPS]
+ opshud.leave_hud(M)
+ set_antag_hud(M, null)
+
+/datum/antagonist/nukeop/apply_innate_effects(mob/living/mob_override)
+ var/mob/living/M = mob_override || owner.current
+ update_synd_icons_added(M)
+
+/datum/antagonist/nukeop/remove_innate_effects(mob/living/mob_override)
+ var/mob/living/M = mob_override || owner.current
+ update_synd_icons_removed(M)
+
+/datum/antagonist/nukeop/proc/equip_op()
+ if(!ishuman(owner.current))
+ return
+ var/mob/living/carbon/human/H = owner.current
+
+ H.set_species(/datum/species/human) //Plasamen burn up otherwise, and lizards are vulnerable to asimov AIs
+
+ H.equipOutfit(nukeop_outfit)
+ return TRUE
+
+/datum/antagonist/nukeop/greet()
+ owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ops.ogg',100,0)
+ to_chat(owner, "You are a [nuke_team ? nuke_team.syndicate_name : "syndicate"] agent!")
+ owner.announce_objectives()
+ return
+
+/datum/antagonist/nukeop/on_gain()
+ give_alias()
+ forge_objectives()
+ . = ..()
+ equip_op()
+ memorize_code()
+ if(send_to_spawnpoint)
+ move_to_spawnpoint()
+
+/datum/antagonist/nukeop/get_team()
+ return nuke_team
+
+/datum/antagonist/nukeop/proc/assign_nuke()
+ if(nuke_team && !nuke_team.tracked_nuke)
+ nuke_team.memorized_code = random_nukecode()
+ var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list
+ if(nuke)
+ nuke_team.tracked_nuke = nuke
+ if(nuke.r_code == "ADMIN")
+ nuke.r_code = nuke_team.memorized_code
+ else //Already set by admins/something else?
+ nuke_team.memorized_code = nuke.r_code
+ else
+ stack_trace("Syndicate nuke not found during nuke team creation.")
+ nuke_team.memorized_code = null
+
+/datum/antagonist/nukeop/proc/give_alias()
+ if(nuke_team && nuke_team.syndicate_name)
+ var/number = 1
+ number = nuke_team.members.Find(owner)
+ owner.current.real_name = "[nuke_team.syndicate_name] Operative #[number]"
+
+/datum/antagonist/nukeop/proc/memorize_code()
+ if(nuke_team && nuke_team.tracked_nuke && nuke_team.memorized_code)
+ owner.store_memory("[nuke_team.tracked_nuke] Code: [nuke_team.memorized_code]", 0, 0)
+ to_chat(owner, "The nuclear authorization code is: [nuke_team.memorized_code]")
+ else
+ to_chat(owner, "Unfortunately the syndicate was unable to provide you with nuclear authorization code.")
+
+/datum/antagonist/nukeop/proc/forge_objectives()
+ if(nuke_team)
+ owner.objectives |= nuke_team.objectives
+
+/datum/antagonist/nukeop/proc/move_to_spawnpoint()
+ var/team_number = 1
+ if(nuke_team)
+ team_number = nuke_team.members.Find(owner)
+ owner.current.forceMove(GLOB.nukeop_start[((team_number - 1) % GLOB.nukeop_start.len) + 1])
+
+/datum/antagonist/nukeop/leader/move_to_spawnpoint()
+ owner.current.forceMove(pick(GLOB.nukeop_leader_start))
+
+/datum/antagonist/nukeop/create_team(datum/objective_team/nuclear/new_team)
+ if(!new_team)
+ if(!always_new_team)
+ for(var/datum/antagonist/nukeop/N in GLOB.antagonists)
+ if(N.nuke_team)
+ nuke_team = N.nuke_team
+ return
+ nuke_team = new /datum/objective_team/nuclear
+ nuke_team.update_objectives()
+ assign_nuke() //This is bit ugly
+ return
+ if(!istype(new_team))
+ stack_trace("Wrong team type passed to [type] initialization.")
+ nuke_team = new_team
+
+/datum/antagonist/nukeop/leader
+ name = "Nuclear Operative Leader"
+ nukeop_outfit = /datum/outfit/syndicate/leader
+ always_new_team = TRUE
+ var/title
+
+/datum/antagonist/nukeop/leader/memorize_code()
+ ..()
+ if(nuke_team && nuke_team.memorized_code)
+ var/obj/item/paper/P = new
+ P.info = "The nuclear authorization code is: [nuke_team.memorized_code]"
+ P.name = "nuclear bomb code"
+ var/mob/living/carbon/human/H = owner.current
+ if(!istype(H))
+ P.forceMove(get_turf(H))
+ else
+ H.put_in_hands(P, TRUE)
+ H.update_icons()
+
+/datum/antagonist/nukeop/leader/give_alias()
+ title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")
+ if(nuke_team && nuke_team.syndicate_name)
+ owner.current.real_name = "[nuke_team.syndicate_name] [title]"
+ else
+ owner.current.real_name = "Syndicate [title]"
+
+/datum/antagonist/nukeop/leader/greet()
+ owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ops.ogg',100,0)
+ to_chat(owner, "You are the Syndicate [title] for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors.")
+ to_chat(owner, "If you feel you are not up to this task, give your ID to another operative.")
+ to_chat(owner, "In your hand you will find a special item capable of triggering a greater challenge for your team. Examine it carefully and consult with your fellow operatives before activating it.")
+ owner.announce_objectives()
+ addtimer(CALLBACK(src, .proc/nuketeam_name_assign), 1)
+
+
+/datum/antagonist/nukeop/leader/proc/nuketeam_name_assign()
+ if(!nuke_team)
+ return
+ nuke_team.rename_team(ask_name())
+
+/datum/objective_team/nuclear/proc/rename_team(new_name)
+ syndicate_name = new_name
+ name = "[syndicate_name] Team"
+ for(var/I in members)
+ var/datum/mind/synd_mind = I
+ var/mob/living/carbon/human/H = synd_mind.current
+ if(!istype(H))
+ continue
+ var/chosen_name = H.dna.species.random_name(H.gender,0,syndicate_name)
+ H.fully_replace_character_name(H.real_name,chosen_name)
+
+/datum/antagonist/nukeop/leader/proc/ask_name()
+ var/randomname = pick(GLOB.last_names)
+ var/newname = stripped_input(owner.current,"You are the nuke operative [title]. Please choose a last name for your family.", "Name change",randomname)
+ if (!newname)
+ newname = randomname
+ else
+ newname = reject_bad_name(newname)
+ if(!newname)
+ newname = randomname
+
+ return capitalize(newname)
+
+/datum/antagonist/nukeop/lone
+ name = "Lone Operative"
+ always_new_team = TRUE
+ send_to_spawnpoint = FALSE //Handled by event
+ nukeop_outfit = /datum/outfit/syndicate/full
+
+/datum/antagonist/nukeop/lone/assign_nuke()
+ if(nuke_team && !nuke_team.tracked_nuke)
+ nuke_team.memorized_code = random_nukecode()
+ var/obj/machinery/nuclearbomb/selfdestruct/nuke = locate() in GLOB.nuke_list
+ if(nuke)
+ nuke_team.tracked_nuke = nuke
+ if(nuke.r_code == "ADMIN")
+ nuke.r_code = nuke_team.memorized_code
+ else //Already set by admins/something else?
+ nuke_team.memorized_code = nuke.r_code
+ else
+ stack_trace("Station self destruct ot found during lone op team creation.")
+ nuke_team.memorized_code = null
+
+/datum/objective_team/nuclear
+ var/syndicate_name
+ var/obj/machinery/nuclearbomb/tracked_nuke
+ var/core_objective = /datum/objective/nuclear
+ var/memorized_code
+
+/datum/objective_team/nuclear/New()
+ ..()
+ syndicate_name = syndicate_name()
+
+/datum/objective_team/nuclear/proc/update_objectives()
+ if(core_objective)
+ var/datum/objective/O = new core_objective
+ O.team = src
+ objectives += O
+
+/datum/objective_team/nuclear/proc/disk_rescued()
+ for(var/obj/item/disk/nuclear/D in GLOB.poi_list)
+ if(!D.onCentCom())
+ return FALSE
+ return TRUE
+
+/datum/objective_team/nuclear/proc/operatives_dead()
+ for(var/I in members)
+ var/datum/mind/operative_mind = I
+ if(ishuman(operative_mind.current) && (operative_mind.current.stat != DEAD))
+ return FALSE
+ return TRUE
+
+/datum/objective_team/nuclear/proc/syndies_escaped()
+ var/obj/docking_port/mobile/S = SSshuttle.getShuttle("syndicate")
+ return (S && (S.z == ZLEVEL_CENTCOM || S.z == ZLEVEL_TRANSIT))
+
+/datum/objective_team/nuclear/proc/get_result()
+ var/evacuation = SSshuttle.emergency.mode == SHUTTLE_ENDGAME
+ var/disk_rescued = disk_rescued()
+ var/syndies_didnt_escape = !syndies_escaped()
+ var/station_was_nuked = SSticker.mode.station_was_nuked
+ var/nuke_off_station = SSticker.mode.nuke_off_station
+
+ if(nuke_off_station == NUKE_SYNDICATE_BASE)
+ return NUKE_RESULT_FLUKE
+ else if(!disk_rescued && station_was_nuked && !syndies_didnt_escape)
+ return NUKE_RESULT_NUKE_WIN
+ else if (!disk_rescued && station_was_nuked && syndies_didnt_escape)
+ return NUKE_RESULT_NOSURVIVORS
+ else if (!disk_rescued && !station_was_nuked && nuke_off_station && !syndies_didnt_escape)
+ return NUKE_RESULT_WRONG_STATION
+ else if (!disk_rescued && !station_was_nuked && nuke_off_station && syndies_didnt_escape)
+ return NUKE_RESULT_WRONG_STATION_DEAD
+ else if ((disk_rescued || evacuation) && operatives_dead())
+ return NUKE_RESULT_CREW_WIN_SYNDIES_DEAD
+ else if (disk_rescued)
+ return NUKE_RESULT_CREW_WIN
+ else if (!disk_rescued && operatives_dead())
+ return NUKE_RESULT_DISK_LOST
+ else if (!disk_rescued && evacuation)
+ return NUKE_RESULT_DISK_STOLEN
+ else
+ return //Undefined result
+
+/datum/objective_team/nuclear/roundend_report()
+ var/list/parts = list()
+ parts += "[syndicate_name] Operatives:"
+
+ switch(get_result())
+ if(NUKE_RESULT_FLUKE)
+ parts += "Humiliating Syndicate Defeat"
+ parts += "The crew of [station_name()] gave [syndicate_name] operatives back their bomb! The syndicate base was destroyed! Next time, don't lose the nuke!"
+ if(NUKE_RESULT_NUKE_WIN)
+ parts += "Syndicate Major Victory!"
+ parts += "[syndicate_name] operatives have destroyed [station_name()]!"
+ if(NUKE_RESULT_NOSURVIVORS)
+ parts += "Total Annihilation"
+ parts += "[syndicate_name] operatives destroyed [station_name()] but did not leave the area in time and got caught in the explosion. Next time, don't lose the disk!"
+ if(NUKE_RESULT_WRONG_STATION)
+ parts += "Crew Minor Victory"
+ parts += "[syndicate_name] operatives secured the authentication disk but blew up something that wasn't [station_name()]. Next time, don't do that!"
+ if(NUKE_RESULT_WRONG_STATION_DEAD)
+ parts += "[syndicate_name] operatives have earned Darwin Award!"
+ parts += "[syndicate_name] operatives blew up something that wasn't [station_name()] and got caught in the explosion. Next time, don't do that!"
+ if(NUKE_RESULT_CREW_WIN_SYNDIES_DEAD)
+ parts += "Crew Major Victory!"
+ parts += "The Research Staff has saved the disk and killed the [syndicate_name] Operatives"
+ if(NUKE_RESULT_CREW_WIN)
+ parts += "Crew Major Victory"
+ parts += "The Research Staff has saved the disk and stopped the [syndicate_name] Operatives!"
+ if(NUKE_RESULT_DISK_LOST)
+ parts += "Neutral Victory!"
+ parts += "The Research Staff failed to secure the authentication disk but did manage to kill most of the [syndicate_name] Operatives!"
+ if(NUKE_RESULT_DISK_STOLEN)
+ parts += "Syndicate Minor Victory!"
+ parts += "[syndicate_name] operatives survived the assault but did not achieve the destruction of [station_name()]. Next time, don't lose the disk!"
+ else
+ parts += "Neutral Victory"
+ parts += "Mission aborted!"
+
+ var/text = " The syndicate operatives were:"
+ var/purchases = ""
+ var/TC_uses = 0
+ for(var/I in members)
+ var/datum/mind/syndicate = I
+ for(var/U in GLOB.uplinks)
+ var/datum/component/uplink/H = U
+ if(H.owner == syndicate.key)
+ TC_uses += H.purchase_log.total_spent
+ if(H.purchase_log)
+ purchases += H.purchase_log.generate_render(show_key = FALSE)
+ else
+ stack_trace("WARNING: Nuke Op uplink with no purchase_log Owner: [H.owner]")
+ text += printplayerlist(members)
+ text += " "
+ text += "(Syndicates used [TC_uses] TC) [purchases]"
+ if(TC_uses == 0 && SSticker.mode.station_was_nuked && !operatives_dead())
+ text += "[icon2html('icons/badass.dmi', world, "badass")]"
+
+ parts += text
+
+ return "
[parts.Join(" ")]
"
diff --git a/code/datums/antagonists/pirate.dm b/code/datums/antagonists/pirate.dm
index ad32e09151..e0ce38c1e4 100644
--- a/code/datums/antagonists/pirate.dm
+++ b/code/datums/antagonists/pirate.dm
@@ -1,6 +1,7 @@
/datum/antagonist/pirate
name = "Space Pirate"
job_rank = ROLE_TRAITOR
+ roundend_category = "space pirates"
var/datum/objective_team/pirate/crew
/datum/antagonist/pirate/greet()
@@ -36,7 +37,6 @@
/datum/objective_team/pirate
name = "Pirate crew"
- var/list/objectives = list()
/datum/objective_team/pirate/proc/forge_objectives()
var/datum/objective/loot/getbooty = new()
@@ -84,11 +84,11 @@ GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list(
loot_table[lootname] = count
else
loot_table[lootname] += count
- var/text = ""
+ var/list/loot_texts = list()
for(var/key in loot_table)
var/amount = loot_table[key]
- text += "[amount] [key][amount > 1 ? "s":""], "
- return text
+ loot_texts += "[amount] [key][amount > 1 ? "s":""]"
+ return loot_texts.Join(", ")
/datum/objective/loot/proc/get_loot_value()
if(!storage_area)
@@ -105,31 +105,26 @@ GLOBAL_LIST_INIT(pirate_loot_cache, typecacheof(list(
return ..() || get_loot_value() >= target_value
-//These need removal ASAP as everything is converted to datum antags.
-/datum/game_mode/proc/auto_declare_completion_pirates()
- var/list/datum/mind/pirates = get_antagonists(/datum/antagonist/pirate)
- var/datum/objective_team/pirate/crew
- var/text = ""
- if(pirates.len)
- text += " Space Pirates were:"
- for(var/datum/mind/M in pirates)
- text += printplayer(M)
- if(!crew)
- var/datum/antagonist/pirate/P = M.has_antag_datum(/datum/antagonist/pirate)
- crew = P.crew
- if(crew)
- text += " Loot stolen: "
- var/datum/objective/loot/L = locate() in crew.objectives
- text += L.loot_listing()
- text += " Total loot value : [L.get_loot_value()]/[L.target_value] credits"
- var/all_dead = TRUE
- for(var/datum/mind/M in crew.members)
- if(considered_alive(M))
- all_dead = FALSE
- break
- if(L.check_completion() && !all_dead)
- text += " The pirate crew was successful!"
- else
- text += " The pirate crew has failed."
- to_chat(world, text)
\ No newline at end of file
+/datum/objective_team/pirate/roundend_report()
+ var/list/parts = list()
+
+ parts += "Space Pirates were:"
+
+ var/all_dead = TRUE
+ for(var/datum/mind/M in members)
+ if(considered_alive(M))
+ all_dead = FALSE
+ parts += printplayerlist(members)
+
+ parts += "Loot stolen: "
+ var/datum/objective/loot/L = locate() in objectives
+ parts += L.loot_listing()
+ parts += "Total loot value : [L.get_loot_value()]/[L.target_value] credits"
+
+ if(L.check_completion() && !all_dead)
+ parts += "The pirate crew was successful!"
+ else
+ parts += "The pirate crew has failed."
+
+ return parts.Join(" ")
\ No newline at end of file
diff --git a/code/datums/antagonists/revolution.dm b/code/datums/antagonists/revolution.dm
index 9db86bdf08..14c6d1ab0e 100644
--- a/code/datums/antagonists/revolution.dm
+++ b/code/datums/antagonists/revolution.dm
@@ -3,6 +3,7 @@
/datum/antagonist/rev
name = "Revolutionary"
+ roundend_category = "revolutionaries" // if by some miracle revolutionaries without revolution happen
job_rank = ROLE_REV
var/hud_type = "rev"
var/datum/objective_team/revolution/rev_team
@@ -184,7 +185,6 @@
/datum/objective_team/revolution
name = "Revolution"
- var/list/objectives = list()
var/max_headrevs = 3
/datum/objective_team/revolution/proc/update_objectives(initial = FALSE)
@@ -227,3 +227,56 @@
rev.promote()
addtimer(CALLBACK(src,.proc/update_heads),HEAD_UPDATE_PERIOD,TIMER_UNIQUE)
+
+
+/datum/objective_team/revolution/roundend_report()
+ if(!members.len)
+ return
+
+ var/list/result = list()
+
+ result += "
"
@@ -1029,6 +1028,8 @@
return 0 //we didn't do anything!
else if(href_list["boot2"])
+ if(!check_rights(R_ADMIN))
+ return
var/mob/M = locate(href_list["boot2"])
if (ismob(M))
if(!check_if_greater_rights_than(M.client))
@@ -1041,72 +1042,110 @@
qdel(M.client)
else if(href_list["addmessage"])
+ if(!check_rights(R_ADMIN))
+ return
var/target_ckey = href_list["addmessage"]
create_message("message", target_ckey, secret = 0)
else if(href_list["addnote"])
+ if(!check_rights(R_ADMIN))
+ return
var/target_ckey = href_list["addnote"]
create_message("note", target_ckey)
else if(href_list["addwatch"])
+ if(!check_rights(R_ADMIN))
+ return
var/target_ckey = href_list["addwatch"]
create_message("watchlist entry", target_ckey, secret = 1)
else if(href_list["addmemo"])
+ if(!check_rights(R_ADMIN))
+ return
create_message("memo", secret = 0, browse = 1)
else if(href_list["addmessageempty"])
+ if(!check_rights(R_ADMIN))
+ return
create_message("message", secret = 0)
else if(href_list["addnoteempty"])
+ if(!check_rights(R_ADMIN))
+ return
create_message("note")
else if(href_list["addwatchempty"])
+ if(!check_rights(R_ADMIN))
+ return
create_message("watchlist entry", secret = 1)
else if(href_list["deletemessage"])
+ if(!check_rights(R_ADMIN))
+ return
var/message_id = href_list["deletemessage"]
delete_message(message_id)
else if(href_list["deletemessageempty"])
+ if(!check_rights(R_ADMIN))
+ return
var/message_id = href_list["deletemessageempty"]
delete_message(message_id, browse = 1)
else if(href_list["editmessage"])
+ if(!check_rights(R_ADMIN))
+ return
var/message_id = href_list["editmessage"]
edit_message(message_id)
else if(href_list["editmessageempty"])
+ if(!check_rights(R_ADMIN))
+ return
var/message_id = href_list["editmessageempty"]
edit_message(message_id, browse = 1)
else if(href_list["secretmessage"])
+ if(!check_rights(R_ADMIN))
+ return
var/message_id = href_list["secretmessage"]
toggle_message_secrecy(message_id)
else if(href_list["searchmessages"])
+ if(!check_rights(R_ADMIN))
+ return
var/target = href_list["searchmessages"]
browse_messages(index = target)
else if(href_list["nonalpha"])
+ if(!check_rights(R_ADMIN))
+ return
var/target = href_list["nonalpha"]
target = text2num(target)
browse_messages(index = target)
else if(href_list["showmessages"])
+ if(!check_rights(R_ADMIN))
+ return
var/target = href_list["showmessages"]
browse_messages(index = target)
else if(href_list["showmemo"])
+ if(!check_rights(R_ADMIN))
+ return
browse_messages("memo")
else if(href_list["showwatch"])
+ if(!check_rights(R_ADMIN))
+ return
browse_messages("watchlist entry")
else if(href_list["showwatchfilter"])
+ if(!check_rights(R_ADMIN))
+ return
browse_messages("watchlist entry", filter = 1)
else if(href_list["showmessageckey"])
+ if(!check_rights(R_ADMIN))
+ return
var/target = href_list["showmessageckey"]
var/agegate = TRUE
if (href_list["showall"])
@@ -1118,6 +1157,8 @@
browse_messages(target_ckey = target, linkless = 1)
else if(href_list["messageedits"])
+ if(!check_rights(R_ADMIN))
+ return
var/message_id = sanitizeSQL("[href_list["messageedits"]]")
var/datum/DBQuery/query_get_message_edits = SSdbcore.NewQuery("SELECT edits FROM [format_table_name("messages")] WHERE id = '[message_id]'")
if(!query_get_message_edits.warn_execute())
@@ -1307,7 +1348,7 @@
if(alert(usr, "Send [key_name(M)] to Prison?", "Message", "Yes", "No") != "Yes")
return
- M.loc = pick(GLOB.prisonwarp)
+ M.forceMove(pick(GLOB.prisonwarp))
to_chat(M, "You have been sent to Prison!")
log_admin("[key_name(usr)] has sent [key_name(M)] to Prison!")
@@ -1543,7 +1584,7 @@
C.admin_ghost()
var/mob/dead/observer/A = C.mob
A.ManualFollow(AM)
-
+
else if(href_list["admingetmovable"])
if(!check_rights(R_ADMIN))
return
@@ -1568,9 +1609,13 @@
C.jumptocoord(x,y,z)
else if(href_list["adminchecklaws"])
+ if(!check_rights(R_ADMIN))
+ return
output_ai_laws()
else if(href_list["admincheckdevilinfo"])
+ if(!check_rights(R_ADMIN))
+ return
var/mob/M = locate(href_list["admincheckdevilinfo"])
output_devil_info(M)
@@ -1604,7 +1649,7 @@
var/mob/living/L = M
var/status
switch (M.stat)
- if (CONSCIOUS)
+ if(CONSCIOUS)
status = "Alive"
if(SOFT_CRIT)
status = "Dying"
@@ -1979,20 +2024,28 @@
Secrets_topic(href_list["secrets"],href_list)
else if(href_list["ac_view_wanted"]) //Admin newscaster Topic() stuff be here
+ if(!check_rights(R_ADMIN))
+ return
src.admincaster_screen = 18 //The ac_ prefix before the hrefs stands for AdminCaster.
src.access_news_network()
else if(href_list["ac_set_channel_name"])
+ if(!check_rights(R_ADMIN))
+ return
src.admincaster_feed_channel.channel_name = stripped_input(usr, "Provide a Feed Channel Name.", "Network Channel Handler", "")
while (findtext(src.admincaster_feed_channel.channel_name," ") == 1)
src.admincaster_feed_channel.channel_name = copytext(src.admincaster_feed_channel.channel_name,2,lentext(src.admincaster_feed_channel.channel_name)+1)
src.access_news_network()
else if(href_list["ac_set_channel_lock"])
+ if(!check_rights(R_ADMIN))
+ return
src.admincaster_feed_channel.locked = !src.admincaster_feed_channel.locked
src.access_news_network()
else if(href_list["ac_submit_new_channel"])
+ if(!check_rights(R_ADMIN))
+ return
var/check = 0
for(var/datum/newscaster/feed_channel/FC in GLOB.news_network.network_channels)
if(FC.channel_name == src.admincaster_feed_channel.channel_name)
@@ -2010,6 +2063,8 @@
src.access_news_network()
else if(href_list["ac_set_channel_receiving"])
+ if(!check_rights(R_ADMIN))
+ return
var/list/available_channels = list()
for(var/datum/newscaster/feed_channel/F in GLOB.news_network.network_channels)
available_channels += F.channel_name
@@ -2017,12 +2072,16 @@
src.access_news_network()
else if(href_list["ac_set_new_message"])
+ if(!check_rights(R_ADMIN))
+ return
src.admincaster_feed_message.body = adminscrub(input(usr, "Write your Feed story.", "Network Channel Handler", ""))
while (findtext(src.admincaster_feed_message.returnBody(-1)," ") == 1)
src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.returnBody(-1),2,lentext(src.admincaster_feed_message.returnBody(-1))+1)
src.access_news_network()
else if(href_list["ac_submit_new_message"])
+ if(!check_rights(R_ADMIN))
+ return
if(src.admincaster_feed_message.returnBody(-1) =="" || src.admincaster_feed_message.returnBody(-1) =="\[REDACTED\]" || src.admincaster_feed_channel.channel_name == "" )
src.admincaster_screen = 6
else
@@ -2037,22 +2096,32 @@
src.access_news_network()
else if(href_list["ac_create_channel"])
+ if(!check_rights(R_ADMIN))
+ return
src.admincaster_screen=2
src.access_news_network()
else if(href_list["ac_create_feed_story"])
+ if(!check_rights(R_ADMIN))
+ return
src.admincaster_screen=3
src.access_news_network()
else if(href_list["ac_menu_censor_story"])
+ if(!check_rights(R_ADMIN))
+ return
src.admincaster_screen=10
src.access_news_network()
else if(href_list["ac_menu_censor_channel"])
+ if(!check_rights(R_ADMIN))
+ return
src.admincaster_screen=11
src.access_news_network()
else if(href_list["ac_menu_wanted"])
+ if(!check_rights(R_ADMIN))
+ return
var/already_wanted = 0
if(GLOB.news_network.wanted_issue.active)
already_wanted = 1
@@ -2064,18 +2133,24 @@
src.access_news_network()
else if(href_list["ac_set_wanted_name"])
+ if(!check_rights(R_ADMIN))
+ return
src.admincaster_wanted_message.criminal = adminscrub(input(usr, "Provide the name of the Wanted person.", "Network Security Handler", ""))
while(findtext(src.admincaster_wanted_message.criminal," ") == 1)
src.admincaster_wanted_message.criminal = copytext(admincaster_wanted_message.criminal,2,lentext(admincaster_wanted_message.criminal)+1)
src.access_news_network()
else if(href_list["ac_set_wanted_desc"])
+ if(!check_rights(R_ADMIN))
+ return
src.admincaster_wanted_message.body = adminscrub(input(usr, "Provide the a description of the Wanted person and any other details you deem important.", "Network Security Handler", ""))
while (findtext(src.admincaster_wanted_message.body," ") == 1)
src.admincaster_wanted_message.body = copytext(src.admincaster_wanted_message.body,2,lentext(src.admincaster_wanted_message.body)+1)
src.access_news_network()
else if(href_list["ac_submit_wanted"])
+ if(!check_rights(R_ADMIN))
+ return
var/input_param = text2num(href_list["ac_submit_wanted"])
if(src.admincaster_wanted_message.criminal == "" || src.admincaster_wanted_message.body == "")
src.admincaster_screen = 16
@@ -2092,6 +2167,8 @@
src.access_news_network()
else if(href_list["ac_cancel_wanted"])
+ if(!check_rights(R_ADMIN))
+ return
var/choice = alert("Please confirm Wanted Issue removal.","Network Security Handler","Confirm","Cancel")
if(choice=="Confirm")
GLOB.news_network.deleteWanted()
@@ -2099,36 +2176,50 @@
src.access_news_network()
else if(href_list["ac_censor_channel_author"])
+ if(!check_rights(R_ADMIN))
+ return
var/datum/newscaster/feed_channel/FC = locate(href_list["ac_censor_channel_author"])
FC.toggleCensorAuthor()
src.access_news_network()
else if(href_list["ac_censor_channel_story_author"])
+ if(!check_rights(R_ADMIN))
+ return
var/datum/newscaster/feed_message/MSG = locate(href_list["ac_censor_channel_story_author"])
MSG.toggleCensorAuthor()
src.access_news_network()
else if(href_list["ac_censor_channel_story_body"])
+ if(!check_rights(R_ADMIN))
+ return
var/datum/newscaster/feed_message/MSG = locate(href_list["ac_censor_channel_story_body"])
MSG.toggleCensorBody()
src.access_news_network()
else if(href_list["ac_pick_d_notice"])
+ if(!check_rights(R_ADMIN))
+ return
var/datum/newscaster/feed_channel/FC = locate(href_list["ac_pick_d_notice"])
src.admincaster_feed_channel = FC
src.admincaster_screen=13
src.access_news_network()
else if(href_list["ac_toggle_d_notice"])
+ if(!check_rights(R_ADMIN))
+ return
var/datum/newscaster/feed_channel/FC = locate(href_list["ac_toggle_d_notice"])
FC.toggleCensorDclass()
src.access_news_network()
else if(href_list["ac_view"])
+ if(!check_rights(R_ADMIN))
+ return
src.admincaster_screen=1
src.access_news_network()
else if(href_list["ac_setScreen"]) //Brings us to the main menu and resets all fields~
+ if(!check_rights(R_ADMIN))
+ return
src.admincaster_screen = text2num(href_list["ac_setScreen"])
if (src.admincaster_screen == 0)
if(src.admincaster_feed_channel)
@@ -2140,25 +2231,35 @@
src.access_news_network()
else if(href_list["ac_show_channel"])
+ if(!check_rights(R_ADMIN))
+ return
var/datum/newscaster/feed_channel/FC = locate(href_list["ac_show_channel"])
src.admincaster_feed_channel = FC
src.admincaster_screen = 9
src.access_news_network()
else if(href_list["ac_pick_censor_channel"])
+ if(!check_rights(R_ADMIN))
+ return
var/datum/newscaster/feed_channel/FC = locate(href_list["ac_pick_censor_channel"])
src.admincaster_feed_channel = FC
src.admincaster_screen = 12
src.access_news_network()
else if(href_list["ac_refresh"])
+ if(!check_rights(R_ADMIN))
+ return
src.access_news_network()
else if(href_list["ac_set_signature"])
+ if(!check_rights(R_ADMIN))
+ return
src.admin_signature = adminscrub(input(usr, "Provide your desired signature.", "Network Identity Handler", ""))
src.access_news_network()
else if(href_list["ac_del_comment"])
+ if(!check_rights(R_ADMIN))
+ return
var/datum/newscaster/feed_comment/FC = locate(href_list["ac_del_comment"])
var/datum/newscaster/feed_message/FM = locate(href_list["ac_del_comment_msg"])
FM.comments -= FC
@@ -2166,6 +2267,8 @@
src.access_news_network()
else if(href_list["ac_lock_comment"])
+ if(!check_rights(R_ADMIN))
+ return
var/datum/newscaster/feed_message/FM = locate(href_list["ac_lock_comment"])
FM.locked ^= 1
src.access_news_network()
@@ -2262,6 +2365,8 @@
error_viewer.show_to(owner, null, href_list["viewruntime_linear"])
else if(href_list["showrelatedacc"])
+ if(!check_rights(R_ADMIN))
+ return
var/client/C = locate(href_list["client"]) in GLOB.clients
var/thing_to_check
if(href_list["showrelatedacc"] == "cid")
diff --git a/code/modules/admin/verbs/BrokenInhands.dm b/code/modules/admin/verbs/BrokenInhands.dm
index 20721077df..112dff352b 100644
--- a/code/modules/admin/verbs/BrokenInhands.dm
+++ b/code/modules/admin/verbs/BrokenInhands.dm
@@ -31,3 +31,5 @@
fdel(F)
WRITE_FILE(F, text)
to_chat(world, "Completely successfully and written to [F]")
+
+
diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm
index 8a7c030458..56faa1f6c4 100644
--- a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm
+++ b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm
@@ -114,8 +114,8 @@
/proc/_range(Dist, Center = usr)
return range(Dist, Center)
-/proc/_regex(pattern, flags_1)
- return regex(pattern, flags_1)
+/proc/_regex(pattern, flags)
+ return regex(pattern, flags)
/proc/_REGEX_QUOTE(text)
return REGEX_QUOTE(text)
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index 2d57ee0965..87f33e0fcd 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -615,15 +615,18 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
/proc/send2otherserver(source,msg,type = "Ahelp")
var/comms_key = CONFIG_GET(string/comms_key)
- if(comms_key)
- var/list/message = list()
- message["message_sender"] = source
- message["message"] = msg
- message["source"] = "([CONFIG_GET(string/cross_comms_name)])"
- message["key"] = comms_key
- message["crossmessage"] = type
+ if(!comms_key)
+ return
+ var/list/message = list()
+ message["message_sender"] = source
+ message["message"] = msg
+ message["source"] = "([CONFIG_GET(string/cross_comms_name)])"
+ message["key"] = comms_key
+ message["crossmessage"] = type
- world.Export("[CONFIG_GET(string/cross_server_address)]?[list2params(message)]")
+ var/list/servers = CONFIG_GET(keyed_string_list/cross_server)
+ for(var/I in servers)
+ world.Export("[servers[I]]?[list2params(message)]")
/proc/ircadminwho()
diff --git a/code/modules/admin/verbs/adminjump.dm b/code/modules/admin/verbs/adminjump.dm
index 1e7f89fc8d..779ea64640 100644
--- a/code/modules/admin/verbs/adminjump.dm
+++ b/code/modules/admin/verbs/adminjump.dm
@@ -34,7 +34,7 @@
log_admin("[key_name(usr)] jumped to [T.x],[T.y],[T.z] in [T.loc]")
message_admins("[key_name_admin(usr)] jumped to [T.x],[T.y],[T.z] in [T.loc]")
- usr.loc = T
+ usr.forceMove(T)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Jump To Turf") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
@@ -137,7 +137,7 @@
admin_ticket_log(M, msg)
if(M)
M.forceMove(get_turf(usr))
- usr.loc = M.loc
+ usr.forceMove(M.loc)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Get Key") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/sendmob(mob/M in sortmobs())
diff --git a/code/modules/admin/verbs/cinematic.dm b/code/modules/admin/verbs/cinematic.dm
index 7093ee23ea..5aa3258f07 100644
--- a/code/modules/admin/verbs/cinematic.dm
+++ b/code/modules/admin/verbs/cinematic.dm
@@ -8,4 +8,4 @@
var/datum/cinematic/choice = input(src,"Cinematic","Choose",null) as anything in subtypesof(/datum/cinematic)
if(choice)
- Cinematic(initial(choice.id),world,null)
+ Cinematic(initial(choice.id),world,null)
\ No newline at end of file
diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm
index b96c8f4bdc..6f16a816df 100644
--- a/code/modules/admin/verbs/debug.dm
+++ b/code/modules/admin/verbs/debug.dm
@@ -739,7 +739,7 @@ GLOBAL_PROTECT(LastAdminCalledProc)
Plasma.air_contents.gases[/datum/gas/plasma][MOLES] = 70
Rad.drainratio = 0
Rad.loaded_tank = Plasma
- Plasma.loc = Rad
+ Plasma.forceMove(Rad)
if(!Rad.active)
Rad.toggle_power()
@@ -802,7 +802,7 @@ GLOBAL_PROTECT(LastAdminCalledProc)
set category = "Debug"
set name = "Display overlay Log"
set desc = "Display SSoverlays log of everything that's passed through it."
-
+
render_stats(SSoverlays.stats, src)
/client/proc/cmd_display_init_log()
diff --git a/code/modules/admin/verbs/diagnostics.dm b/code/modules/admin/verbs/diagnostics.dm
index bcf58b1a4c..6f2bcb6c46 100644
--- a/code/modules/admin/verbs/diagnostics.dm
+++ b/code/modules/admin/verbs/diagnostics.dm
@@ -53,17 +53,6 @@
set category = "Debug"
set name = "Radio report"
- var/filters = list(
- "1" = "GLOB.RADIO_TO_AIRALARM",
- "2" = "GLOB.RADIO_FROM_AIRALARM",
- "3" = "GLOB.RADIO_CHAT",
- "4" = "GLOB.RADIO_ATMOSIA",
- "5" = "GLOB.RADIO_NAVBEACONS",
- "6" = "GLOB.RADIO_AIRLOCK",
- "7" = "RADIO_SECBOT",
- "8" = "RADIO_MULEBOT",
- "_default" = "NO_FILTER"
- )
var/output = "Radio Report"
for (var/fq in SSradio.frequencies)
output += "Freq: [fq] "
@@ -74,9 +63,9 @@
for (var/filter in fqs.devices)
var/list/f = fqs.devices[filter]
if (!f)
- output += " [filters[filter]]: ERROR "
+ output += " [filter]: ERROR "
continue
- output += " [filters[filter]]: [f.len] "
+ output += " [filter]: [f.len] "
for (var/device in f)
if (istype(device, /atom))
var/atom/A = device
diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm
index 5d0c2fe833..cbde59bcb6 100644
--- a/code/modules/admin/verbs/mapping.dm
+++ b/code/modules/admin/verbs/mapping.dm
@@ -39,7 +39,6 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
/client/proc/cmd_admin_rejuvenate,
/datum/admins/proc/show_traitor_panel,
/client/proc/disable_communication,
- /client/proc/print_pointers,
/client/proc/cmd_show_at_list,
/client/proc/cmd_show_at_markers,
/client/proc/manipulate_organs,
diff --git a/code/modules/admin/verbs/massmodvar.dm b/code/modules/admin/verbs/massmodvar.dm
index 6043d23d62..db1150fb72 100644
--- a/code/modules/admin/verbs/massmodvar.dm
+++ b/code/modules/admin/verbs/massmodvar.dm
@@ -64,14 +64,14 @@
if(default == VV_NUM)
var/dir_text = ""
- if(dir < 0 && dir < 16)
- if(dir & 1)
+ if(var_value > 0 && var_value < 16)
+ if(var_value & 1)
dir_text += "NORTH"
- if(dir & 2)
+ if(var_value & 2)
dir_text += "SOUTH"
- if(dir & 4)
+ if(var_value & 4)
dir_text += "EAST"
- if(dir & 8)
+ if(var_value & 8)
dir_text += "WEST"
if(dir_text)
diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm
index 3a2e13fdcc..ea88c90072 100644
--- a/code/modules/admin/verbs/modifyvariables.dm
+++ b/code/modules/admin/verbs/modifyvariables.dm
@@ -441,11 +441,11 @@ GLOBAL_PROTECT(VVpixelmovement)
if(tdir > 0 && tdir < 16)
if(tdir & 1)
dir_text += "NORTH"
- if(dir & 2)
+ if(tdir & 2)
dir_text += "SOUTH"
- if(dir & 4)
+ if(tdir & 4)
dir_text += "EAST"
- if(dir & 8)
+ if(tdir & 8)
dir_text += "WEST"
if(dir_text)
@@ -560,14 +560,14 @@ GLOBAL_PROTECT(VVpixelmovement)
if(default == VV_NUM)
var/dir_text = ""
- if(dir < 0 && dir < 16)
- if(dir & 1)
+ if(var_value > 0 && var_value < 16)
+ if(var_value & 1)
dir_text += "NORTH"
- if(dir & 2)
+ if(var_value & 2)
dir_text += "SOUTH"
- if(dir & 4)
+ if(var_value & 4)
dir_text += "EAST"
- if(dir & 8)
+ if(var_value & 8)
dir_text += "WEST"
if(dir_text)
diff --git a/code/modules/admin/verbs/one_click_antag.dm b/code/modules/admin/verbs/one_click_antag.dm
index 8a18dc9ac5..2c59ce21f2 100644
--- a/code/modules/admin/verbs/one_click_antag.dm
+++ b/code/modules/admin/verbs/one_click_antag.dm
@@ -238,26 +238,17 @@
if(agentcount < 3)
return 0
- var/nuke_code = random_nukecode()
-
- var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list
- if(nuke)
- nuke.r_code = nuke_code
-
//Let's find the spawn locations
var/leader_chosen = FALSE
- var/spawnpos = 1 //Decides where they'll spawn. 1=leader.
-
+ var/datum/objective_team/nuclear/nuke_team
for(var/mob/c in chosen)
- if(spawnpos > GLOB.nukeop_start.len)
- spawnpos = 1 //Ran out of spawns. Let's loop back to the first non-leader position
var/mob/living/carbon/human/new_character=makeBody(c)
if(!leader_chosen)
leader_chosen = TRUE
- new_character.mind.make_Nuke(pick(GLOB.nukeop_leader_start), nuke_code, TRUE)
+ var/datum/antagonist/nukeop/N = new_character.mind.add_antag_datum(/datum/antagonist/nukeop/leader)
+ nuke_team = N.nuke_team
else
- new_character.mind.make_Nuke(GLOB.nukeop_start[spawnpos], nuke_code)
- spawnpos++
+ new_character.mind.add_antag_datum(/datum/antagonist/nukeop,nuke_team)
return 1
else
return 0
@@ -317,11 +308,14 @@
//Assign antag status and the mission
SSticker.mode.traitors += Commando.mind
Commando.mind.special_role = "deathsquad"
+
var/datum/objective/missionobj = new
missionobj.owner = Commando.mind
missionobj.explanation_text = mission
missionobj.completed = 1
Commando.mind.objectives += missionobj
+
+ Commando.mind.add_antag_datum(/datum/antagonist/auto_custom)
//Greet the commando
to_chat(Commando, "You are the [numagents==1?"Deathsquad Officer":"Death Commando"].")
@@ -369,11 +363,14 @@
//Assign antag status and the mission
SSticker.mode.traitors += newmob.mind
newmob.mind.special_role = "official"
+
var/datum/objective/missionobj = new
missionobj.owner = newmob.mind
missionobj.explanation_text = mission
missionobj.completed = 1
newmob.mind.objectives += missionobj
+
+ newmob.mind.add_antag_datum(/datum/antagonist/auto_custom)
if(CONFIG_GET(flag/enforce_human_authority))
newmob.set_species(/datum/species/human)
@@ -474,12 +471,15 @@
//Assign antag status and the mission
SSticker.mode.traitors += ERTOperative.mind
ERTOperative.mind.special_role = "ERT"
+
var/datum/objective/missionobj = new
missionobj.owner = ERTOperative.mind
missionobj.explanation_text = mission
missionobj.completed = 1
ERTOperative.mind.objectives += missionobj
+ ERTOperative.mind.add_antag_datum(/datum/antagonist/auto_custom)
+
//Greet the commando
to_chat(ERTOperative, "You are [numagents==1?"the Emergency Response Team Commander":"an Emergency Response Officer"].")
var/missiondesc = "Your squad is being sent on a Code [alert] mission to [station_name()] by Nanotrasen's Security Division."
diff --git a/code/modules/admin/verbs/onlyone.dm b/code/modules/admin/verbs/onlyone.dm
index b675815602..d09041aaf3 100644
--- a/code/modules/admin/verbs/onlyone.dm
+++ b/code/modules/admin/verbs/onlyone.dm
@@ -28,6 +28,7 @@ GLOBAL_VAR_INIT(highlander, FALSE)
/mob/living/carbon/human/proc/make_scottish()
SSticker.mode.traitors += mind
mind.special_role = "highlander"
+
dna.species.species_traits |= NOGUNS //nice try jackass
var/datum/objective/steal/steal_objective = new
@@ -40,6 +41,8 @@ GLOBAL_VAR_INIT(highlander, FALSE)
hijack_objective.owner = mind
mind.objectives += hijack_objective
+ mind.add_antag_datum(/datum/antagonist/auto_custom)
+
mind.announce_objectives()
for(var/obj/item/I in get_equipped_items())
diff --git a/code/modules/admin/verbs/panicbunker.dm b/code/modules/admin/verbs/panicbunker.dm
index f7d1d60aab..fc0cab66c9 100644
--- a/code/modules/admin/verbs/panicbunker.dm
+++ b/code/modules/admin/verbs/panicbunker.dm
@@ -12,5 +12,4 @@
message_admins("[key_name_admin(usr)] has toggled the Panic Bunker, it is now [new_pb ? "enabled" : "disabled"].")
if (new_pb && !SSdbcore.Connect())
message_admins("The Database is not connected! Panic bunker will not work until the connection is reestablished.")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Panic Bunker", "[new_pb]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Panic Bunker", "[new_pb ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/playsound.dm b/code/modules/admin/verbs/playsound.dm
index 6b1edf7709..a05637571c 100644
--- a/code/modules/admin/verbs/playsound.dm
+++ b/code/modules/admin/verbs/playsound.dm
@@ -92,6 +92,7 @@
if(SSevents.holidays && SSevents.holidays[APRIL_FOOLS])
pitch = pick(0.5, 0.7, 0.8, 0.85, 0.9, 0.95, 1.1, 1.2, 1.4, 1.6, 2.0, 2.5)
to_chat(src, "You feel the Honkmother messing with your song...")
+
SSblackbox.record_feedback("nested tally", "played_url", 1, list("[ckey]", "[web_sound_input]"))
log_admin("[key_name(src)] played web sound: [web_sound_input]")
message_admins("[key_name(src)] played web sound: [web_sound_input]")
diff --git a/code/modules/admin/verbs/possess.dm b/code/modules/admin/verbs/possess.dm
index fc81ca3a02..a9b5093e99 100644
--- a/code/modules/admin/verbs/possess.dm
+++ b/code/modules/admin/verbs/possess.dm
@@ -21,25 +21,26 @@
usr.loc = O
usr.real_name = O.name
usr.name = O.name
- usr.client.eye = O
+ usr.reset_perspective(O)
usr.control_object = O
SSblackbox.record_feedback("tally", "admin_verb", 1, "Possess Object") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
-/proc/release(obj/O in world)
+/proc/release()
set name = "Release Obj"
set category = "Object"
//usr.loc = get_turf(usr)
if(usr.control_object && usr.name_archive) //if you have a name archived and if you are actually relassing an object
usr.real_name = usr.name_archive
+ usr.name_archive = ""
usr.name = usr.real_name
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
H.name = H.get_visible_name()
-// usr.regenerate_icons() //So the name is updated properly
- usr.loc = O.loc
- usr.client.eye = usr
+
+ usr.loc = get_turf(usr.control_object)
+ usr.reset_perspective()
usr.control_object = null
SSblackbox.record_feedback("tally", "admin_verb", 1, "Release Object") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 48ba94bb76..01e45e471b 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -125,7 +125,7 @@
var/msg = "[key_name_admin(usr)] has toggled [key_name_admin(M)]'s nodamage to [(M.status_flags & GODMODE) ? "On" : "Off"]"
message_admins(msg)
admin_ticket_log(M, msg)
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Godmode", "[M.status_flags & GODMODE]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Godmode", "[M.status_flags & GODMODE ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/proc/cmd_admin_mute(whom, mute_type, automute = 0)
@@ -386,7 +386,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
A.equip_wizard()
if("Syndicate")
new_character.forceMove(pick(GLOB.nukeop_start))
- call(/datum/game_mode/proc/equip_syndicate)(new_character)
+ var/datum/antagonist/nukeop/N = new_character.mind.has_antag_datum(/datum/antagonist/nukeop,TRUE)
+ N.equip_op()
if("Space Ninja")
var/list/ninja_spawn = list()
for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
@@ -746,7 +747,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
else
to_chat(usr, "Random events disabled")
message_admins("Admin [key_name_admin(usr)] has disabled random events.")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Random Events", "[new_are]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Random Events", "[new_are ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/admin_change_sec_level()
@@ -979,7 +980,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
to_chat(usr, "You toggled your admin antag HUD [adding_hud ? "ON" : "OFF"].")
message_admins("[key_name_admin(usr)] toggled their admin antag HUD [adding_hud ? "ON" : "OFF"].")
log_admin("[key_name(usr)] toggled their admin antag HUD [adding_hud ? "ON" : "OFF"].")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Antag HUD", "[adding_hud]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Antag HUD", "[adding_hud ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/has_antag_hud()
var/datum/atom_hud/A = GLOB.huds[ANTAG_HUD_TRAITOR]
@@ -1198,7 +1199,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
if (GLOB.hub_visibility && !world.reachable)
message_admins("WARNING: The server will not show up on the hub because byond is detecting that a filewall is blocking incoming connections.")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggled Hub Visibility", "[GLOB.hub_visibility]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggled Hub Visibility", "[GLOB.hub_visibility ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/smite(mob/living/carbon/human/target as mob)
set name = "Smite"
diff --git a/code/modules/assembly/assembly.dm b/code/modules/assembly/assembly.dm
index 315e28df02..7e0aa59816 100644
--- a/code/modules/assembly/assembly.dm
+++ b/code/modules/assembly/assembly.dm
@@ -114,3 +114,4 @@
/obj/item/device/assembly/interact(mob/user)
return //HTML MENU FOR WIRES GOES HERE
+
diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm
index b929e83ada..439ea314bb 100644
--- a/code/modules/assembly/holder.dm
+++ b/code/modules/assembly/holder.dm
@@ -68,11 +68,10 @@
a_right.on_found(finder)
/obj/item/device/assembly_holder/Move()
- ..()
+ . = ..()
if(a_left && a_right)
a_left.holder_movement()
a_right.holder_movement()
- return
/obj/item/device/assembly_holder/attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess
if(a_left && a_right)
@@ -88,10 +87,10 @@
return 0
if(a_left)
a_left.holder = null
- a_left.loc = T
+ a_left.forceMove(T)
if(a_right)
a_right.holder = null
- a_right.loc = T
+ a_right.forceMove(T)
qdel(src)
else
..()
diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm
index 0b9d42e42e..565465ec6d 100644
--- a/code/modules/assembly/infrared.dm
+++ b/code/modules/assembly/infrared.dm
@@ -83,10 +83,9 @@
/obj/item/device/assembly/infra/Move()
var/t = dir
- ..()
+ . = ..()
setDir(t)
qdel(first)
- return
/obj/item/device/assembly/infra/holder_movement()
if(!holder)
diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm
index e8ee742e56..152fa374ee 100644
--- a/code/modules/assembly/mousetrap.dm
+++ b/code/modules/assembly/mousetrap.dm
@@ -20,7 +20,7 @@
if(!armed)
if(ishuman(usr))
var/mob/living/carbon/human/user = usr
- if((user.getBrainLoss() >= 60) || user.disabilities & CLUMSY && prob(50))
+ if((user.disabilities & (CLUMSY | DUMB)) && prob(50))
to_chat(user, "Your hand slips, setting off the trigger!")
pulse(0)
update_icon()
@@ -76,7 +76,7 @@
if(!armed)
to_chat(user, "You arm [src].")
else
- if(((user.getBrainLoss() >= 60) || user.disabilities & CLUMSY) && prob(50))
+ if((user.disabilities & (CLUMSY | DUMB)) && prob(50))
var/which_hand = "l_hand"
if(!(user.active_hand_index % 2))
which_hand = "r_hand"
@@ -92,7 +92,7 @@
/obj/item/device/assembly/mousetrap/attack_hand(mob/living/carbon/human/user)
if(armed)
- if(((user.getBrainLoss() >= 60) || user.disabilities & CLUMSY) && prob(50))
+ if((user.disabilities & (CLUMSY | DUMB)) && prob(50))
var/which_hand = "l_hand"
if(!(user.active_hand_index % 2))
which_hand = "r_hand"
@@ -139,4 +139,4 @@
/obj/item/device/assembly/mousetrap/armed
icon_state = "mousetraparmed"
- armed = TRUE
+ armed = 1
diff --git a/code/modules/assembly/shock_kit.dm b/code/modules/assembly/shock_kit.dm
index 1b21738391..174312df1e 100644
--- a/code/modules/assembly/shock_kit.dm
+++ b/code/modules/assembly/shock_kit.dm
@@ -1,42 +1,39 @@
-/obj/item/assembly/shock_kit
- name = "electrohelmet assembly"
- desc = "This appears to be made from both an electropack and a helmet."
- icon = 'icons/obj/assemblies.dmi'
- icon_state = "shock_kit"
- var/obj/item/clothing/head/helmet/part1 = null
- var/obj/item/device/electropack/part2 = null
- w_class = WEIGHT_CLASS_HUGE
+/obj/item/assembly/shock_kit
+ name = "electrohelmet assembly"
+ desc = "This appears to be made from both an electropack and a helmet."
+ icon = 'icons/obj/assemblies.dmi'
+ icon_state = "shock_kit"
+ var/obj/item/clothing/head/helmet/part1 = null
+ var/obj/item/device/electropack/part2 = null
+ w_class = WEIGHT_CLASS_HUGE
flags_1 = CONDUCT_1
-
-/obj/item/assembly/shock_kit/Destroy()
- qdel(part1)
- qdel(part2)
- return ..()
-
-/obj/item/assembly/shock_kit/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/wrench))
- var/turf/T = loc
- if(ismob(T))
- T = T.loc
- part1.loc = T
- part2.loc = T
- part1.master = null
- part2.master = null
- part1 = null
- part2 = null
- qdel(src)
- return
- add_fingerprint(user)
- return
-
-/obj/item/assembly/shock_kit/attack_self(mob/user)
- part1.attack_self(user)
- part2.attack_self(user)
- add_fingerprint(user)
- return
-
-/obj/item/assembly/shock_kit/receive_signal()
- if(istype(loc, /obj/structure/chair/e_chair))
- var/obj/structure/chair/e_chair/C = loc
- C.shock()
- return
+
+/obj/item/assembly/shock_kit/Destroy()
+ qdel(part1)
+ qdel(part2)
+ return ..()
+
+/obj/item/assembly/shock_kit/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/wrench))
+ part1.forceMove(drop_location())
+ part2.forceMove(drop_location())
+ part1.master = null
+ part2.master = null
+ part1 = null
+ part2 = null
+ qdel(src)
+ return
+ add_fingerprint(user)
+ return
+
+/obj/item/assembly/shock_kit/attack_self(mob/user)
+ part1.attack_self(user)
+ part2.attack_self(user)
+ add_fingerprint(user)
+ return
+
+/obj/item/assembly/shock_kit/receive_signal()
+ if(istype(loc, /obj/structure/chair/e_chair))
+ var/obj/structure/chair/e_chair/C = loc
+ C.shock()
+ return
diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm
index d9fdab39be..1b0102abdd 100644
--- a/code/modules/assembly/signaler.dm
+++ b/code/modules/assembly/signaler.dm
@@ -9,8 +9,8 @@
wires = WIRE_RECEIVE | WIRE_PULSE | WIRE_RADIO_PULSE | WIRE_RADIO_RECEIVE
attachable = 1
- var/code = 30
- var/frequency = 1457
+ var/code = DEFAULT_SIGNALER_CODE
+ var/frequency = FREQ_SIGNALER
var/delay = 0
var/datum/radio_frequency/radio_connection
@@ -73,7 +73,7 @@ Code:
if (href_list["freq"])
var/new_frequency = (frequency + text2num(href_list["freq"]))
- if(new_frequency < 1200 || new_frequency > 1600)
+ if(new_frequency < MIN_FREE_FREQ || new_frequency > MAX_FREE_FREQ)
new_frequency = sanitize_frequency(new_frequency)
set_frequency(new_frequency)
@@ -105,10 +105,7 @@ Code:
if(!radio_connection)
return
- var/datum/signal/signal = new
- signal.source = src
- signal.encryption = code
- signal.data["message"] = "ACTIVATE"
+ var/datum/signal/signal = new(list("code" = code))
radio_connection.post_signal(src, signal)
var/time = time2text(world.realtime,"hh:mm:ss")
@@ -122,7 +119,7 @@ Code:
/obj/item/device/assembly/signaler/receive_signal(datum/signal/signal)
if(!signal)
return 0
- if(signal.encryption != code)
+ if(signal.data["code"] != code)
return 0
if(!(src.wires & WIRE_RADIO_RECEIVE))
return 0
@@ -132,13 +129,9 @@ Code:
/obj/item/device/assembly/signaler/proc/set_frequency(new_frequency)
- if(!SSradio)
- sleep(20)
- if(!SSradio)
- return
SSradio.remove_object(src, frequency)
frequency = new_frequency
- radio_connection = SSradio.add_object(src, frequency, GLOB.RADIO_CHAT)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_SIGNALER)
return
// Embedded signaller used in grenade construction.
@@ -175,7 +168,7 @@ Code:
/obj/item/device/assembly/signaler/anomaly/receive_signal(datum/signal/signal)
if(!signal)
return 0
- if(signal.encryption != code)
+ if(signal.data["code"] != code)
return 0
for(var/obj/effect/anomaly/A in get_turf(src))
A.anomalyNeutralize()
diff --git a/code/modules/assembly/voice.dm b/code/modules/assembly/voice.dm
index 617f384592..913176b662 100644
--- a/code/modules/assembly/voice.dm
+++ b/code/modules/assembly/voice.dm
@@ -1,91 +1,91 @@
-/obj/item/device/assembly/voice
- name = "voice analyzer"
- desc = "A small electronic device able to record a voice sample, and send a signal when that sample is repeated."
- icon_state = "voice"
- materials = list(MAT_METAL=500, MAT_GLASS=50)
+/obj/item/device/assembly/voice
+ name = "voice analyzer"
+ desc = "A small electronic device able to record a voice sample, and send a signal when that sample is repeated."
+ icon_state = "voice"
+ materials = list(MAT_METAL=500, MAT_GLASS=50)
flags_1 = HEAR_1
- attachable = 1
- verb_say = "beeps"
- verb_ask = "beeps"
- verb_exclaim = "beeps"
- var/listening = 0
- var/recorded = "" //the activation message
- var/mode = 1
- var/static/list/modes = list("inclusive",
- "exclusive",
- "recognizer",
- "voice sensor")
-
-/obj/item/device/assembly/voice/examine(mob/user)
- ..()
- to_chat(user, "Use a multitool to swap between \"inclusive\", \"exclusive\", \"recognizer\", and \"voice sensor\" mode.")
-
-/obj/item/device/assembly/voice/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
- if(speaker == src)
- return
-
- if(listening && !radio_freq)
- record_speech(speaker, raw_message, message_language)
- else
- if(check_activation(speaker, raw_message))
- addtimer(CALLBACK(src, .proc/pulse, 0), 10)
-
-/obj/item/device/assembly/voice/proc/record_speech(atom/movable/speaker, raw_message, datum/language/message_language)
- switch(mode)
- if(1)
- recorded = raw_message
- listening = 0
- say("Activation message is '[recorded]'.", message_language)
- if(2)
- recorded = raw_message
- listening = 0
- say("Activation message is '[recorded]'.", message_language)
- if(3)
- recorded = speaker.GetVoice()
- listening = 0
- say("Your voice pattern is saved.", message_language)
- if(4)
- if(length(raw_message))
- addtimer(CALLBACK(src, .proc/pulse, 0), 10)
-
-/obj/item/device/assembly/voice/proc/check_activation(atom/movable/speaker, raw_message)
- . = 0
- switch(mode)
- if(1)
- if(findtext(raw_message, recorded))
- . = 1
- if(2)
- if(raw_message == recorded)
- . = 1
- if(3)
- if(speaker.GetVoice() == recorded)
- . = 1
- if(4)
- if(length(raw_message))
- . = 1
-
-/obj/item/device/assembly/voice/attackby(obj/item/W, mob/user, params)
- if(istype(W, /obj/item/device/multitool))
- mode %= modes.len
- mode++
- to_chat(user, "You set [src] into a [modes[mode]] mode.")
- listening = 0
- recorded = ""
- else
- return ..()
-
-/obj/item/device/assembly/voice/activate()
- if(secured)
- if(!holder)
- listening = !listening
- say("[listening ? "Now" : "No longer"] recording input.")
-
-/obj/item/device/assembly/voice/attack_self(mob/user)
- if(!user)
- return 0
- activate()
- return 1
-
-/obj/item/device/assembly/voice/toggle_secure()
- . = ..()
- listening = 0
+ attachable = 1
+ verb_say = "beeps"
+ verb_ask = "beeps"
+ verb_exclaim = "beeps"
+ var/listening = 0
+ var/recorded = "" //the activation message
+ var/mode = 1
+ var/static/list/modes = list("inclusive",
+ "exclusive",
+ "recognizer",
+ "voice sensor")
+
+/obj/item/device/assembly/voice/examine(mob/user)
+ ..()
+ to_chat(user, "Use a multitool to swap between \"inclusive\", \"exclusive\", \"recognizer\", and \"voice sensor\" mode.")
+
+/obj/item/device/assembly/voice/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
+ if(speaker == src)
+ return
+
+ if(listening && !radio_freq)
+ record_speech(speaker, raw_message, message_language)
+ else
+ if(check_activation(speaker, raw_message))
+ addtimer(CALLBACK(src, .proc/pulse, 0), 10)
+
+/obj/item/device/assembly/voice/proc/record_speech(atom/movable/speaker, raw_message, datum/language/message_language)
+ switch(mode)
+ if(1)
+ recorded = raw_message
+ listening = 0
+ say("Activation message is '[recorded]'.", message_language)
+ if(2)
+ recorded = raw_message
+ listening = 0
+ say("Activation message is '[recorded]'.", message_language)
+ if(3)
+ recorded = speaker.GetVoice()
+ listening = 0
+ say("Your voice pattern is saved.", message_language)
+ if(4)
+ if(length(raw_message))
+ addtimer(CALLBACK(src, .proc/pulse, 0), 10)
+
+/obj/item/device/assembly/voice/proc/check_activation(atom/movable/speaker, raw_message)
+ . = 0
+ switch(mode)
+ if(1)
+ if(findtext(raw_message, recorded))
+ . = 1
+ if(2)
+ if(raw_message == recorded)
+ . = 1
+ if(3)
+ if(speaker.GetVoice() == recorded)
+ . = 1
+ if(4)
+ if(length(raw_message))
+ . = 1
+
+/obj/item/device/assembly/voice/attackby(obj/item/W, mob/user, params)
+ if(istype(W, /obj/item/device/multitool))
+ mode %= modes.len
+ mode++
+ to_chat(user, "You set [src] into a [modes[mode]] mode.")
+ listening = 0
+ recorded = ""
+ else
+ return ..()
+
+/obj/item/device/assembly/voice/activate()
+ if(secured)
+ if(!holder)
+ listening = !listening
+ say("[listening ? "Now" : "No longer"] recording input.")
+
+/obj/item/device/assembly/voice/attack_self(mob/user)
+ if(!user)
+ return 0
+ activate()
+ return 1
+
+/obj/item/device/assembly/voice/toggle_secure()
+ . = ..()
+ listening = 0
diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm
index 952ee0e068..9e14bcdad1 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -80,8 +80,8 @@
var/shorted = 0
var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone
- var/frequency = 1439
- var/alarm_frequency = 1437
+ var/frequency = FREQ_ATMOS_CONTROL
+ var/alarm_frequency = FREQ_ATMOS_ALARMS
var/datum/radio_frequency/radio_connection
var/list/TLV = list( // Breathable air.
@@ -427,21 +427,16 @@
/obj/machinery/airalarm/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
- radio_connection = SSradio.add_object(src, frequency, GLOB.RADIO_TO_AIRALARM)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_TO_AIRALARM)
/obj/machinery/airalarm/proc/send_signal(target, list/command)//sends signal 'command' to 'target'. Returns 0 if no radio connection, 1 otherwise
if(!radio_connection)
return 0
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = command
+ var/datum/signal/signal = new(command)
signal.data["tag"] = target
signal.data["sigtype"] = "command"
-
- radio_connection.post_signal(src, signal, GLOB.RADIO_FROM_AIRALARM)
+ radio_connection.post_signal(src, signal, RADIO_FROM_AIRALARM)
return 1
@@ -632,12 +627,10 @@
var/area/A = get_area(src)
- var/datum/signal/alert_signal = new
- alert_signal.source = src
- alert_signal.transmission_method = 1
- alert_signal.data["zone"] = A.name
- alert_signal.data["type"] = "Atmospheric"
-
+ var/datum/signal/alert_signal = new(list(
+ "zone" = A.name,
+ "type" = "Atmospheric"
+ ))
if(alert_level==2)
alert_signal.data["alert"] = "severe"
else if (alert_level==1)
@@ -645,7 +638,7 @@
else if (alert_level==0)
alert_signal.data["alert"] = "clear"
- frequency.post_signal(src, alert_signal,null,-1)
+ frequency.post_signal(src, alert_signal, range = -1)
/obj/machinery/airalarm/proc/apply_danger_level()
var/area/A = get_area(src)
@@ -742,7 +735,7 @@
return
return ..()
-
+
/obj/machinery/airalarm/AltClick(mob/user)
..()
if(!issilicon(user) && (!user.canUseTopic(src, be_close=TRUE) || !isturf(loc)))
@@ -750,7 +743,7 @@
return
else
togglelock(user)
-
+
/obj/machinery/airalarm/proc/togglelock(mob/living/user)
if(stat & (NOPOWER|BROKEN))
to_chat(user, "It does nothing!")
diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm
index 6c335bf896..0dca88ade0 100644
--- a/code/modules/atmospherics/machinery/atmosmachinery.dm
+++ b/code/modules/atmospherics/machinery/atmosmachinery.dm
@@ -346,10 +346,7 @@ Pipelines + Other Objects -> Pipe network
return list()
/obj/machinery/atmospherics/update_remote_sight(mob/user)
- if(isborer(user))
- user.sight |= (SEE_PIXELS)
- else
- user.sight |= (SEE_TURFS|BLIND)
+ user.sight |= (SEE_TURFS|BLIND)
//Used for certain children of obj/machinery/atmospherics to not show pipe vision when mob is inside it.
/obj/machinery/atmospherics/proc/can_see_pipes()
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm
index ef6dd85afa..36462a3eb6 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/circulator.dm
@@ -15,6 +15,7 @@
anchored = TRUE
density = TRUE
+
var/global/const/CIRC_LEFT = 1
var/global/const/CIRC_RIGHT = 2
@@ -39,6 +40,8 @@
var/transfer_moles = pressure_delta*air1.volume/(air2.temperature * R_IDEAL_GAS_EQUATION)
last_pressure_delta = pressure_delta
+
+ //Actually transfer the gas
var/datum/gas_mixture/removed = air2.remove(transfer_moles)
update_parents()
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
index f8204947f1..0bb6c629e0 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/dp_vent_pump.dm
@@ -131,17 +131,13 @@ Acts like a normal vent, but has an input AND output.
SSradio.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
- radio_connection = SSradio.add_object(src, frequency, filter = GLOB.RADIO_ATMOSIA)
+ radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
/obj/machinery/atmospherics/components/binary/dp_vent_pump/proc/broadcast_status()
if(!radio_connection)
return
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
+ var/datum/signal/signal = new(list(
"tag" = id,
"device" = "ADVP",
"power" = on,
@@ -151,8 +147,8 @@ Acts like a normal vent, but has an input AND output.
"output" = output_pressure_max,
"external" = external_pressure_bound,
"sigtype" = "status"
- )
- radio_connection.post_signal(src, signal, filter = GLOB.RADIO_ATMOSIA)
+ ))
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
/obj/machinery/atmospherics/components/binary/dp_vent_pump/atmosinit()
..()
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm
index 86c5375d07..8470695704 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/passive_gate.dm
@@ -72,25 +72,20 @@ Passive gate is similar to the regular pump except:
SSradio.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
- radio_connection = SSradio.add_object(src, frequency, filter = GLOB.RADIO_ATMOSIA)
+ radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
/obj/machinery/atmospherics/components/binary/passive_gate/proc/broadcast_status()
if(!radio_connection)
return
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
+ var/datum/signal/signal = new(list(
"tag" = id,
"device" = "AGP",
"power" = on,
"target_output" = target_pressure,
"sigtype" = "status"
- )
-
- radio_connection.post_signal(src, signal, filter = GLOB.RADIO_ATMOSIA)
+ ))
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
/obj/machinery/atmospherics/components/binary/passive_gate/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
diff --git a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
index 97bba0e534..176d6792bf 100644
--- a/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
+++ b/code/modules/atmospherics/machinery/components/binary_devices/pump.dm
@@ -75,25 +75,20 @@ Thus, the two variables affect pump operation are set in New():
SSradio.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
- radio_connection = SSradio.add_object(src, frequency, filter = GLOB.RADIO_ATMOSIA)
+ radio_connection = SSradio.add_object(src, frequency, filter = RADIO_ATMOSIA)
/obj/machinery/atmospherics/components/binary/pump/proc/broadcast_status()
if(!radio_connection)
return
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
+ var/datum/signal/signal = new(list(
"tag" = id,
"device" = "AGP",
"power" = on,
"target_output" = target_pressure,
"sigtype" = "status"
- )
-
- radio_connection.post_signal(src, signal, filter = GLOB.RADIO_ATMOSIA)
+ ))
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
/obj/machinery/atmospherics/components/binary/pump/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
index 4baeb3dd3e..5860633b28 100644
--- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
+++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm
@@ -29,7 +29,7 @@
SSradio.remove_object(src, frequency)
frequency = new_frequency
if(frequency)
- radio_connection = SSradio.add_object(src, frequency, GLOB.RADIO_ATMOSIA)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA)
/obj/machinery/atmospherics/components/trinary/filter/New()
..()
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
index a7123dd97b..b677db89a4 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm
@@ -42,7 +42,7 @@
radio = new(src)
radio.keyslot = new radio_key
- radio.subspace_transmission = 1
+ radio.subspace_transmission = TRUE
radio.canhear_range = 0
radio.recalculateChannels()
@@ -182,7 +182,7 @@
mob_occupant.Unconscious((mob_occupant.bodytemperature * unconscious_factor) * 2000)
if(beaker)
if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic.
- beaker.reagents.trans_to(occupant, 1, 10 * efficiency) // Transfer reagents, multiplied because cryo magic.
+ beaker.reagents.trans_to(occupant, 1, efficiency * 0.25) // Transfer reagents.
beaker.reagents.reaction(occupant, VAPOR)
air1.gases[/datum/gas/oxygen][MOLES] -= 2 / efficiency //Let's use gas for this
if(++reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker).
@@ -348,7 +348,6 @@
else
data["occupant"]["temperaturestatus"] = "bad"
-
var/datum/gas_mixture/air1 = AIR1
data["cellTemperature"] = round(air1.temperature, 1)
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
index 37bfb5d952..7162499a3f 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/outlet_injector.dm
@@ -93,19 +93,14 @@
if(!radio_connection)
return
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
- signal.data = list(
+ var/datum/signal/signal = new(list(
"tag" = id,
"device" = "AO",
"power" = on,
"volume_rate" = volume_rate,
//"timestamp" = world.time,
"sigtype" = "status"
- )
-
+ ))
radio_connection.post_signal(src, signal)
/obj/machinery/atmospherics/components/unary/outlet_injector/atmosinit()
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
index a05a13217d..311bca338a 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
@@ -26,7 +26,7 @@
// INT_BOUND: Do not pass internal_pressure_bound
// NO_BOUND: Do not pass either
- var/frequency = 1439
+ var/frequency = FREQ_ATMOS_CONTROL
var/datum/radio_frequency/radio_connection
var/radio_filter_out
var/radio_filter_in
@@ -178,11 +178,7 @@
if(!radio_connection)
return
- var/datum/signal/signal = new
- signal.transmission_method = 1 // radio signal
- signal.source = src
-
- signal.data = list(
+ var/datum/signal/signal = new(list(
"tag" = id_tag,
"frequency" = frequency,
"device" = "VP",
@@ -193,7 +189,7 @@
"internal" = internal_pressure_bound,
"external" = external_pressure_bound,
"sigtype" = "status"
- )
+ ))
var/area/A = get_area(src)
if(!A.air_vent_names[id_tag])
@@ -206,8 +202,8 @@
/obj/machinery/atmospherics/components/unary/vent_pump/atmosinit()
//some vents work his own spesial way
- radio_filter_in = frequency==1439?(GLOB.RADIO_FROM_AIRALARM):null
- radio_filter_out = frequency==1439?(GLOB.RADIO_TO_AIRALARM):null
+ radio_filter_in = frequency==FREQ_ATMOS_CONTROL?(RADIO_FROM_AIRALARM):null
+ radio_filter_out = frequency==FREQ_ATMOS_CONTROL?(RADIO_TO_AIRALARM):null
if(frequency)
set_frequency(frequency)
broadcast_status()
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
index b3ade6f0fb..2deefc17d0 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm
@@ -23,7 +23,7 @@
var/widenet = 0 //is this scrubber acting on the 3x3 area around it.
var/list/turf/adjacent_turfs = list()
- var/frequency = 1439
+ var/frequency = FREQ_ATMOS_CONTROL
var/datum/radio_frequency/radio_connection
var/radio_filter_out
var/radio_filter_in
@@ -81,7 +81,7 @@
icon_state = "scrub_off"
return
- if(scrubbing & SCRUBBING)
+ if(scrubbing & SCRUBBING)
if(widenet)
icon_state = "scrub_wide"
else
@@ -98,16 +98,12 @@
if(!radio_connection)
return FALSE
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
-
var/list/f_types = list()
for(var/path in GLOB.meta_gas_info)
var/list/gas = GLOB.meta_gas_info[path]
f_types += list(list("gas_id" = gas[META_GAS_ID], "gas_name" = gas[META_GAS_NAME], "enabled" = (path in filter_types)))
- signal.data = list(
+ var/datum/signal/signal = new(list(
"tag" = id_tag,
"frequency" = frequency,
"device" = "VS",
@@ -117,7 +113,7 @@
"widenet" = widenet,
"filter_types" = f_types,
"sigtype" = "status"
- )
+ ))
var/area/A = get_area(src)
if(!A.air_scrub_names[id_tag])
@@ -130,8 +126,8 @@
return TRUE
/obj/machinery/atmospherics/components/unary/vent_scrubber/atmosinit()
- radio_filter_in = frequency==initial(frequency)?(GLOB.RADIO_FROM_AIRALARM):null
- radio_filter_out = frequency==initial(frequency)?(GLOB.RADIO_TO_AIRALARM):null
+ radio_filter_in = frequency==initial(frequency)?(RADIO_FROM_AIRALARM):null
+ radio_filter_out = frequency==initial(frequency)?(RADIO_TO_AIRALARM):null
if(frequency)
set_frequency(frequency)
broadcast_status()
@@ -205,7 +201,7 @@
return TRUE
-//There is no easy way for an object to be notified of changes to atmos can pass flags_1
+//There is no easy way for an object to be notified of changes to atmos can pass flags
// So we check every machinery process (2 seconds)
/obj/machinery/atmospherics/components/unary/vent_scrubber/process()
if(widenet)
diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm
index a26b379735..ccddc8f8ac 100644
--- a/code/modules/atmospherics/machinery/other/meter.dm
+++ b/code/modules/atmospherics/machinery/other/meter.dm
@@ -77,15 +77,12 @@
if(!radio_connection)
return
- var/datum/signal/signal = new
- signal.source = src
- signal.transmission_method = 1
- signal.data = list(
+ var/datum/signal/signal = new(list(
"id_tag" = id_tag,
"device" = "AM",
"pressure" = round(env_pressure),
"sigtype" = "status"
- )
+ ))
radio_connection.post_signal(src, signal)
/obj/machinery/meter/proc/status()
diff --git a/code/modules/atmospherics/machinery/portable/pump.dm b/code/modules/atmospherics/machinery/portable/pump.dm
index 3f2bceaa04..db153d60a4 100644
--- a/code/modules/atmospherics/machinery/portable/pump.dm
+++ b/code/modules/atmospherics/machinery/portable/pump.dm
@@ -135,7 +135,7 @@
investigate_log("was set to [pump.target_pressure] kPa by [key_name(usr)].", INVESTIGATE_ATMOS)
if("eject")
if(holding)
- holding.loc = get_turf(src)
+ holding.forceMove(drop_location())
holding = null
. = TRUE
update_icon()
diff --git a/code/modules/atmospherics/machinery/portable/scrubber.dm b/code/modules/atmospherics/machinery/portable/scrubber.dm
index 564e6d294f..3ba7e0a110 100644
--- a/code/modules/atmospherics/machinery/portable/scrubber.dm
+++ b/code/modules/atmospherics/machinery/portable/scrubber.dm
@@ -96,7 +96,7 @@
. = TRUE
if("eject")
if(holding)
- holding.loc = get_turf(src)
+ holding.forceMove(drop_location())
holding = null
. = TRUE
if("toggle_filter")
diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm
index 8b640676ba..5627206edf 100644
--- a/code/modules/awaymissions/capture_the_flag.dm
+++ b/code/modules/awaymissions/capture_the_flag.dm
@@ -509,7 +509,7 @@
/datum/outfit/ctf/red/post_equip(mob/living/carbon/human/H)
..()
var/obj/item/device/radio/R = H.ears
- R.set_frequency(GLOB.REDTEAM_FREQ)
+ R.set_frequency(FREQ_CTF_RED)
R.freqlock = TRUE
R.independent = TRUE
H.dna.species.stunmod = 0
@@ -517,7 +517,7 @@
/datum/outfit/ctf/blue/post_equip(mob/living/carbon/human/H)
..()
var/obj/item/device/radio/R = H.ears
- R.set_frequency(GLOB.BLUETEAM_FREQ)
+ R.set_frequency(FREQ_CTF_BLUE)
R.freqlock = TRUE
R.independent = TRUE
H.dna.species.stunmod = 0
@@ -532,7 +532,6 @@
var/team = WHITE_TEAM
time_between_triggers = 1
anchored = TRUE
- flags_2 = SLOWS_WHILE_IN_HAND_2
alpha = 255
/obj/structure/trap/examine(mob/user)
diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm
index 1f5df77be7..db50d0c468 100644
--- a/code/modules/awaymissions/corpse.dm
+++ b/code/modules/awaymissions/corpse.dm
@@ -21,6 +21,7 @@
var/brute_damage = 0
var/oxy_damage = 0
var/burn_damage = 0
+ var/datum/disease/disease = null //Do they start with a pre-spawned disease?
var/mob_color //Change the mob's color
var/assignedrole
var/show_flavour = TRUE
@@ -70,6 +71,8 @@
M.gender = mob_gender
if(faction)
M.faction = list(faction)
+ if(disease)
+ M.ForceContractDisease(new disease)
if(death)
M.death(1) //Kills the new mob
@@ -259,6 +262,19 @@
///////////Civilians//////////////////////
+/obj/effect/mob_spawn/human/corpse/assistant
+ name = "Assistant"
+ outfit = /datum/outfit/job/assistant
+
+/obj/effect/mob_spawn/human/corpse/assistant/beesease_infection
+ disease = /datum/disease/beesease
+
+/obj/effect/mob_spawn/human/corpse/assistant/brainrot_infection
+ disease = /datum/disease/brainrot
+
+/obj/effect/mob_spawn/human/corpse/assistant/spanishflu_infection
+ disease = /datum/disease/fluspanish
+
/obj/effect/mob_spawn/human/cook
name = "Cook"
outfit = /datum/outfit/job/cook
diff --git a/code/modules/awaymissions/exile.dm b/code/modules/awaymissions/exile.dm
index 2c683e91c9..74a9a30d7c 100644
--- a/code/modules/awaymissions/exile.dm
+++ b/code/modules/awaymissions/exile.dm
@@ -1,13 +1,13 @@
-
-/obj/structure/closet/secure_closet/exile
- name = "exile implants"
+
+/obj/structure/closet/secure_closet/exile
+ name = "exile implants"
req_access = list(ACCESS_HOS)
-
-/obj/structure/closet/secure_closet/exile/New()
- ..()
- new /obj/item/implanter/exile(src)
- new /obj/item/implantcase/exile(src)
- new /obj/item/implantcase/exile(src)
- new /obj/item/implantcase/exile(src)
- new /obj/item/implantcase/exile(src)
+
+/obj/structure/closet/secure_closet/exile/New()
+ ..()
+ new /obj/item/implanter/exile(src)
+ new /obj/item/implantcase/exile(src)
+ new /obj/item/implantcase/exile(src)
+ new /obj/item/implantcase/exile(src)
+ new /obj/item/implantcase/exile(src)
new /obj/item/implantcase/exile(src)
\ No newline at end of file
diff --git a/code/modules/awaymissions/mission_code/Academy.dm b/code/modules/awaymissions/mission_code/Academy.dm
index 5af834955f..462bfa9a80 100644
--- a/code/modules/awaymissions/mission_code/Academy.dm
+++ b/code/modules/awaymissions/mission_code/Academy.dm
@@ -139,7 +139,7 @@
/obj/structure/academy_wizard_spawner/proc/summon_wizard()
var/turf/T = src.loc
var/mob/living/carbon/human/wizbody = new(T)
- wizbody.fully_replace_character_name("Academy Teacher")
+ wizbody.fully_replace_character_name(wizbody.real_name, "Academy Teacher")
wizbody.mind_initialize()
var/datum/mind/wizmind = wizbody.mind
wizmind.special_role = "Academy Defender"
diff --git a/code/modules/awaymissions/mission_code/caves.dm b/code/modules/awaymissions/mission_code/caves.dm
index 05885fbe19..fd2f8f18af 100644
--- a/code/modules/awaymissions/mission_code/caves.dm
+++ b/code/modules/awaymissions/mission_code/caves.dm
@@ -42,7 +42,7 @@
/obj/item/paper/fluff/awaymissions/caves/work_notice
name = "work notice"
- info = "
Survival Info For Miners
The caves are an unforgiving place, the only thing you'll have to traverse is the supplies in your locker and your own wit. Travel in packs when mining and try to shut down the monster dens before they overwhelm you. The job is dangerous but the haul is good, so remember this infomation and hopefully we'll all go home alive.
"
+ info = "
Survival Info For Miners
The caves are an unforgiving place, the only thing you'll have to traverse is the supplies in your locker and your own wit. Travel in packs when mining and try to shut down the monster dens before they overwhelm you. The job is dangerous but the haul is good, so remember this information and hopefully we'll all go home alive.
"
/obj/item/paper/fluff/awaymissions/caves/shipment_notice
name = "shipment notice"
diff --git a/code/modules/awaymissions/mission_code/centcomAway.dm b/code/modules/awaymissions/mission_code/centcomAway.dm
index 11c3f14012..082d2d3c9e 100644
--- a/code/modules/awaymissions/mission_code/centcomAway.dm
+++ b/code/modules/awaymissions/mission_code/centcomAway.dm
@@ -60,4 +60,4 @@
teams never did figure out what happened that last time... and I can't wrap my head \
around it myself. Why would a shuttle full of evacuees all snap and beat each other \
to death the moment they reached safety? \
- - D. Cereza"
+ - D. Cereza"
\ No newline at end of file
diff --git a/code/modules/awaymissions/mission_code/stationCollision.dm b/code/modules/awaymissions/mission_code/stationCollision.dm
index 4aa6e88249..65ed8f95b7 100644
--- a/code/modules/awaymissions/mission_code/stationCollision.dm
+++ b/code/modules/awaymissions/mission_code/stationCollision.dm
@@ -136,41 +136,18 @@ GLOBAL_VAR_INIT(sc_safecode5, "[rand(0,9)]")
/*
* Modified Nar-Sie
*/
-/obj/singularity/narsie/sc_Narsie
+/obj/singularity/narsie/mini
desc = "Your body becomes weak and your feel your mind slipping away as you try to comprehend what you know can't be possible."
move_self = 0 //Contianed narsie does not move!
grav_pull = 0 //Contained narsie does not pull stuff in!
- var/uneatable = list(/turf/open/space, /obj/effect/overlay, /mob/living/simple_animal/hostile/construct)
//Override this to prevent no adminlog runtimes and admin warnings about a singularity without containment
-/obj/singularity/narsie/sc_Narsie/admin_investigate_setup()
+/obj/singularity/narsie/mini/admin_investigate_setup()
return
-/obj/singularity/narsie/sc_Narsie/process()
+/obj/singularity/narsie/mini/process()
eat()
if(prob(25))
mezzer()
-/obj/singularity/narsie/sc_Narsie/consume(atom/A)
- if(is_type_in_list(A, uneatable))
- return 0
- if(isliving(A))
- var/mob/living/L = A
- L.gib()
- else if(istype(A, /obj/))
- var/obj/O = A
- O.ex_act(EXPLODE_DEVASTATE)
- if(O)
- qdel(O)
- else if(isturf(A))
- var/turf/T = A
- if(T.intact)
- for(var/obj/O in T.contents)
- if(O.level != 1)
- continue
- if(O.invisibility == INVISIBILITY_MAXIMUM)
- src.consume(O)
- T.ChangeTurf(/turf/open/space)
- return
-
-/obj/singularity/narsie/sc_Narsie/ex_act()
+/obj/singularity/narsie/mini/ex_act()
return
\ No newline at end of file
diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm
index 3031936d43..1fe8baba01 100644
--- a/code/modules/awaymissions/mission_code/wildwest.dm
+++ b/code/modules/awaymissions/mission_code/wildwest.dm
@@ -115,9 +115,11 @@
to_chat(user, "The Wish Granter punishes you for your wickedness, claiming your soul and warping your body to match the darkness in your heart.")
SSticker.mode.traitors += user.mind
user.mind.special_role = "traitor"
+
var/datum/objective/hijack/hijack = new
hijack.owner = user.mind
user.mind.objectives += hijack
+ user.mind.add_antag_datum(/datum/antagonist/auto_custom)
to_chat(user, "Your inhibitions are swept away, the bonds of loyalty broken, you are free to murder as you please!")
user.mind.announce_objectives()
user.set_species(/datum/species/shadow)
diff --git a/code/modules/awaymissions/pamphlet.dm b/code/modules/awaymissions/pamphlet.dm
index a1d12ae90a..94ebb91972 100644
--- a/code/modules/awaymissions/pamphlet.dm
+++ b/code/modules/awaymissions/pamphlet.dm
@@ -1,39 +1,39 @@
-/obj/item/paper/pamphlet
- name = "pamphlet"
- icon_state = "pamphlet"
+/obj/item/paper/pamphlet
+ name = "pamphlet"
+ icon_state = "pamphlet"
/obj/item/paper/pamphlet/gateway
- info = "Welcome to the Nanotrasen Gateway project... \
- Congratulations! If you're reading this, you and your superiors have decided that you're \
- ready to commit to a life spent colonising the rolling hills of far away worlds. You \
- must be ready for a lifetime of adventure, a little bit of hard work, and an award \
- winning dental plan- but that's not all the Nanotrasen Gateway project has to offer. \
- Because we care about you, we feel it is only fair to make sure you know the risks \
- before you commit to joining the Nanotrasen Gateway project. All away destinations have \
- been fully scanned by a Nanotrasen expeditionary team, and are certified to be 100% safe. \
- We've even left a case of space beer along with the basic materials you'll need to expand \
- Nanotrasen's operational area and start your new life.
\
- Gateway Operation Basics \
- All Nanotrasen approved Gateways operate on the same basic principals. They operate off \
- area equipment power as you would expect, and without this supply, it cannot safely function, \
- causinng it to reject all attempts at operation.
\
- Once it is correctly setup, and once it has enough power to operate, the Gateway will begin \
- searching for an output location. The amount of time this takes is variable, but the Gateway \
- interface will give you an estimate accurate to the minute. Power loss will not interrupt the \
- searching process. Influenza will not interrupt the searching process. Temporal anomalies \
- may cause the estimate to be inaccurate, but will not interrupt the searching process.
\
- Life On The Other Side \
- Once you have traversed the Gateway, you may experience some disorientation. Do not panic. \
- This is a normal side effect of travelling vast distances in a short period of time. You should \
- survey the immediate area, and attempt to locate your complimentary case of space beer. Our \
- expeditionary teams have ensured the complete safety of all away locations, but in a small \
- number of cases, the Gateway they have established may not be immediately obvious. \
- Do not panic if you cannot locate the return Gateway. Begin colonisation of the destination. \
-
A New World \
- As a participant in the Nanotrasen Gateway Project, you will be on the frontiers of space. \
- Though complete safety is assured, participants are advised to prepare for inhospitable \
- environs."
-
-//we don't want the silly text overlay!
-/obj/item/paper/pamphlet/update_icon()
- return
+ info = "Welcome to the Nanotrasen Gateway project... \
+ Congratulations! If you're reading this, you and your superiors have decided that you're \
+ ready to commit to a life spent colonising the rolling hills of far away worlds. You \
+ must be ready for a lifetime of adventure, a little bit of hard work, and an award \
+ winning dental plan- but that's not all the Nanotrasen Gateway project has to offer. \
+ Because we care about you, we feel it is only fair to make sure you know the risks \
+ before you commit to joining the Nanotrasen Gateway project. All away destinations have \
+ been fully scanned by a Nanotrasen expeditionary team, and are certified to be 100% safe. \
+ We've even left a case of space beer along with the basic materials you'll need to expand \
+ Nanotrasen's operational area and start your new life.
\
+ Gateway Operation Basics \
+ All Nanotrasen approved Gateways operate on the same basic principals. They operate off \
+ area equipment power as you would expect, and without this supply, it cannot safely function, \
+ causinng it to reject all attempts at operation.
\
+ Once it is correctly setup, and once it has enough power to operate, the Gateway will begin \
+ searching for an output location. The amount of time this takes is variable, but the Gateway \
+ interface will give you an estimate accurate to the minute. Power loss will not interrupt the \
+ searching process. Influenza will not interrupt the searching process. Temporal anomalies \
+ may cause the estimate to be inaccurate, but will not interrupt the searching process.
\
+ Life On The Other Side \
+ Once you have traversed the Gateway, you may experience some disorientation. Do not panic. \
+ This is a normal side effect of travelling vast distances in a short period of time. You should \
+ survey the immediate area, and attempt to locate your complimentary case of space beer. Our \
+ expeditionary teams have ensured the complete safety of all away locations, but in a small \
+ number of cases, the Gateway they have established may not be immediately obvious. \
+ Do not panic if you cannot locate the return Gateway. Begin colonisation of the destination. \
+
A New World \
+ As a participant in the Nanotrasen Gateway Project, you will be on the frontiers of space. \
+ Though complete safety is assured, participants are advised to prepare for inhospitable \
+ environs."
+
+//we don't want the silly text overlay!
+/obj/item/paper/pamphlet/update_icon()
+ return
diff --git a/code/modules/awaymissions/super_secret_room.dm b/code/modules/awaymissions/super_secret_room.dm
index b1f505a27e..4b25d768f4 100644
--- a/code/modules/awaymissions/super_secret_room.dm
+++ b/code/modules/awaymissions/super_secret_room.dm
@@ -124,4 +124,4 @@
..()
/obj/effect/landmark/error
- name = "error"
\ No newline at end of file
+ name = "error"
diff --git a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm
index 3fcb0648a1..296c876688 100644
--- a/code/modules/cargo/console.dm
+++ b/code/modules/cargo/console.dm
@@ -201,14 +201,10 @@
/obj/machinery/computer/cargo/proc/post_signal(command)
- var/datum/radio_frequency/frequency = SSradio.return_frequency(1435)
+ var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS)
if(!frequency)
return
- var/datum/signal/status_signal = new
- status_signal.source = src
- status_signal.transmission_method = 1
- status_signal.data["command"] = command
-
+ var/datum/signal/status_signal = new(list("command" = command))
frequency.post_signal(src, status_signal)
diff --git a/code/modules/cargo/exports/research.dm b/code/modules/cargo/exports/research.dm
index b1ac30e7f9..d2d11cecd1 100644
--- a/code/modules/cargo/exports/research.dm
+++ b/code/modules/cargo/exports/research.dm
@@ -12,8 +12,8 @@
if(sold_nodes[V]) //Already sold before, don't want it.
continue
var/datum/techweb_node/TWN = D.stored_research.researched_nodes[V]
- cost += TWN
- return ..() * cost
+ cost += TWN.export_price
+ return cost
/datum/export/tech/sell_object(obj/O)
..()
diff --git a/code/modules/client/asset_cache.dm b/code/modules/client/asset_cache.dm
index 3704494050..4af0e4dc7f 100644
--- a/code/modules/client/asset_cache.dm
+++ b/code/modules/client/asset_cache.dm
@@ -324,6 +324,9 @@ GLOBAL_LIST_EMPTY(asset_datums)
"chevron.png" = 'html/chevron.png',
"chevron-expand.png" = 'html/chevron-expand.png',
"scales.png" = 'html/scales.png',
+ "coding.png" = 'html/coding.png',
+ "ban.png" = 'html/ban.png',
+ "chrome-wrench.png" = 'html/chrome-wrench.png',
"changelog.css" = 'html/changelog.css'
)
diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm
index dbbe6ea512..9ae87488ce 100644
--- a/code/modules/client/client_defines.dm
+++ b/code/modules/client/client_defines.dm
@@ -68,3 +68,6 @@
var/datum/chatOutput/chatOutput
+ var/list/credits //lazy list of all credit object bound to this client
+
+ var/datum/player_details/player_details //these persist between logins/logouts during the same round.
\ No newline at end of file
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index cb1712dff5..eec1f6f198 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -76,6 +76,7 @@
//Logs all hrefs, except chat pings
if(!(href_list["_src_"] == "chat" && href_list["proc"] == "ping" && LAZYLEN(href_list) == 2))
WRITE_FILE(GLOB.world_href_log, "[time_stamp(show_ds = TRUE)] [src] (usr:[usr]) || [hsrc ? "[hsrc] " : ""][href] ")
+
// Admin PM
if(href_list["priv_msg"])
cmd_admin_pm(href_list["priv_msg"],null)
@@ -195,13 +196,10 @@ GLOBAL_LIST(external_rsc_urls)
if(!prefs)
prefs = new /datum/preferences(src)
GLOB.preferences_datums[ckey] = prefs
- else
- prefs.parent = src
prefs.last_ip = address //these are gonna be used for banning
prefs.last_id = computer_id //these are gonna be used for banning
if(world.byond_version >= 511 && byond_version >= 511 && prefs.clientfps)
vars["fps"] = prefs.clientfps
- sethotkeys(1) //set hoykeys from preferences (from_pref = 1)
log_access("Login: [key_name(src)] from [address ? address : "localhost"]-[computer_id] || BYOND v[byond_version]")
var/alert_mob_dupe_login = FALSE
@@ -227,8 +225,17 @@ GLOBAL_LIST(external_rsc_urls)
message_admins("Notice: [key_name_admin(src)] has the same [matches] as [key_name_admin(C)] (no longer logged in). ")
log_access("Notice: [key_name(src)] has the same [matches] as [key_name(C)] (no longer logged in).")
+ if(GLOB.player_details[ckey])
+ player_details = GLOB.player_details[ckey]
+ else
+ player_details = new
+ GLOB.player_details[ckey] = player_details
+
+
. = ..() //calls mob.Login()
+ set_macros()
+
chatOutput.start() // Starts the chat
if(alert_mob_dupe_login)
@@ -364,6 +371,8 @@ GLOBAL_LIST(external_rsc_urls)
//////////////
/client/Del()
+ if(credits)
+ QDEL_LIST(credits)
log_access("Logout: [key_name(src)]")
if(holder)
adminGreet(1)
@@ -372,30 +381,18 @@ GLOBAL_LIST(external_rsc_urls)
if (!GLOB.admins.len && SSticker.IsRoundInProgress()) //Only report this stuff if we are currently playing.
var/cheesy_message = pick(
"I have no admins online!",\
- "I'm all alone... :(",\
- "I'm feeling lonely. :(",\
- "I'm so lonely. :(",\
+ "I'm all alone :(",\
+ "I'm feeling lonely :(",\
+ "I'm so lonely :(",\
"Why does nobody love me? :(",\
- "I want a man. :(",\
+ "I want a man :(",\
"Where has everyone gone?",\
- "I need a hug. :(",\
- "Someone come hold me. :(",\
+ "I need a hug :(",\
+ "Someone come hold me :(",\
"I need someone on me :(",\
"What happened? Where has everyone gone?",\
- "My nipples are so stiff, but Zelda ain't here. :(",\
- "Leon senpai, play more Spessmans. :(",\
- "If only Serdy were here...",\
- "Panic bunker can't keep my love for you out.",\
- "Cebu needs to Awoo herself back into my heart.",\
- "I don't even have a Turry to snuggle viciously here.",\
- "MOM, WHERE ARE YOU??? D:",\
- "It's a beautiful day outside. Birds are singing, flowers are blooming. On days like this...kids like you...SHOULD BE BURNING IN HELL.",\
- "Sometimes when I have sex, I think about putting an entire peanut butter and jelly sandwich in the VCR.",\
- "Oh good, no-one around to watch me lick Goofball's nipples. :D",\
- "I've replaced Beepsky with a fidget spinner, glory be autism abuse.",\
- "i shure hop dere are no PRED arund!!!!",\
- "NO PRED CAN eVER CATCH MI"\
- )
+ "Forever alone :("\
+ )
send2irc("Server", "[cheesy_message] (No admins online)")
diff --git a/code/modules/client/player_details.dm b/code/modules/client/player_details.dm
new file mode 100644
index 0000000000..a842607235
--- /dev/null
+++ b/code/modules/client/player_details.dm
@@ -0,0 +1,2 @@
+/datum/player_details
+ var/list/player_actions = list()
\ No newline at end of file
diff --git a/code/modules/client/preferences_toggles.dm b/code/modules/client/preferences_toggles.dm
index fba2c486ab..255423a4fc 100644
--- a/code/modules/client/preferences_toggles.dm
+++ b/code/modules/client/preferences_toggles.dm
@@ -30,7 +30,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_ears)(
usr.client.prefs.chat_toggles ^= CHAT_GHOSTEARS
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTEARS) ? "see all speech in the world" : "only see speech from nearby mobs"].")
usr.client.prefs.save_preferences()
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost Ears", "[usr.client.prefs.chat_toggles & CHAT_GHOSTEARS]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost Ears", "[usr.client.prefs.chat_toggles & CHAT_GHOSTEARS ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_ears/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTEARS
@@ -41,7 +41,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_sight)
usr.client.prefs.chat_toggles ^= CHAT_GHOSTSIGHT
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTSIGHT) ? "see all emotes in the world" : "only see emotes from nearby mobs"].")
usr.client.prefs.save_preferences()
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost Sight", "[usr.client.prefs.chat_toggles & CHAT_GHOSTSIGHT]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost Sight", "[usr.client.prefs.chat_toggles & CHAT_GHOSTSIGHT ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_sight/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTSIGHT
@@ -52,7 +52,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_whispe
usr.client.prefs.chat_toggles ^= CHAT_GHOSTWHISPER
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTWHISPER) ? "see all whispers in the world" : "only see whispers from nearby mobs"].")
usr.client.prefs.save_preferences()
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost Whispers", "[usr.client.prefs.chat_toggles & CHAT_GHOSTWHISPER]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost Whispers", "[usr.client.prefs.chat_toggles & CHAT_GHOSTWHISPER ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_whispers/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTWHISPER
@@ -63,7 +63,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_radio)
usr.client.prefs.chat_toggles ^= CHAT_GHOSTRADIO
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTRADIO) ? "see radio chatter" : "not see radio chatter"].")
usr.client.prefs.save_preferences()
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost Radio", "[usr.client.prefs.chat_toggles & CHAT_GHOSTRADIO]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! //social experiment, increase the generation whenever you copypaste this shamelessly GENERATION 1
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost Radio", "[usr.client.prefs.chat_toggles & CHAT_GHOSTRADIO ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! //social experiment, increase the generation whenever you copypaste this shamelessly GENERATION 1
/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_radio/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTRADIO
@@ -74,7 +74,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox, toggle_ghost_pda)()
usr.client.prefs.chat_toggles ^= CHAT_GHOSTPDA
to_chat(usr, "As a ghost, you will now [(usr.client.prefs.chat_toggles & CHAT_GHOSTPDA) ? "see all pda messages in the world" : "only see pda messages from nearby mobs"].")
usr.client.prefs.save_preferences()
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost PDA", "[usr.client.prefs.chat_toggles & CHAT_GHOSTPDA]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost PDA", "[usr.client.prefs.chat_toggles & CHAT_GHOSTPDA ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/verbs/menu/Settings/Ghost/chatterbox/toggle_ghost_pda/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_GHOSTPDA
@@ -89,7 +89,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox/Events, toggle_death
usr.client.prefs.toggles ^= DISABLE_DEATHRATTLE
usr.client.prefs.save_preferences()
to_chat(usr, "You will [(usr.client.prefs.toggles & DISABLE_DEATHRATTLE) ? "no longer" : "now"] get messages when a sentient mob dies.")
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Deathrattle", "[!(usr.client.prefs.toggles & DISABLE_DEATHRATTLE)]")) //If you are copy-pasting this, maybe you should spend some time reading the comments.
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Deathrattle", "[!(usr.client.prefs.toggles & DISABLE_DEATHRATTLE) ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, maybe you should spend some time reading the comments.
/datum/verbs/menu/Settings/Ghost/chatterbox/Events/toggle_deathrattle/Get_checked(client/C)
return !(C.prefs.toggles & DISABLE_DEATHRATTLE)
@@ -100,7 +100,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost/chatterbox/Events, toggle_arriv
usr.client.prefs.toggles ^= DISABLE_ARRIVALRATTLE
to_chat(usr, "You will [(usr.client.prefs.toggles & DISABLE_ARRIVALRATTLE) ? "no longer" : "now"] get messages when someone joins the station.")
usr.client.prefs.save_preferences()
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Arrivalrattle", "[!(usr.client.prefs.toggles & DISABLE_ARRIVALRATTLE)]")) //If you are copy-pasting this, maybe you should rethink where your life went so wrong.
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Arrivalrattle", "[!(usr.client.prefs.toggles & DISABLE_ARRIVALRATTLE) ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, maybe you should rethink where your life went so wrong.
/datum/verbs/menu/Settings/Ghost/chatterbox/Events/toggle_arrivalrattle/Get_checked(client/C)
return !(C.prefs.toggles & DISABLE_ARRIVALRATTLE)
@@ -111,7 +111,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Ghost, togglemidroundantag)()
usr.client.prefs.toggles ^= MIDROUND_ANTAG
usr.client.prefs.save_preferences()
to_chat(usr, "You will [(usr.client.prefs.toggles & MIDROUND_ANTAG) ? "now" : "no longer"] be considered for midround antagonist positions.")
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Midround Antag", "[usr.client.prefs.toggles & MIDROUND_ANTAG]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Midround Antag", "[usr.client.prefs.toggles & MIDROUND_ANTAG ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/verbs/menu/Settings/Ghost/togglemidroundantag/Get_checked(client/C)
return C.prefs.toggles & MIDROUND_ANTAG
@@ -128,7 +128,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggletitlemusic)()
else
to_chat(usr, "You will no longer hear music in the game lobby.")
usr.stop_sound_channel(CHANNEL_LOBBYMUSIC)
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Lobby Music", "[usr.client.prefs.toggles & SOUND_LOBBY]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Lobby Music", "[usr.client.prefs.toggles & SOUND_LOBBY ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/verbs/menu/Settings/Sound/toggletitlemusic/Get_checked(client/C)
return C.prefs.toggles & SOUND_LOBBY
@@ -147,7 +147,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, togglemidis)()
var/client/C = usr.client
if(C && C.chatOutput && !C.chatOutput.broken && C.chatOutput.loaded)
C.chatOutput.sendMusic(" ")
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Hearing Midis", "[usr.client.prefs.toggles & SOUND_MIDI]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Hearing Midis", "[usr.client.prefs.toggles & SOUND_MIDI ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/verbs/menu/Settings/Sound/togglemidis/Get_checked(client/C)
return C.prefs.toggles & SOUND_MIDI
@@ -162,7 +162,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggle_instruments)()
to_chat(usr, "You will now hear people playing musical instruments.")
else
to_chat(usr, "You will no longer hear musical instruments.")
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Instruments", "[usr.client.prefs.toggles & SOUND_INSTRUMENTS]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Instruments", "[usr.client.prefs.toggles & SOUND_INSTRUMENTS ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/verbs/menu/Settings/Sound/toggle_instruments/Get_checked(client/C)
return C.prefs.toggles & SOUND_INSTRUMENTS
@@ -179,7 +179,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, Toggle_Soundscape)()
to_chat(usr, "You will no longer hear ambient sounds.")
usr.stop_sound_channel(CHANNEL_AMBIENCE)
usr.stop_sound_channel(CHANNEL_BUZZ)
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ambience", "[usr.client.prefs.toggles & SOUND_AMBIENCE]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ambience", "[usr.client.prefs.toggles & SOUND_AMBIENCE ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/verbs/menu/Settings/Sound/Toggle_Soundscape/Get_checked(client/C)
return C.prefs.toggles & SOUND_AMBIENCE
@@ -196,7 +196,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggle_ship_ambience)()
to_chat(usr, "You will no longer hear ship ambience.")
usr.stop_sound_channel(CHANNEL_BUZZ)
usr.client.ambience_playing = 0
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ship Ambience", "[usr.client.prefs.toggles & SOUND_SHIP_AMBIENCE]")) //If you are copy-pasting this, I bet you read this comment expecting to see the same thing :^)
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ship Ambience", "[usr.client.prefs.toggles & SOUND_SHIP_AMBIENCE ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, I bet you read this comment expecting to see the same thing :^)
/datum/verbs/menu/Settings/Sound/toggle_ship_ambience/Get_checked(client/C)
return C.prefs.toggles & SOUND_SHIP_AMBIENCE
@@ -208,7 +208,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggle_announcement_sound)()
usr.client.prefs.toggles ^= SOUND_ANNOUNCEMENTS
to_chat(usr, "You will now [(usr.client.prefs.toggles & SOUND_ANNOUNCEMENTS) ? "hear announcement sounds" : "no longer hear announcements"].")
usr.client.prefs.save_preferences()
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Announcement Sound", "[usr.client.prefs.toggles & SOUND_ANNOUNCEMENTS]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Announcement Sound", "[usr.client.prefs.toggles & SOUND_ANNOUNCEMENTS ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/verbs/menu/Settings/Sound/toggle_announcement_sound/Get_checked(client/C)
return C.prefs.toggles & SOUND_ANNOUNCEMENTS
@@ -223,7 +223,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings/Sound, toggleprayersounds)()
to_chat(usr, "You will now hear prayer sounds.")
else
to_chat(usr, "You will no longer prayer sounds.")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Prayer Sounds", "[usr.client.prefs.toggles & SOUND_PRAYERS]"))
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Prayer Sounds", "[usr.client.prefs.toggles & SOUND_PRAYERS ? "Enabled" : "Disabled"]"))
/datum/verbs/menu/Settings/Sound/toggleprayersounds/Get_checked(client/C)
return C.prefs.toggles & SOUND_PRAYERS
@@ -246,7 +246,7 @@ TOGGLE_CHECKBOX(/datum/verbs/menu/Settings, listen_ooc)()
usr.client.prefs.chat_toggles ^= CHAT_OOC
usr.client.prefs.save_preferences()
to_chat(usr, "You will [(usr.client.prefs.chat_toggles & CHAT_OOC) ? "now" : "no longer"] see messages on the OOC channel.")
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Seeing OOC", "[usr.client.prefs.chat_toggles & CHAT_OOC]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Seeing OOC", "[usr.client.prefs.chat_toggles & CHAT_OOC ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/verbs/menu/Settings/listen_ooc/Get_checked(client/C)
return C.prefs.chat_toggles & CHAT_OOC
@@ -337,7 +337,7 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
prefs.toggles ^= INTENT_STYLE
to_chat(src, "[(prefs.toggles & INTENT_STYLE) ? "Clicking directly on intents selects them." : "Clicking on intents rotates selection clockwise."]")
prefs.save_preferences()
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Intent Selection", "[prefs.toggles & INTENT_STYLE]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Intent Selection", "[prefs.toggles & INTENT_STYLE ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggle_ghost_hud_pref()
set name = "Toggle Ghost HUD"
@@ -349,7 +349,7 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
prefs.save_preferences()
if(isobserver(mob))
mob.hud_used.show_hud()
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost HUD", "[prefs.ghost_hud]"))
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost HUD", "[prefs.ghost_hud ? "Enabled" : "Disabled"]"))
/client/verb/toggle_inquisition() // warning: unexpected inquisition
set name = "Toggle Inquisitiveness"
@@ -362,7 +362,7 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
to_chat(src, "You will now examine everything you click on.")
else
to_chat(src, "You will no longer examine things you click on.")
- SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost Inquisitiveness", "[prefs.inquisitive_ghost]"))
+ SSblackbox.record_feedback("nested tally", "preferences_verb", 1, list("Toggle Ghost Inquisitiveness", "[prefs.inquisitive_ghost ? "Enabled" : "Disabled"]"))
//Admin Preferences
/client/proc/toggleadminhelpsound()
@@ -374,7 +374,7 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
prefs.toggles ^= SOUND_ADMINHELP
prefs.save_preferences()
to_chat(usr, "You will [(prefs.toggles & SOUND_ADMINHELP) ? "now" : "no longer"] hear a sound when adminhelps arrive.")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Adminhelp Sound", "[prefs.toggles & SOUND_ADMINHELP]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Adminhelp Sound", "[prefs.toggles & SOUND_ADMINHELP ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggleannouncelogin()
set name = "Do/Don't Announce Login"
@@ -385,7 +385,7 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
prefs.toggles ^= ANNOUNCE_LOGIN
prefs.save_preferences()
to_chat(usr, "You will [(prefs.toggles & ANNOUNCE_LOGIN) ? "now" : "no longer"] have an announcement to other admins when you login.")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Login Announcement", "[prefs.toggles & ANNOUNCE_LOGIN]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Login Announcement", "[prefs.toggles & ANNOUNCE_LOGIN ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggle_hear_radio()
set name = "Show/Hide Radio Chatter"
@@ -396,7 +396,7 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
prefs.chat_toggles ^= CHAT_RADIO
prefs.save_preferences()
to_chat(usr, "You will [(prefs.chat_toggles & CHAT_RADIO) ? "now" : "no longer"] see radio chatter from nearby radios or speakers")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Radio Chatter", "[prefs.chat_toggles & CHAT_RADIO]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Radio Chatter", "[prefs.chat_toggles & CHAT_RADIO ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/deadchat()
set name = "Show/Hide Deadchat"
@@ -405,7 +405,7 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
prefs.chat_toggles ^= CHAT_DEAD
prefs.save_preferences()
to_chat(src, "You will [(prefs.chat_toggles & CHAT_DEAD) ? "now" : "no longer"] see deadchat.")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Deadchat Visibility", "[prefs.chat_toggles & CHAT_DEAD]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Deadchat Visibility", "[prefs.chat_toggles & CHAT_DEAD ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggleprayers()
set name = "Show/Hide Prayers"
@@ -414,4 +414,4 @@ GLOBAL_LIST_INIT(ghost_orbits, list(GHOST_ORBIT_CIRCLE,GHOST_ORBIT_TRIANGLE,GHOS
prefs.chat_toggles ^= CHAT_PRAYER
prefs.save_preferences()
to_chat(src, "You will [(prefs.chat_toggles & CHAT_PRAYER) ? "now" : "no longer"] see prayerchat.")
- SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Prayer Visibility", "[prefs.chat_toggles & CHAT_PRAYER]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+ SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Prayer Visibility", "[prefs.chat_toggles & CHAT_PRAYER ? "Enabled" : "Disabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
diff --git a/code/modules/clothing/chameleon.dm b/code/modules/clothing/chameleon.dm
index dd876f3701..80195f6e39 100644
--- a/code/modules/clothing/chameleon.dm
+++ b/code/modules/clothing/chameleon.dm
@@ -170,30 +170,30 @@
var/obj/item/I = target
var/mob/living/M = owner
- var/flags_1 = I.slot_flags
- if(flags_1 & SLOT_OCLOTHING)
+ var/flags = I.slot_flags
+ if(flags & SLOT_OCLOTHING)
M.update_inv_wear_suit()
- if(flags_1 & SLOT_ICLOTHING)
+ if(flags & SLOT_ICLOTHING)
M.update_inv_w_uniform()
- if(flags_1 & SLOT_GLOVES)
+ if(flags & SLOT_GLOVES)
M.update_inv_gloves()
- if(flags_1 & SLOT_EYES)
+ if(flags & SLOT_EYES)
M.update_inv_glasses()
- if(flags_1 & SLOT_EARS)
+ if(flags & SLOT_EARS)
M.update_inv_ears()
- if(flags_1 & SLOT_MASK)
+ if(flags & SLOT_MASK)
M.update_inv_wear_mask()
- if(flags_1 & SLOT_HEAD)
+ if(flags & SLOT_HEAD)
M.update_inv_head()
- if(flags_1 & SLOT_FEET)
+ if(flags & SLOT_FEET)
M.update_inv_shoes()
- if(flags_1 & SLOT_ID)
+ if(flags & SLOT_ID)
M.update_inv_wear_id()
- if(flags_1 & SLOT_BELT)
+ if(flags & SLOT_BELT)
M.update_inv_belt()
- if(flags_1 & SLOT_BACK)
+ if(flags & SLOT_BACK)
M.update_inv_back()
- if(flags_1 & SLOT_NECK)
+ if(flags & SLOT_NECK)
M.update_inv_neck()
/obj/item/clothing/under/chameleon
diff --git a/code/modules/clothing/ears/_ears.dm b/code/modules/clothing/ears/_ears.dm
index 9d5433663e..b8f093dfa5 100644
--- a/code/modules/clothing/ears/_ears.dm
+++ b/code/modules/clothing/ears/_ears.dm
@@ -1,45 +1,46 @@
-//Ears: currently only used for headsets and earmuffs
-/obj/item/clothing/ears
- name = "ears"
- w_class = WEIGHT_CLASS_TINY
- throwforce = 0
- slot_flags = SLOT_EARS
- resistance_flags = NONE
-
-/obj/item/clothing/ears/earmuffs
- name = "earmuffs"
- desc = "Protects your hearing from loud noises, and quiet ones as well."
- icon_state = "earmuffs"
- item_state = "earmuffs"
- strip_delay = 15
- equip_delay_other = 25
- resistance_flags = FLAMMABLE
- flags_2 = BANG_PROTECT_2|HEALS_EARS_2
-
-/obj/item/clothing/ears/headphones
- name = "headphones"
- desc = "Unce unce unce unce. Boop!"
- icon = 'icons/obj/clothing/accessories.dmi'
- icon_state = "headphones"
- item_state = "headphones"
- slot_flags = SLOT_EARS | SLOT_HEAD | SLOT_NECK //Fluff item, put it whereever you want!
- actions_types = list(/datum/action/item_action/toggle_headphones)
- var/headphones_on = FALSE
-
-/obj/item/clothing/ears/headphones/Initialize()
- . = ..()
- update_icon()
-
-/obj/item/clothing/ears/headphones/update_icon()
- icon_state = "[initial(icon_state)]_[headphones_on? "on" : "off"]"
- item_state = "[initial(item_state)]_[headphones_on? "on" : "off"]"
-
-/obj/item/clothing/ears/headphones/proc/toggle(owner)
- headphones_on = !headphones_on
- update_icon()
- var/mob/living/carbon/human/H = owner
- if(istype(H))
- H.update_inv_ears()
- H.update_inv_neck()
- H.update_inv_head()
- to_chat(owner, "You turn the music [headphones_on? "on. Untz Untz Untz!" : "off."]")
+
+//Ears: currently only used for headsets and earmuffs
+/obj/item/clothing/ears
+ name = "ears"
+ w_class = WEIGHT_CLASS_TINY
+ throwforce = 0
+ slot_flags = SLOT_EARS
+ resistance_flags = NONE
+
+/obj/item/clothing/ears/earmuffs
+ name = "earmuffs"
+ desc = "Protects your hearing from loud noises, and quiet ones as well."
+ icon_state = "earmuffs"
+ item_state = "earmuffs"
+ strip_delay = 15
+ equip_delay_other = 25
+ resistance_flags = FLAMMABLE
+ flags_2 = BANG_PROTECT_2|HEALS_EARS_2
+
+/obj/item/clothing/ears/headphones
+ name = "headphones"
+ desc = "Unce unce unce unce. Boop!"
+ icon = 'icons/obj/clothing/accessories.dmi'
+ icon_state = "headphones"
+ item_state = "headphones"
+ slot_flags = SLOT_EARS | SLOT_HEAD | SLOT_NECK //Fluff item, put it whereever you want!
+ actions_types = list(/datum/action/item_action/toggle_headphones)
+ var/headphones_on = FALSE
+
+/obj/item/clothing/ears/headphones/Initialize()
+ . = ..()
+ update_icon()
+
+/obj/item/clothing/ears/headphones/update_icon()
+ icon_state = "[initial(icon_state)]_[headphones_on? "on" : "off"]"
+ item_state = "[initial(item_state)]_[headphones_on? "on" : "off"]"
+
+/obj/item/clothing/ears/headphones/proc/toggle(owner)
+ headphones_on = !headphones_on
+ update_icon()
+ var/mob/living/carbon/human/H = owner
+ if(istype(H))
+ H.update_inv_ears()
+ H.update_inv_neck()
+ H.update_inv_head()
+ to_chat(owner, "You turn the music [headphones_on? "on. Untz Untz Untz!" : "off."]")
diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm
index 4f108a505f..249cd6a1d9 100644
--- a/code/modules/clothing/gloves/color.dm
+++ b/code/modules/clothing/gloves/color.dm
@@ -4,7 +4,7 @@
icon_state = "yellow"
item_state = "ygloves"
siemens_coefficient = 0
- permeability_coefficient = 0.5
+ permeability_coefficient = 0.05
item_color="yellow"
resistance_flags = NONE
@@ -14,7 +14,7 @@
icon_state = "yellow"
item_state = "ygloves"
siemens_coefficient = 1 //Set to a default of 1, gets overridden in New()
- permeability_coefficient = 0.5
+ permeability_coefficient = 0.05
item_color="yellow"
resistance_flags = NONE
@@ -77,7 +77,7 @@
name = "insulated gloves"
desc = "These gloves will protect the wearer from electric shock."
siemens_coefficient = 0
- permeability_coefficient = 0.5
+ permeability_coefficient = 0.05
resistance_flags = NONE
/obj/item/clothing/gloves/color/rainbow
@@ -148,7 +148,7 @@
item_state = "egloves"
item_color = "captain"
siemens_coefficient = 0
- permeability_coefficient = 0.5
+ permeability_coefficient = 0.05
cold_protection = HANDS
min_cold_protection_temperature = GLOVES_MIN_TEMP_PROTECT
heat_protection = HANDS
@@ -162,7 +162,7 @@
icon_state = "latex"
item_state = "lgloves"
siemens_coefficient = 0.3
- permeability_coefficient = 0.1
+ permeability_coefficient = 0.01
item_color="white"
transfer_prints = TRUE
resistance_flags = NONE
diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm
index 9adc86e7f8..51a1131f1c 100644
--- a/code/modules/clothing/head/hardhat.dm
+++ b/code/modules/clothing/head/hardhat.dm
@@ -1,84 +1,84 @@
-/obj/item/clothing/head/hardhat
- name = "hard hat"
- desc = "A piece of headgear used in dangerous working conditions to protect the head. Comes with a built-in flashlight."
- icon_state = "hardhat0_yellow"
- item_state = "hardhat0_yellow"
- var/brightness_on = 4 //luminosity when on
+/obj/item/clothing/head/hardhat
+ name = "hard hat"
+ desc = "A piece of headgear used in dangerous working conditions to protect the head. Comes with a built-in flashlight."
+ icon_state = "hardhat0_yellow"
+ item_state = "hardhat0_yellow"
+ var/brightness_on = 4 //luminosity when on
var/on = FALSE
- item_color = "yellow" //Determines used sprites: hardhat[on]_[item_color] and hardhat[on]_[item_color]2 (lying down sprite)
- armor = list(melee = 15, bullet = 5, laser = 20,energy = 10, bomb = 20, bio = 10, rad = 20, fire = 100, acid = 50)
- flags_inv = 0
- actions_types = list(/datum/action/item_action/toggle_helmet_light)
- resistance_flags = FIRE_PROOF
+ item_color = "yellow" //Determines used sprites: hardhat[on]_[item_color] and hardhat[on]_[item_color]2 (lying down sprite)
+ armor = list(melee = 15, bullet = 5, laser = 20,energy = 10, bomb = 20, bio = 10, rad = 20, fire = 100, acid = 50)
+ flags_inv = 0
+ actions_types = list(/datum/action/item_action/toggle_helmet_light)
+ resistance_flags = FIRE_PROOF
dynamic_hair_suffix = "+generic"
-
- dog_fashion = /datum/dog_fashion/head
-
-/obj/item/clothing/head/hardhat/attack_self(mob/user)
- on = !on
- icon_state = "hardhat[on]_[item_color]"
- item_state = "hardhat[on]_[item_color]"
- user.update_inv_head() //so our mob-overlays update
-
- if(on)
- turn_on(user)
- else
- turn_off(user)
- for(var/X in actions)
- var/datum/action/A = X
- A.UpdateButtonIcon()
-
-/obj/item/clothing/head/hardhat/proc/turn_on(mob/user)
- set_light(brightness_on)
-
-/obj/item/clothing/head/hardhat/proc/turn_off(mob/user)
- set_light(0)
-
-/obj/item/clothing/head/hardhat/orange
- icon_state = "hardhat0_orange"
- item_state = "hardhat0_orange"
- item_color = "orange"
- dog_fashion = null
-
-/obj/item/clothing/head/hardhat/red
- icon_state = "hardhat0_red"
- item_state = "hardhat0_red"
- item_color = "red"
- dog_fashion = null
- name = "firefighter helmet"
+
+ dog_fashion = /datum/dog_fashion/head
+
+/obj/item/clothing/head/hardhat/attack_self(mob/user)
+ on = !on
+ icon_state = "hardhat[on]_[item_color]"
+ item_state = "hardhat[on]_[item_color]"
+ user.update_inv_head() //so our mob-overlays update
+
+ if(on)
+ turn_on(user)
+ else
+ turn_off(user)
+ for(var/X in actions)
+ var/datum/action/A = X
+ A.UpdateButtonIcon()
+
+/obj/item/clothing/head/hardhat/proc/turn_on(mob/user)
+ set_light(brightness_on)
+
+/obj/item/clothing/head/hardhat/proc/turn_off(mob/user)
+ set_light(0)
+
+/obj/item/clothing/head/hardhat/orange
+ icon_state = "hardhat0_orange"
+ item_state = "hardhat0_orange"
+ item_color = "orange"
+ dog_fashion = null
+
+/obj/item/clothing/head/hardhat/red
+ icon_state = "hardhat0_red"
+ item_state = "hardhat0_red"
+ item_color = "red"
+ dog_fashion = null
+ name = "firefighter helmet"
flags_1 = STOPSPRESSUREDMAGE_1
- heat_protection = HEAD
- max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT
- cold_protection = HEAD
- min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
-
-/obj/item/clothing/head/hardhat/white
- icon_state = "hardhat0_white"
- item_state = "hardhat0_white"
- item_color = "white"
+ heat_protection = HEAD
+ max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT
+ cold_protection = HEAD
+ min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
+
+/obj/item/clothing/head/hardhat/white
+ icon_state = "hardhat0_white"
+ item_state = "hardhat0_white"
+ item_color = "white"
flags_1 = STOPSPRESSUREDMAGE_1
- heat_protection = HEAD
- max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT
- cold_protection = HEAD
- min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
- dog_fashion = /datum/dog_fashion/head
-
-/obj/item/clothing/head/hardhat/dblue
- icon_state = "hardhat0_dblue"
- item_state = "hardhat0_dblue"
- item_color = "dblue"
- dog_fashion = null
-
-/obj/item/clothing/head/hardhat/atmos
- icon_state = "hardhat0_atmos"
- item_state = "hardhat0_atmos"
- item_color = "atmos"
- dog_fashion = null
- name = "atmospheric technician's firefighting helmet"
- desc = "A firefighter's helmet, able to keep the user cool in any situation."
+ heat_protection = HEAD
+ max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT
+ cold_protection = HEAD
+ min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
+ dog_fashion = /datum/dog_fashion/head
+
+/obj/item/clothing/head/hardhat/dblue
+ icon_state = "hardhat0_dblue"
+ item_state = "hardhat0_dblue"
+ item_color = "dblue"
+ dog_fashion = null
+
+/obj/item/clothing/head/hardhat/atmos
+ icon_state = "hardhat0_atmos"
+ item_state = "hardhat0_atmos"
+ item_color = "atmos"
+ dog_fashion = null
+ name = "atmospheric technician's firefighting helmet"
+ desc = "A firefighter's helmet, able to keep the user cool in any situation."
flags_1 = STOPSPRESSUREDMAGE_1 | THICKMATERIAL_1
- flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
- heat_protection = HEAD
- max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
- cold_protection = HEAD
- min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
+ heat_protection = HEAD
+ max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
+ cold_protection = HEAD
+ min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index 5691dbb782..15d4579d33 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -283,7 +283,7 @@
for(var/obj/item/device/flashlight/seclite/S in src)
to_chat(user, "You unscrew the seclite from [src].")
F = null
- S.loc = get_turf(user)
+ S.forceMove(user.drop_location())
update_helmlight(user)
S.update_brightness(user)
update_icon()
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index 9f09783df2..544d9e7b12 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -1,5 +1,7 @@
+
+
/obj/item/clothing/head/centhat
- name = "\improper Centcom hat"
+ name = "\improper CentCom hat"
icon_state = "centcom"
desc = "It's good to be emperor."
item_state = "that"
@@ -291,6 +293,18 @@
desc = "A simple straw hat."
icon_state = "scarecrow_hat"
+/obj/item/clothing/head/lobsterhat
+ name = "foam lobster head"
+ desc = "When everything's going to crab, protecting your head is the best choice."
+ icon_state = "lobster_hat"
+ flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
+
+/obj/item/clothing/head/drfreezehat
+ name = "doctor freeze's wig"
+ desc = "A cool wig for cool people."
+ icon_state = "drfreeze_hat"
+ flags_inv = HIDEHAIR
+
/obj/item/clothing/head/pharoah
name = "pharoah hat"
desc = "Walk like an Egyptian."
diff --git a/code/modules/clothing/outfits/ert.dm b/code/modules/clothing/outfits/ert.dm
index 58b4d1fffe..403b81211d 100644
--- a/code/modules/clothing/outfits/ert.dm
+++ b/code/modules/clothing/outfits/ert.dm
@@ -14,8 +14,8 @@
L.implant(H, null, 1)
var/obj/item/device/radio/R = H.ears
- R.set_frequency(GLOB.CENTCOM_FREQ)
- R.freqlock = 1
+ R.set_frequency(FREQ_CENTCOM)
+ R.freqlock = TRUE
var/obj/item/card/id/W = H.wear_id
W.registered_name = H.real_name
diff --git a/code/modules/clothing/outfits/standard.dm b/code/modules/clothing/outfits/standard.dm
index e16dd2a782..050c2fdc87 100644
--- a/code/modules/clothing/outfits/standard.dm
+++ b/code/modules/clothing/outfits/standard.dm
@@ -102,8 +102,8 @@
var/obj/item/device/radio/R = H.ears
if(R)
- R.set_frequency(GLOB.SYND_FREQ)
- R.freqlock = 1
+ R.set_frequency(FREQ_SYNDICATE)
+ R.freqlock = TRUE
var/obj/item/card/id/W = H.wear_id
if(W)
@@ -257,8 +257,8 @@
W.update_label()
var/obj/item/device/radio/headset/R = H.ears
- R.set_frequency(GLOB.CENTCOM_FREQ)
- R.freqlock = 1
+ R.set_frequency(FREQ_CENTCOM)
+ R.freqlock = TRUE
/datum/outfit/ghost_cultist
name = "Cultist Ghost"
@@ -396,8 +396,8 @@
return
var/obj/item/device/radio/R = H.ears
- R.set_frequency(GLOB.CENTCOM_FREQ)
- R.freqlock = 1
+ R.set_frequency(FREQ_CENTCOM)
+ R.freqlock = TRUE
var/obj/item/implant/mindshield/L = new/obj/item/implant/mindshield(H)//Here you go Deuryn
L.implant(H, null, 1)
diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm
index 1715636b57..2b25188b80 100644
--- a/code/modules/clothing/spacesuits/chronosuit.dm
+++ b/code/modules/clothing/spacesuits/chronosuit.dm
@@ -98,7 +98,7 @@
I.flags_1 &= ~NODROP_1
if(camera)
camera.remove_target_ui()
- camera.loc = user
+ camera.forceMove(user)
teleport_now.UpdateButtonIcon()
/obj/item/clothing/suit/space/chronos/proc/chronowalk(atom/location)
@@ -278,19 +278,19 @@
if(loc == user)
forceMove(get_turf(user))
if(user.client && user.client.eye != src)
- src.loc = get_turf(user)
+ src.forceMove(user.drop_location())
user.reset_perspective(src)
user.set_machine(src)
var/atom/step = get_step(src, direction)
if(step)
if((step.x <= TRANSITIONEDGE) || (step.x >= (world.maxx - TRANSITIONEDGE - 1)) || (step.y <= TRANSITIONEDGE) || (step.y >= (world.maxy - TRANSITIONEDGE - 1)))
if(!src.Move(step))
- src.loc = step
+ src.forceMove(step)
else
- src.loc = step
+ src.forceMove(step)
if((x == holder.x) && (y == holder.y) && (z == holder.z))
remove_target_ui()
- loc = user
+ forceMove(user)
else if(!target_ui)
create_target_ui()
phase_time = world.time + phase_time_length
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index cc1df785b5..8e2251980d 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -136,7 +136,7 @@
return
jetpack.turn_off()
- jetpack.loc = get_turf(src)
+ jetpack.forceMove(drop_location())
jetpack = null
to_chat(user, "You successfully remove the jetpack from [src].")
diff --git a/code/modules/clothing/suits/_suits.dm b/code/modules/clothing/suits/_suits.dm
index e934b77f38..0068c1e102 100644
--- a/code/modules/clothing/suits/_suits.dm
+++ b/code/modules/clothing/suits/_suits.dm
@@ -2,7 +2,7 @@
icon = 'icons/obj/clothing/suits.dmi'
name = "suit"
var/fire_resist = T0C+100
- allowed = list(/obj/item/tank/internals/emergency_oxygen)
+ allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0)
slot_flags = SLOT_OCLOTHING
var/blood_overlay_type = "suit"
diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm
index 7cbdb46f55..3e044108fb 100644
--- a/code/modules/clothing/suits/armor.dm
+++ b/code/modules/clothing/suits/armor.dm
@@ -354,7 +354,7 @@
item_state = "centcom"
w_class = WEIGHT_CLASS_BULKY
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- allowed = list(/obj/item/gun/energy, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals/emergency_oxygen)
+ allowed = list(/obj/item/gun/energy, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
flags_1 = THICKMATERIAL_1
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS
diff --git a/code/modules/clothing/suits/bio.dm b/code/modules/clothing/suits/bio.dm
index 11b60817ed..bfd4415b3a 100644
--- a/code/modules/clothing/suits/bio.dm
+++ b/code/modules/clothing/suits/bio.dm
@@ -21,7 +21,7 @@
flags_1 = THICKMATERIAL_1
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
slowdown = 1
- allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/pen, /obj/item/device/flashlight/pen, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray)
+ allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/pen, /obj/item/device/flashlight/pen, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray)
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 80, fire = 30, acid = 100)
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
strip_delay = 70
diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm
index bb379ae6f3..e6331eb8b8 100644
--- a/code/modules/clothing/suits/jobs.dm
+++ b/code/modules/clothing/suits/jobs.dm
@@ -20,7 +20,7 @@
item_state = "bio_suit"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
flags_inv = HIDEJUMPSUIT
- allowed = list(/obj/item/disk, /obj/item/stamp, /obj/item/reagent_containers/food/drinks/flask, /obj/item/melee, /obj/item/storage/lockbox/medal, /obj/item/device/assembly/flash/handheld, /obj/item/storage/box/matches, /obj/item/lighter, /obj/item/clothing/mask/cigarette, /obj/item/storage/fancy/cigarettes, /obj/item/tank/internals/emergency_oxygen)
+ allowed = list(/obj/item/disk, /obj/item/stamp, /obj/item/reagent_containers/food/drinks/flask, /obj/item/melee, /obj/item/storage/lockbox/medal, /obj/item/device/assembly/flash/handheld, /obj/item/storage/box/matches, /obj/item/lighter, /obj/item/clothing/mask/cigarette, /obj/item/storage/fancy/cigarettes, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
//Chaplain
/obj/item/clothing/suit/hooded/chaplain_hoodie
@@ -29,7 +29,7 @@
icon_state = "chaplain_hoodie"
item_state = "chaplain_hoodie"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
- allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen)
+ allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
hoodtype = /obj/item/clothing/head/hooded/chaplain_hood
/obj/item/clothing/head/hooded/chaplain_hood
@@ -46,7 +46,7 @@
item_state = "nun"
body_parts_covered = CHEST|GROIN|LEGS|ARMS|HANDS
flags_inv = HIDESHOES|HIDEJUMPSUIT
- allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen)
+ allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
/obj/item/clothing/suit/studentuni
name = "student robe"
@@ -54,7 +54,7 @@
icon_state = "studentuni"
item_state = "studentuni"
body_parts_covered = ARMS|CHEST
- allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen)
+ allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
/obj/item/clothing/suit/witchhunter
name = "witchunter garb"
@@ -62,7 +62,7 @@
icon_state = "witchhunter"
item_state = "witchhunter"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
- allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen)
+ allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
//Chef
/obj/item/clothing/suit/toggle/chef
diff --git a/code/modules/clothing/suits/labcoat.dm b/code/modules/clothing/suits/labcoat.dm
index f50f6eaf6a..abf609376b 100644
--- a/code/modules/clothing/suits/labcoat.dm
+++ b/code/modules/clothing/suits/labcoat.dm
@@ -1,48 +1,48 @@
-/obj/item/clothing/suit/toggle/labcoat
- name = "labcoat"
- desc = "A suit that protects against minor chemical spills."
- icon_state = "labcoat"
- item_state = "labcoat"
- blood_overlay_type = "coat"
- body_parts_covered = CHEST|ARMS
- allowed = list(/obj/item/device/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/device/healthanalyzer, /obj/item/device/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/soap, /obj/item/device/sensor_device, /obj/item/tank/internals/emergency_oxygen)
- armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 50, rad = 0, fire = 50, acid = 50)
- togglename = "buttons"
-
-/obj/item/clothing/suit/toggle/labcoat/cmo
- name = "chief medical officer's labcoat"
- desc = "Bluer than the standard model."
- icon_state = "labcoat_cmo"
- item_state = "labcoat_cmo"
-
-/obj/item/clothing/suit/toggle/labcoat/emt
- name = "EMT's jacket"
- desc = "A dark blue jacket with reflective strips for emergency medical technicians."
- icon_state = "labcoat_emt"
- item_state = "labcoat_cmo"
-
-/obj/item/clothing/suit/toggle/labcoat/mad
- name = "\improper The Mad's labcoat"
- desc = "It makes you look capable of konking someone on the noggin and shooting them into space."
- icon_state = "labgreen"
- item_state = "labgreen"
-
-/obj/item/clothing/suit/toggle/labcoat/genetics
- name = "geneticist labcoat"
- desc = "A suit that protects against minor chemical spills. Has a blue stripe on the shoulder."
- icon_state = "labcoat_gen"
-
-/obj/item/clothing/suit/toggle/labcoat/chemist
- name = "chemist labcoat"
- desc = "A suit that protects against minor chemical spills. Has an orange stripe on the shoulder."
- icon_state = "labcoat_chem"
-
-/obj/item/clothing/suit/toggle/labcoat/virologist
- name = "virologist labcoat"
- desc = "A suit that protects against minor chemical spills. Offers slightly more protection against biohazards than the standard model. Has a green stripe on the shoulder."
- icon_state = "labcoat_vir"
-
-/obj/item/clothing/suit/toggle/labcoat/science
- name = "scientist labcoat"
- desc = "A suit that protects against minor chemical spills. Has a purple stripe on the shoulder."
+/obj/item/clothing/suit/toggle/labcoat
+ name = "labcoat"
+ desc = "A suit that protects against minor chemical spills."
+ icon_state = "labcoat"
+ item_state = "labcoat"
+ blood_overlay_type = "coat"
+ body_parts_covered = CHEST|ARMS
+ allowed = list(/obj/item/device/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/device/healthanalyzer, /obj/item/device/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/soap, /obj/item/device/sensor_device, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
+ armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 50, rad = 0, fire = 50, acid = 50)
+ togglename = "buttons"
+
+/obj/item/clothing/suit/toggle/labcoat/cmo
+ name = "chief medical officer's labcoat"
+ desc = "Bluer than the standard model."
+ icon_state = "labcoat_cmo"
+ item_state = "labcoat_cmo"
+
+/obj/item/clothing/suit/toggle/labcoat/emt
+ name = "EMT's jacket"
+ desc = "A dark blue jacket with reflective strips for emergency medical technicians."
+ icon_state = "labcoat_emt"
+ item_state = "labcoat_cmo"
+
+/obj/item/clothing/suit/toggle/labcoat/mad
+ name = "\improper The Mad's labcoat"
+ desc = "It makes you look capable of konking someone on the noggin and shooting them into space."
+ icon_state = "labgreen"
+ item_state = "labgreen"
+
+/obj/item/clothing/suit/toggle/labcoat/genetics
+ name = "geneticist labcoat"
+ desc = "A suit that protects against minor chemical spills. Has a blue stripe on the shoulder."
+ icon_state = "labcoat_gen"
+
+/obj/item/clothing/suit/toggle/labcoat/chemist
+ name = "chemist labcoat"
+ desc = "A suit that protects against minor chemical spills. Has an orange stripe on the shoulder."
+ icon_state = "labcoat_chem"
+
+/obj/item/clothing/suit/toggle/labcoat/virologist
+ name = "virologist labcoat"
+ desc = "A suit that protects against minor chemical spills. Offers slightly more protection against biohazards than the standard model. Has a green stripe on the shoulder."
+ icon_state = "labcoat_vir"
+
+/obj/item/clothing/suit/toggle/labcoat/science
+ name = "scientist labcoat"
+ desc = "A suit that protects against minor chemical spills. Has a purple stripe on the shoulder."
icon_state = "labcoat_tox"
\ No newline at end of file
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index a5135222d0..5a2e5ade3c 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -93,7 +93,7 @@
item_state = "syndicate-black-red"
desc = "A plastic replica of the Syndicate space suit. You'll look just like a real murderous Syndicate agent in this! This is a toy, it is not made for use in space!"
w_class = WEIGHT_CLASS_NORMAL
- allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/toy)
+ allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy)
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
resistance_flags = NONE
@@ -160,7 +160,7 @@
item_state = "w_suit"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
flags_inv = HIDEJUMPSUIT
- allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen)
+ allowed = list(/obj/item/storage/book/bible, /obj/item/nullrod, /obj/item/reagent_containers/food/drinks/bottle/holywater, /obj/item/storage/fancy/candle_box, /obj/item/candle, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
/obj/item/clothing/suit/cardborg
name = "cardborg suit"
@@ -240,7 +240,7 @@
body_parts_covered = CHEST|GROIN|ARMS
cold_protection = CHEST|GROIN|ARMS
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT //Space carp like space, so you should too
- allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/gun/ballistic/automatic/speargun)
+ allowed = list(/obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/gun/ballistic/automatic/speargun)
hoodtype = /obj/item/clothing/head/hooded/carp_hood
/obj/item/clothing/head/hooded/carp_hood
@@ -355,7 +355,7 @@
desc = "Aviators not included."
icon_state = "bomberjacket"
item_state = "brownjsuit"
- allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/device/radio)
+ allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/device/radio)
body_parts_covered = CHEST|GROIN|ARMS
cold_protection = CHEST|GROIN|ARMS
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
@@ -367,7 +367,7 @@
item_state = "hostrench"
resistance_flags = NONE
max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT
- allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver, /obj/item/gun/ballistic/revolver/detective, /obj/item/device/radio)
+ allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver, /obj/item/gun/ballistic/revolver/detective, /obj/item/device/radio)
/obj/item/clothing/suit/jacket/leather/overcoat
name = "leather overcoat"
@@ -397,7 +397,7 @@
desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable."
icon_state = "militaryjacket"
item_state = "militaryjacket"
- allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver, /obj/item/gun/ballistic/revolver/detective, /obj/item/device/radio)
+ allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/gun/ballistic/automatic/pistol, /obj/item/gun/ballistic/revolver, /obj/item/gun/ballistic/revolver/detective, /obj/item/device/radio)
/obj/item/clothing/suit/jacket/letterman
name = "letterman jacket"
@@ -470,7 +470,7 @@
cold_protection = CHEST|GROIN|ARMS
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 0, fire = 0, acid = 0)
- allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
+ allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
/obj/item/clothing/head/hooded/winterhood
name = "winter hood"
@@ -513,7 +513,7 @@
name = "medical winter coat"
icon_state = "coatmedical"
item_state = "coatmedical"
- allowed = list(/obj/item/device/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/device/healthanalyzer, /obj/item/device/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen)
+ allowed = list(/obj/item/device/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/device/healthanalyzer, /obj/item/device/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 50, rad = 0, fire = 0, acid = 45)
hoodtype = /obj/item/clothing/head/hooded/winterhood/medical
@@ -524,7 +524,7 @@
name = "science winter coat"
icon_state = "coatscience"
item_state = "coatscience"
- allowed = list(/obj/item/device/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/device/healthanalyzer, /obj/item/device/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen)
+ allowed = list(/obj/item/device/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/device/healthanalyzer, /obj/item/device/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 10, bio = 0, rad = 0, fire = 0, acid = 0)
hoodtype = /obj/item/clothing/head/hooded/winterhood/science
@@ -536,7 +536,7 @@
icon_state = "coatengineer"
item_state = "coatengineer"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 20, fire = 30, acid = 45)
- allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/device/t_scanner, /obj/item/construction/rcd, /obj/item/pipe_dispenser, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
+ allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/device/t_scanner, /obj/item/construction/rcd, /obj/item/pipe_dispenser, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
hoodtype = /obj/item/clothing/head/hooded/winterhood/engineering
/obj/item/clothing/head/hooded/winterhood/engineering
@@ -555,7 +555,7 @@
name = "hydroponics winter coat"
icon_state = "coathydro"
item_state = "coathydro"
- allowed = list(/obj/item/reagent_containers/spray/plantbgone, /obj/item/device/plant_analyzer, /obj/item/seeds, /obj/item/reagent_containers/glass/bottle, /obj/item/cultivator, /obj/item/reagent_containers/spray/pestspray, /obj/item/hatchet, /obj/item/storage/bag/plants, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
+ allowed = list(/obj/item/reagent_containers/spray/plantbgone, /obj/item/device/plant_analyzer, /obj/item/seeds, /obj/item/reagent_containers/glass/bottle, /obj/item/cultivator, /obj/item/reagent_containers/spray/pestspray, /obj/item/hatchet, /obj/item/storage/bag/plants, /obj/item/toy, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
hoodtype = /obj/item/clothing/head/hooded/winterhood/hydro
/obj/item/clothing/head/hooded/winterhood/hydro
@@ -574,7 +574,7 @@
name = "mining winter coat"
icon_state = "coatminer"
item_state = "coatminer"
- allowed = list(/obj/item/pickaxe, /obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
+ allowed = list(/obj/item/pickaxe, /obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0)
hoodtype = /obj/item/clothing/head/hooded/winterhood/miner
diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm
index 10c1a47ac1..22b5ee421b 100644
--- a/code/modules/clothing/suits/utility.dm
+++ b/code/modules/clothing/suits/utility.dm
@@ -18,7 +18,7 @@
gas_transfer_coefficient = 0.9
permeability_coefficient = 0.5
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/extinguisher, /obj/item/crowbar)
+ allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/extinguisher, /obj/item/crowbar)
slowdown = 1
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
flags_1 = STOPSPRESSUREDMAGE_1 | THICKMATERIAL_1
@@ -141,7 +141,7 @@
permeability_coefficient = 0.5
flags_1 = THICKMATERIAL_1
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
- allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/device/geiger_counter)
+ allowed = list(/obj/item/device/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/device/geiger_counter)
slowdown = 1.5
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100, fire = 30, acid = 30)
strip_delay = 60
@@ -151,6 +151,6 @@
/obj/item/clothing/suit/radiation/ComponentInitialize()
. = ..()
- AddComponent(/datum/component/rad_insulation, RAD_NO_INSULATION, TRUE, FALSE)
+ AddComponent(/datum/component/rad_insulation, RAD_NO_INSULATION, TRUE, FALSE)
// Just don't want things to be irradiated inside this
// Except things on the mob aren't even inside the suit so ehhhhhh
\ No newline at end of file
diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm
index f983ca2563..49364e76d9 100644
--- a/code/modules/clothing/under/accessories.dm
+++ b/code/modules/clothing/under/accessories.dm
@@ -15,11 +15,11 @@
if(U.pockets) // storage items conflict
return FALSE
- pockets.loc = U
+ pockets.forceMove(U)
U.pockets = pockets
U.attached_accessory = src
- loc = U
+ forceMove(U)
layer = FLOAT_LAYER
plane = FLOAT_PLANE
if(minimize_when_attached)
@@ -39,7 +39,7 @@
/obj/item/clothing/accessory/proc/detach(obj/item/clothing/under/U, user)
if(pockets && pockets == U.pockets)
- pockets.loc = src
+ pockets.forceMove(src)
U.pockets = null
for(var/armor_type in armor)
@@ -135,7 +135,7 @@
"You pin \the [src] on [M]'s chest.")
if(input)
SSblackbox.record_feedback("associative", "commendation", 1, list("commender" = "[user.real_name]", "commendee" = "[M.real_name]", "medal" = "[src]", "reason" = input))
- GLOB.commendations += "[user.real_name] awarded [M.real_name] the [name]! \n- [input]"
+ GLOB.commendations += "[user.real_name] awarded [M.real_name] the [name]! \n- [input]"
commended = TRUE
log_game("[key_name(M)] was given the following commendation by [key_name(user)]: [input]")
message_admins("[key_name(M)] was given the following commendation by [key_name(user)]: [input]")
diff --git a/code/modules/clothing/under/jobs/civilian.dm b/code/modules/clothing/under/jobs/civilian.dm
index 4e7f0da011..6d522a3706 100644
--- a/code/modules/clothing/under/jobs/civilian.dm
+++ b/code/modules/clothing/under/jobs/civilian.dm
@@ -40,6 +40,7 @@
item_color = "cargo"
body_parts_covered = CHEST|GROIN|ARMS
mutantrace_variation = MUTANTRACE_VARIATION
+ alt_covers_chest = TRUE
/obj/item/clothing/under/rank/chaplain
diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm
index 185712e072..cd69aec17e 100644
--- a/code/modules/clothing/under/jobs/engineering.dm
+++ b/code/modules/clothing/under/jobs/engineering.dm
@@ -31,4 +31,4 @@
icon_state = "robotics"
item_state = "robotics"
item_color = "robotics"
- resistance_flags = NONE
+ resistance_flags = NONE
\ No newline at end of file
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index 899219c227..608005ffbf 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -646,6 +646,7 @@
return 0
/obj/item/clothing/under/plasmaman/attackby(obj/item/E, mob/user, params)
+ ..()
if (istype(E, /obj/item/device/extinguisher_refill))
if (extinguishes_left == 5)
to_chat(user, "The inbuilt extinguisher is full.")
@@ -728,4 +729,4 @@
body_parts_covered = CHEST|GROIN|ARMS|LEGS
fitted = NO_FEMALE_UNIFORM
can_adjust = FALSE
- resistance_flags = NONE
+ resistance_flags = NONE
\ No newline at end of file
diff --git a/code/modules/events/alien_infestation.dm b/code/modules/events/alien_infestation.dm
index 1a8a174bff..f8f26b3efb 100644
--- a/code/modules/events/alien_infestation.dm
+++ b/code/modules/events/alien_infestation.dm
@@ -16,6 +16,7 @@
// 50% chance of being incremented by one
var/spawncount = 1
var/successSpawn = 0 //So we don't make a command report if nothing gets spawned.
+ fakeable = TRUE
/datum/round_event/ghost_role/alien_infestation/setup()
diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm
index 95f72d15b3..e75752adcc 100644
--- a/code/modules/events/blob.dm
+++ b/code/modules/events/blob.dm
@@ -11,6 +11,7 @@
/datum/round_event/ghost_role/blob
announceWhen = -1
role_name = "blob overmind"
+ fakeable = TRUE
/datum/round_event/ghost_role/blob/announce(fake)
priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak5.ogg')
diff --git a/code/modules/events/carp_migration.dm b/code/modules/events/carp_migration.dm
index b75140e3c7..c17140a2d2 100644
--- a/code/modules/events/carp_migration.dm
+++ b/code/modules/events/carp_migration.dm
@@ -23,3 +23,5 @@
new /mob/living/simple_animal/hostile/carp(C.loc)
else
new /mob/living/simple_animal/hostile/carp/megacarp(C.loc)
+
+
diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm
index eb7625e08c..9ce4bf6ac3 100644
--- a/code/modules/events/disease_outbreak.dm
+++ b/code/modules/events/disease_outbreak.dm
@@ -10,6 +10,8 @@
var/virus_type
+ var/max_severity = 3
+
/datum/round_event/disease_outbreak/announce(fake)
priority_announce("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak7.ogg')
@@ -17,8 +19,14 @@
/datum/round_event/disease_outbreak/setup()
announceWhen = rand(15, 30)
+
/datum/round_event/disease_outbreak/start()
- if(!virus_type)
+ var/advanced_virus = FALSE
+ max_severity = 3 + max(Floor((world.time - control.earliest_start)/6000),0) //3 symptoms at 20 minutes, plus 1 per 10 minutes
+ if(prob(20 + (10 * max_severity)))
+ advanced_virus = TRUE
+
+ if(!virus_type && !advanced_virus)
virus_type = pick(/datum/disease/dnaspread, /datum/disease/advance/flu, /datum/disease/advance/cold, /datum/disease/brainrot, /datum/disease/magnitis)
for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list))
@@ -41,16 +49,48 @@
continue
var/datum/disease/D
- if(virus_type == /datum/disease/dnaspread) //Dnaspread needs strain_data set to work.
- if(!H.dna || (H.disabilities & BLIND)) //A blindness disease would be the worst.
- continue
- D = new virus_type()
- var/datum/disease/dnaspread/DS = D
- DS.strain_data["name"] = H.real_name
- DS.strain_data["UI"] = H.dna.uni_identity
- DS.strain_data["SE"] = H.dna.struc_enzymes
+ if(!advanced_virus)
+ if(virus_type == /datum/disease/dnaspread) //Dnaspread needs strain_data set to work.
+ if(!H.dna || (H.disabilities & BLIND)) //A blindness disease would be the worst.
+ continue
+ D = new virus_type()
+ var/datum/disease/dnaspread/DS = D
+ DS.strain_data["name"] = H.real_name
+ DS.strain_data["UI"] = H.dna.uni_identity
+ DS.strain_data["SE"] = H.dna.struc_enzymes
+ else
+ D = new virus_type()
else
- D = new virus_type()
+ D = make_virus(max_severity, max_severity)
D.carrier = TRUE
H.AddDisease(D)
- break
\ No newline at end of file
+
+ if(advanced_virus)
+ var/datum/disease/advance/A = D
+ var/list/name_symptoms = list() //for feedback
+ for(var/datum/symptom/S in A.symptoms)
+ name_symptoms += S.name
+ message_admins("An event has triggered a random advanced virus outbreak on [key_name_admin(H)]! It has these symptoms: [english_list(name_symptoms)]")
+ log_game("An event has triggered a random advanced virus outbreak on [key_name(H)]! It has these symptoms: [english_list(name_symptoms)]")
+ break
+
+/datum/round_event/disease_outbreak/proc/make_virus(max_symptoms, max_level)
+ if(max_symptoms > SYMPTOM_LIMIT)
+ max_symptoms = SYMPTOM_LIMIT
+ var/datum/disease/advance/A = new(FALSE, null)
+ A.symptoms = list()
+ var/list/datum/symptom/possible_symptoms = list()
+ for(var/symptom in subtypesof(/datum/symptom))
+ var/datum/symptom/S = symptom
+ if(initial(S.level) > max_level)
+ continue
+ if(initial(S.level) <= 0) //unobtainable symptoms
+ continue
+ possible_symptoms += S
+ for(var/i in 1 to max_symptoms)
+ var/datum/symptom/chosen_symptom = pick_n_take(possible_symptoms)
+ if(chosen_symptom)
+ var/datum/symptom/S = new chosen_symptom
+ A.symptoms += S
+ A.Refresh() //just in case someone already made and named the same disease
+ return A
diff --git a/code/modules/events/dust.dm b/code/modules/events/dust.dm
index 978f62d85a..47eb2d4ea8 100644
--- a/code/modules/events/dust.dm
+++ b/code/modules/events/dust.dm
@@ -28,4 +28,4 @@
fakeable = FALSE
/datum/round_event/sandstorm/tick()
- spawn_meteors(10, GLOB.meteorsC)
+ spawn_meteors(10, GLOB.meteorsC)
\ No newline at end of file
diff --git a/code/modules/events/ghost_role.dm b/code/modules/events/ghost_role.dm
index f5e9513b2e..e50d89a3a3 100644
--- a/code/modules/events/ghost_role.dm
+++ b/code/modules/events/ghost_role.dm
@@ -7,6 +7,7 @@
var/minimum_required = 1
var/role_name = "debug rat with cancer" // Q U A L I T Y M E M E S
var/list/spawned_mobs = list()
+ fakeable = FALSE
/datum/round_event/ghost_role/start()
try_spawning()
diff --git a/code/modules/events/holiday/friday13th.dm b/code/modules/events/holiday/friday13th.dm
index b1db15a896..ba2c9ea78f 100644
--- a/code/modules/events/holiday/friday13th.dm
+++ b/code/modules/events/holiday/friday13th.dm
@@ -15,4 +15,4 @@
/datum/round_event/fridaythethirteen/announce(fake)
for(var/mob/living/L in player_list)
- to_chat(L, "You are feeling unlucky today.")
+ to_chat(L, "You are feeling unlucky today.")
\ No newline at end of file
diff --git a/code/modules/events/holiday/vday.dm b/code/modules/events/holiday/vday.dm
index 41ff90407d..abb5a0639d 100644
--- a/code/modules/events/holiday/vday.dm
+++ b/code/modules/events/holiday/vday.dm
@@ -45,19 +45,26 @@
to_chat(L, "You didn't get a date! They're all having fun without you! you'll show them though...")
var/datum/objective/martyr/normiesgetout = new
normiesgetout.owner = L.mind
+ L.mind.special_role = "heartbreaker"
SSticker.mode.traitors |= L.mind
L.mind.objectives += normiesgetout
+ L.mind.add_antag_datum(/datum/antagonist/auto_custom)
+
/proc/forge_valentines_objective(mob/living/lover,mob/living/date)
SSticker.mode.traitors |= lover.mind
lover.mind.special_role = "valentine"
+
var/datum/objective/protect/protect_objective = new /datum/objective/protect
protect_objective.owner = lover.mind
protect_objective.target = date.mind
protect_objective.explanation_text = "Protect [date.real_name], your date."
lover.mind.objectives += protect_objective
+
+ lover.mind.add_antag_datum(/datum/antagonist/auto_custom)
+
to_chat(lover, "You're on a date with [date]! Protect them at all costs. This takes priority over all other loyalties.")
diff --git a/code/modules/events/mass_hallucination.dm b/code/modules/events/mass_hallucination.dm
index 88fe218a22..5bad888f17 100644
--- a/code/modules/events/mass_hallucination.dm
+++ b/code/modules/events/mass_hallucination.dm
@@ -10,4 +10,4 @@
/datum/round_event/mass_hallucination/start()
for(var/mob/living/carbon/C in GLOB.alive_mob_list)
- C.hallucination += rand(20, 50)
+ C.hallucination += rand(20, 50)
\ No newline at end of file
diff --git a/code/modules/events/nightmare.dm b/code/modules/events/nightmare.dm
index 073ef8aea3..76188cb5b7 100644
--- a/code/modules/events/nightmare.dm
+++ b/code/modules/events/nightmare.dm
@@ -35,6 +35,7 @@
player_mind.assigned_role = "Nightmare"
player_mind.special_role = "Nightmare"
SSticker.mode.traitors += player_mind
+ player_mind.add_antag_datum(/datum/antagonist/auto_custom)
S.set_species(/datum/species/shadow/nightmare)
playsound(S, 'sound/magic/ethereal_exit.ogg', 50, 1, -1)
message_admins("[key_name_admin(S)] has been made into a Nightmare by an event.")
diff --git a/code/modules/events/operative.dm b/code/modules/events/operative.dm
index 47130ff924..e0e3b98776 100644
--- a/code/modules/events/operative.dm
+++ b/code/modules/events/operative.dm
@@ -26,32 +26,12 @@
var/datum/preferences/A = new
A.copy_to(operative)
operative.dna.update_dna_identity()
-
- operative.equipOutfit(/datum/outfit/syndicate/full)
-
var/datum/mind/Mind = new /datum/mind(selected.key)
Mind.assigned_role = "Lone Operative"
Mind.special_role = "Lone Operative"
- SSticker.mode.traitors |= Mind
Mind.active = 1
-
- var/obj/machinery/nuclearbomb/selfdestruct/nuke = locate() in GLOB.machines
- if(nuke)
- var/nuke_code
- if(!nuke.r_code || nuke.r_code == "ADMIN")
- nuke_code = random_nukecode()
- nuke.r_code = nuke_code
- else
- nuke_code = nuke.r_code
-
- Mind.store_memory("Station Self-Destruct Device Code: [nuke_code]", 0, 0)
- to_chat(Mind.current, "The nuclear authorization code is: [nuke_code]")
-
- var/datum/objective/nuclear/O = new()
- O.owner = Mind
- Mind.objectives += O
-
Mind.transfer_to(operative)
+ Mind.add_antag_datum(/datum/antagonist/nukeop/lone)
message_admins("[key_name_admin(operative)] has been made into lone operative by an event.")
log_game("[key_name(operative)] was spawned as a lone operative by an event.")
diff --git a/code/modules/events/prison_break.dm b/code/modules/events/prison_break.dm
index ebcade74a3..96f5a3917d 100644
--- a/code/modules/events/prison_break.dm
+++ b/code/modules/events/prison_break.dm
@@ -56,4 +56,4 @@
temp.prison_open()
else if(istype(O, /obj/machinery/door_timer))
var/obj/machinery/door_timer/temp = O
- temp.timer_end(forced = TRUE)
+ temp.timer_end(forced = TRUE)
\ No newline at end of file
diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm
index 7b66ac553f..d186d2cf88 100644
--- a/code/modules/events/radiation_storm.dm
+++ b/code/modules/events/radiation_storm.dm
@@ -16,5 +16,4 @@
//sound not longer matches the text, but an audible warning is probably good
/datum/round_event/radiation_storm/start()
- SSweather.run_weather("radiation storm",ZLEVEL_STATION_PRIMARY)
- make_maint_all_access()
+ SSweather.run_weather("radiation storm",ZLEVEL_STATION_PRIMARY)
\ No newline at end of file
diff --git a/code/modules/events/sentience.dm b/code/modules/events/sentience.dm
index bd08743aaf..227bf14984 100644
--- a/code/modules/events/sentience.dm
+++ b/code/modules/events/sentience.dm
@@ -9,6 +9,7 @@
role_name = "random animal"
var/animals = 1
var/one = "one"
+ fakeable = TRUE
/datum/round_event/ghost_role/sentience/announce(fake)
var/sentience_report = ""
diff --git a/code/modules/events/shuttle_loan.dm b/code/modules/events/shuttle_loan.dm
index ca5de88d58..55984df033 100644
--- a/code/modules/events/shuttle_loan.dm
+++ b/code/modules/events/shuttle_loan.dm
@@ -135,7 +135,7 @@
new /obj/structure/spider/stickyweb(T)
if(ANTIDOTE_NEEDED)
- var/obj/item/reagent_containers/glass/bottle/virus_type = pick(/obj/item/reagent_containers/glass/bottle/beesease, /obj/item/reagent_containers/glass/bottle/brainrot, /obj/item/reagent_containers/glass/bottle/fluspanish)
+ var/obj/effect/mob_spawn/human/corpse/assistant/infected_assistant = pick(/obj/effect/mob_spawn/human/corpse/assistant/beesease_infection, /obj/effect/mob_spawn/human/corpse/assistant/brainrot_infection, /obj/effect/mob_spawn/human/corpse/assistant/spanishflu_infection)
var/turf/T
for(var/i=0, i<10, i++)
if(prob(15))
@@ -145,7 +145,7 @@
else if(prob(25))
shuttle_spawns.Add(/obj/item/shard)
T = pick_n_take(empty_shuttle_turfs)
- new virus_type(T)
+ new infected_assistant(T)
shuttle_spawns.Add(/obj/structure/closet/crate)
shuttle_spawns.Add(/obj/item/reagent_containers/glass/bottle/pierrot_throat)
shuttle_spawns.Add(/obj/item/reagent_containers/glass/bottle/magnitis)
diff --git a/code/modules/events/spontaneous_appendicitis.dm b/code/modules/events/spontaneous_appendicitis.dm
index 46bb254703..a9ae27993d 100644
--- a/code/modules/events/spontaneous_appendicitis.dm
+++ b/code/modules/events/spontaneous_appendicitis.dm
@@ -26,4 +26,4 @@
var/datum/disease/D = new /datum/disease/appendicitis
H.ForceContractDisease(D)
- break
+ break
\ No newline at end of file
diff --git a/code/modules/events/weightless.dm b/code/modules/events/weightless.dm
index 425ed7ef9f..bb5b3fd15a 100644
--- a/code/modules/events/weightless.dm
+++ b/code/modules/events/weightless.dm
@@ -28,3 +28,5 @@
if(announceWhen >= 0)
command_alert("Artificial gravity arrays are now functioning within normal parameters. Please report any irregularities to your respective head of staff.")
+
+
diff --git a/code/modules/events/wizard/departmentrevolt.dm b/code/modules/events/wizard/departmentrevolt.dm
index 618c746a65..3227f81d58 100644
--- a/code/modules/events/wizard/departmentrevolt.dm
+++ b/code/modules/events/wizard/departmentrevolt.dm
@@ -44,6 +44,7 @@
citizens += H
SSticker.mode.traitors += M
M.special_role = "separatist"
+ M.add_antag_datum(/datum/antagonist/auto_custom)
H.log_message("Was made into a separatist, long live [nation]!", INDIVIDUAL_ATTACK_LOG)
to_chat(H, "You are a separatist! [nation] forever! Protect the sovereignty of your newfound land with your comrades in arms!")
if(citizens.len)
diff --git a/code/modules/events/wizard/greentext.dm b/code/modules/events/wizard/greentext.dm
index 6ee000249b..1cf4858ce7 100644
--- a/code/modules/events/wizard/greentext.dm
+++ b/code/modules/events/wizard/greentext.dm
@@ -67,6 +67,7 @@
O.completed = 1 //YES!
O.owner = new_holder.mind
new_holder.mind.objectives += O
+ new_holder.mind.add_antag_datum(/datum/antagonist/auto_custom)
new_holder.log_message("Won with greentext!!!", INDIVIDUAL_ATTACK_LOG)
color_altered_mobs -= new_holder
resistance_flags |= ON_FIRE
diff --git a/code/modules/flufftext/Dreaming.dm b/code/modules/flufftext/Dreaming.dm
index 779fe7fa09..bfbad559e1 100644
--- a/code/modules/flufftext/Dreaming.dm
+++ b/code/modules/flufftext/Dreaming.dm
@@ -1,5 +1,5 @@
-/mob/living/carbon/proc/dream()
- set waitfor = 0
+/mob/living/carbon/proc/dream()
+ set waitfor = 0
var/list/dreams = GLOB.dream_strings.Copy()
for(var/obj/item/bedsheet/sheet in loc)
dreams += sheet.dream_messages
@@ -9,12 +9,12 @@
dreaming++
for(var/i in 1 to dream_images.len)
addtimer(CALLBACK(src, .proc/experience_dream, dream_images[i]), ((i - 1) * rand(30,60)))
- return 1
-
-/mob/living/carbon/proc/handle_dreams()
- if(prob(5) && !dreaming)
- dream()
-
+ return 1
+
+/mob/living/carbon/proc/handle_dreams()
+ if(prob(5) && !dreaming)
+ dream()
+
/mob/living/carbon/proc/experience_dream(dream_image)
dreaming--
if(stat != UNCONSCIOUS || InCritical())
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index 194edd77b1..a4726d4bfd 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -779,7 +779,7 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
humans += H
person = pick(humans)
- var/message = target.compose_message(person,understood_language,pick(radio_messages),"1459",person.get_spans(),face_name = TRUE)
+ var/message = target.compose_message(person,understood_language,pick(radio_messages),"[FREQ_COMMON]",person.get_spans(),face_name = TRUE)
feedback_details += "Type: Radio, Source: [person.real_name], Message: [message]"
to_chat(target, message)
qdel(src)
diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm
index 7217fe0b28..137f04c7b1 100644
--- a/code/modules/food_and_drinks/drinks/drinks.dm
+++ b/code/modules/food_and_drinks/drinks/drinks.dm
@@ -91,12 +91,10 @@
addtimer(CALLBACK(reagents, /datum/reagents.proc/add_reagent, refill, trans), 600)
/obj/item/reagent_containers/food/drinks/attackby(obj/item/I, mob/user, params)
- if(I.is_hot())
- var/added_heat = (I.is_hot() / 100) //ishot returns a temperature
- if(reagents)
- reagents.chem_temp += added_heat
- to_chat(user, "You heat [src] with [I].")
- reagents.handle_reactions()
+ var/hotness = I.is_hot()
+ if(hotness && reagents)
+ reagents.expose_temperature(hotness)
+ to_chat(user, "You heat [name] with [I]!")
..()
/obj/item/reagent_containers/food/drinks/throw_impact(atom/target, mob/thrower)
@@ -393,6 +391,7 @@
container_type = NONE
spillable = FALSE
isGlass = FALSE
+ grind_results = list("aluminum" = 10)
/obj/item/reagent_containers/food/drinks/soda_cans/attack(mob/M, mob/user)
if(M == user && !src.reagents.total_volume && user.a_intent == INTENT_HARM && user.zone_selected == "head")
diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
index 005dda29ca..81ebc3d67c 100644
--- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm
+++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm
@@ -232,8 +232,8 @@
icon_state = "absinthebottle"
list_reagents = list("absinthe" = 100)
-/obj/item/reagent_containers/food/drinks/bottle/absinthe/New()
- ..()
+/obj/item/reagent_containers/food/drinks/bottle/absinthe/Initialize()
+ . = ..()
redact()
/obj/item/reagent_containers/food/drinks/bottle/absinthe/proc/redact()
diff --git a/code/modules/food_and_drinks/food.dm b/code/modules/food_and_drinks/food.dm
index e23f6b98a9..57288d8277 100644
--- a/code/modules/food_and_drinks/food.dm
+++ b/code/modules/food_and_drinks/food.dm
@@ -9,13 +9,12 @@
var/foodtype = NONE
var/last_check_time
-/obj/item/weapon/reagent_containers/food/Initialize(mapload)
- ..()
+/obj/item/reagent_containers/food/Initialize(mapload)
+ . = ..()
if(!mapload)
- pixel_x = rand(-5, 5) //Randomizes postion slightly.
+ pixel_x = rand(-5, 5)
pixel_y = rand(-5, 5)
-
/obj/item/reagent_containers/food/proc/checkLiked(var/fraction, mob/M)
if(last_check_time + 50 < world.time)
if(ishuman(M))
diff --git a/code/modules/food_and_drinks/food/customizables.dm b/code/modules/food_and_drinks/food/customizables.dm
index 3351a67d39..fc49cee9ab 100644
--- a/code/modules/food_and_drinks/food/customizables.dm
+++ b/code/modules/food_and_drinks/food/customizables.dm
@@ -276,8 +276,8 @@
icon = 'icons/obj/food/soupsalad.dmi'
icon_state = "wishsoup"
-/obj/item/reagent_containers/food/snacks/customizable/soup/New()
- ..()
+/obj/item/reagent_containers/food/snacks/customizable/soup/Initialize()
+ . = ..()
eatverb = pick("slurp","sip","suck","inhale","drink")
diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm
index 49f85a882d..4ccded83f7 100644
--- a/code/modules/food_and_drinks/food/snacks.dm
+++ b/code/modules/food_and_drinks/food/snacks.dm
@@ -6,6 +6,7 @@
lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi'
unique_rename = 1
+ grind_results = list() //To let them be ground up to transfer their reagents
var/bitesize = 2
var/bitecount = 0
var/trash = null
@@ -315,10 +316,10 @@
// name = "Xenoburger" //Name that displays in the UI.
// desc = "Smells caustic. Tastes like heresy." //Duh
// icon_state = "xburger" //Refers to an icon in food.dmi
-///obj/item/reagent_containers/food/snacks/xenoburger/New() //Don't mess with this.
-// ..() //Same here.
+///obj/item/reagent_containers/food/snacks/xenoburger/Initialize() //Don't mess with this. | nO I WILL MESS WITH THIS
+// . = ..() //Same here.
// reagents.add_reagent("xenomicrobes", 10) //This is what is in the food item. you may copy/paste
-// reagents.add_reagent("nutriment", 2) // this line of code for all the contents.
+// reagents.add_reagent("nutriment", 2) //this line of code for all the contents.
// bitesize = 3 //This is the amount each bite consumes.
//All foods are distributed among various categories. Use common sense.
diff --git a/code/modules/food_and_drinks/food/snacks_egg.dm b/code/modules/food_and_drinks/food/snacks_egg.dm
index bfe181b419..10039f7a8b 100644
--- a/code/modules/food_and_drinks/food/snacks_egg.dm
+++ b/code/modules/food_and_drinks/food/snacks_egg.dm
@@ -20,6 +20,7 @@
filling_color = "#F0E68C"
tastes = list("egg" = 1)
foodtype = MEAT
+ grind_results = list("eggyolk" = 5)
/obj/item/reagent_containers/food/snacks/egg/throw_impact(atom/hit_atom)
if(!..()) //was it caught by a mob?
diff --git a/code/modules/food_and_drinks/food/snacks_other.dm b/code/modules/food_and_drinks/food/snacks_other.dm
index c32ebfb765..9691eee144 100644
--- a/code/modules/food_and_drinks/food/snacks_other.dm
+++ b/code/modules/food_and_drinks/food/snacks_other.dm
@@ -28,6 +28,7 @@
filling_color = "#FF1493"
tastes = list("watermelon" = 1)
foodtype = FRUIT
+ juice_results = list("watermelonjuice" = 5)
/obj/item/reagent_containers/food/snacks/candy_corn
name = "candy corn"
@@ -66,8 +67,8 @@
tastes = list("popcorn" = 3, "butter" = 1)
foodtype = JUNKFOOD
-/obj/item/reagent_containers/food/snacks/popcorn/New()
- ..()
+/obj/item/reagent_containers/food/snacks/popcorn/Initialize()
+ . = ..()
eatverb = pick("bite","crunch","nibble","gnaw","gobble","chomp")
/obj/item/reagent_containers/food/snacks/loadedbakedpotato
@@ -447,8 +448,8 @@
tastes = list("candy" = 1)
foodtype = JUNKFOOD | SUGAR
-/obj/item/reagent_containers/food/snacks/lollipop/New()
- ..()
+/obj/item/reagent_containers/food/snacks/lollipop/Initialize()
+ . = ..()
head = mutable_appearance('icons/obj/lollipop.dmi', "lollipop_head")
change_head_color(rgb(rand(0, 255), rand(0, 255), rand(0, 255)))
@@ -466,8 +467,8 @@
/obj/item/reagent_containers/food/snacks/lollipop/cyborg
var/spamchecking = TRUE
-/obj/item/reagent_containers/food/snacks/lollipop/cyborg/New()
- ..()
+/obj/item/reagent_containers/food/snacks/lollipop/cyborg/Initialize()
+ . = ..()
addtimer(CALLBACK(src, .proc/spamcheck), 1200)
/obj/item/reagent_containers/food/snacks/lollipop/cyborg/equipped(mob/living/user, slot)
@@ -487,15 +488,15 @@
tastes = list("candy")
foodtype = JUNKFOOD
-/obj/item/reagent_containers/food/snacks/gumball/New()
- ..()
+/obj/item/reagent_containers/food/snacks/gumball/Initialize()
+ . = ..()
color = rgb(rand(0, 255), rand(0, 255), rand(0, 255))
/obj/item/reagent_containers/food/snacks/gumball/cyborg
var/spamchecking = TRUE
-/obj/item/reagent_containers/food/snacks/gumball/cyborg/New()
- ..()
+/obj/item/reagent_containers/food/snacks/gumball/cyborg/Initialize()
+ . = ..()
addtimer(CALLBACK(src, .proc/spamcheck), 1200)
/obj/item/reagent_containers/food/snacks/gumball/cyborg/equipped(mob/living/user, slot)
diff --git a/code/modules/food_and_drinks/food/snacks_pastry.dm b/code/modules/food_and_drinks/food/snacks_pastry.dm
index 284784484f..b7df203e30 100644
--- a/code/modules/food_and_drinks/food/snacks_pastry.dm
+++ b/code/modules/food_and_drinks/food/snacks_pastry.dm
@@ -350,3 +350,113 @@
filling_color = "#F2CE91"
tastes = list("pastry" = 1, "sweetness" = 1)
foodtype = GRAIN
+
+#define PANCAKE_MAX_STACK 10
+
+/obj/item/reagent_containers/food/snacks/pancakes
+ name = "pancake"
+ desc = "A fluffy pancake. The softer, superior relative of the waffle."
+ icon_state = "pancakes_1"
+ item_state = "pancakes"
+ bonus_reagents = list("vitamin" = 1)
+ list_reagents = list("nutriment" = 4, "vitamin" = 1)
+ filling_color = "#D2691E"
+ tastes = list("pancakes" = 1)
+ foodtype = GRAIN | SUGAR
+
+/obj/item/reagent_containers/food/snacks/pancakes/blueberry
+ name = "blueberry pancake"
+ desc = "A fluffy and delicious blueberry pancake."
+ icon_state = "bbpancakes_1"
+ item_state = "bbpancakes"
+ bonus_reagents = list("vitamin" = 2)
+ list_reagents = list("nutriment" = 6, "vitamin" = 3)
+ tastes = list("pancakes" = 1, "blueberries" = 1)
+
+/obj/item/reagent_containers/food/snacks/pancakes/chocolatechip
+ name = "chocolate chip pancake"
+ desc = "A fluffy and delicious chocolate chip pancake."
+ icon_state = "ccpancakes_1"
+ item_state = "ccpancakes"
+ bonus_reagents = list("vitamin" = 2)
+ list_reagents = list("nutriment" = 6, "vitamin" = 3)
+ tastes = list("pancakes" = 1, "chocolate" = 1)
+
+/obj/item/reagent_containers/food/snacks/pancakes/Initialize()
+ . = ..()
+ update_icon()
+
+/obj/item/reagent_containers/food/snacks/pancakes/update_icon()
+ if(contents.len)
+ name = "stack of pancakes"
+ else
+ name = initial(name)
+ if(contents.len < our_overlays.len)
+ cut_overlay(our_overlays[our_overlays.len])
+
+/obj/item/reagent_containers/food/snacks/pancakes/examine(mob/user)
+ var/ingredients_listed = ""
+ var/pancakeCount = contents.len
+ switch(pancakeCount)
+ if(0)
+ desc = initial(desc)
+ if(1 to 2)
+ desc = "A stack of fluffy pancakes."
+ if(3 to 6)
+ desc = "A fat stack of fluffy pancakes!"
+ if(7 to 9)
+ desc = "A grand tower of fluffy, delicious pancakes!"
+ if(PANCAKE_MAX_STACK to INFINITY)
+ desc = "A massive towering spire of fluffy, delicious pancakes. It looks like it could tumble over!"
+ var/originalBites = bitecount
+ if (pancakeCount)
+ var/obj/item/reagent_containers/food/snacks/S = contents[pancakeCount]
+ bitecount = S.bitecount
+ ..()
+ if (pancakeCount)
+ for(var/obj/item/reagent_containers/food/snacks/pancakes/ING in contents)
+ ingredients_listed += "[ING.name], "
+ to_chat(user, "It contains [contents.len?"[ingredients_listed]":"no ingredient, "]on top of a [initial(name)].")
+ bitecount = originalBites
+
+/obj/item/reagent_containers/food/snacks/pancakes/attackby(obj/item/I, mob/living/user, params)
+ if(istype(I, /obj/item/reagent_containers/food/snacks/pancakes/))
+ var/obj/item/reagent_containers/food/snacks/pancakes/P = I
+ if((contents.len >= PANCAKE_MAX_STACK) || ((P.contents.len + contents.len) > PANCAKE_MAX_STACK) || (reagents.total_volume >= volume))
+ to_chat(user, "You can't add that many pancakes to [src]!")
+ else
+ if(!user.transferItemToLoc(I, src))
+ return
+ to_chat(user, "You add the [I] to the [name].")
+ P.name = initial(P.name)
+ contents += P
+ update_overlays(P)
+ if (P.contents.len)
+ for(var/V in P.contents)
+ P = V
+ P.name = initial(P.name)
+ contents += P
+ update_overlays(P)
+ P = I
+ clearlist(P.contents)
+ return
+ else if(contents.len)
+ var/obj/O = contents[contents.len]
+ return O.attackby(I, user, params)
+ ..()
+
+/obj/item/reagent_containers/food/snacks/pancakes/update_overlays(obj/item/reagent_containers/food/snacks/P)
+ var/mutable_appearance/pancake = mutable_appearance(icon, "[P.item_state]_[rand(1,3)]")
+ pancake.pixel_x = rand(-1,1)
+ pancake.pixel_y = 3 * contents.len - 1
+ add_overlay(pancake)
+ update_icon()
+
+/obj/item/reagent_containers/food/snacks/pancakes/attack(mob/M, mob/user, def_zone, stacked = TRUE)
+ if(user.a_intent == INTENT_HARM || !contents.len || !stacked)
+ return ..()
+ var/obj/item/O = contents[contents.len]
+ . = O.attack(M, user, def_zone, FALSE)
+ update_icon()
+
+#undef PANCAKE_MAX_STACK
\ No newline at end of file
diff --git a/code/modules/food_and_drinks/food/snacks_pie.dm b/code/modules/food_and_drinks/food/snacks_pie.dm
index 977bd60da1..1255b16f1e 100644
--- a/code/modules/food_and_drinks/food/snacks_pie.dm
+++ b/code/modules/food_and_drinks/food/snacks_pie.dm
@@ -112,13 +112,13 @@
foodtype = GRAIN | VEGETABLES
-/obj/item/reagent_containers/food/snacks/pie/plump_pie/New()
+/obj/item/reagent_containers/food/snacks/pie/plump_pie/Initialize()
+ . = ..()
var/fey = prob(10)
if(fey)
name = "exceptional plump pie"
desc = "Microwave is taken by a fey mood! It has cooked an exceptional plump pie!"
bonus_reagents = list("nutriment" = 1, "omnizine" = 5, "vitamin" = 4)
- ..()
if(fey)
reagents.add_reagent("omnizine", 5)
diff --git a/code/modules/food_and_drinks/food/snacks_salad.dm b/code/modules/food_and_drinks/food/snacks_salad.dm
index 4cb44093a7..65ff4d2eb9 100644
--- a/code/modules/food_and_drinks/food/snacks_salad.dm
+++ b/code/modules/food_and_drinks/food/snacks_salad.dm
@@ -9,9 +9,9 @@
tastes = list("leaves" = 1)
foodtype = VEGETABLES
-/obj/item/reagent_containers/food/snacks/salad/New()
- ..()
- eatverb = pick("crunch","devour","nibble","gnaw","gobble","chomp")
+/obj/item/reagent_containers/food/snacks/salad/Initialize()
+ . = ..()
+ eatverb = pick("crunch","devour","nibble","gnaw","gobble","chomp") //who the fuck gnaws and devours on a salad
/obj/item/reagent_containers/food/snacks/salad/aesirsalad
name = "\improper Aesir salad"
diff --git a/code/modules/food_and_drinks/food/snacks_soup.dm b/code/modules/food_and_drinks/food/snacks_soup.dm
index 422e35b849..3e3fc9440a 100644
--- a/code/modules/food_and_drinks/food/snacks_soup.dm
+++ b/code/modules/food_and_drinks/food/snacks_soup.dm
@@ -8,8 +8,8 @@
tastes = list("tasteless soup" = 1)
foodtype = VEGETABLES
-/obj/item/reagent_containers/food/snacks/soup/New()
- ..()
+/obj/item/reagent_containers/food/snacks/soup/Initialize()
+ . = ..()
eatverb = pick("slurp","sip","suck","inhale","drink")
/obj/item/reagent_containers/food/snacks/soup/wish
@@ -19,12 +19,12 @@
list_reagents = list("water" = 10)
tastes = list("wishes" = 1)
-/obj/item/reagent_containers/food/snacks/soup/wish/New()
+/obj/item/reagent_containers/food/snacks/soup/wish/Initialize()
+ . = ..()
var/wish_true = prob(25)
if(wish_true)
desc = "A wish come true!"
bonus_reagents = list("nutriment" = 9, "vitamin" = 1)
- ..()
if(wish_true)
reagents.add_reagent("nutriment", 9)
reagents.add_reagent("vitamin", 1)
@@ -99,10 +99,10 @@
list_reagents = list("nutriment" = 6)
tastes = list("chaos" = 1)
-/obj/item/reagent_containers/food/snacks/soup/mystery/New()
+/obj/item/reagent_containers/food/snacks/soup/mystery/Initialize()
+ . = ..()
extra_reagent = pick("capsaicin", "frostoil", "omnizine", "banana", "blood", "slimejelly", "toxin", "banana", "carbon", "oculine")
bonus_reagents = list("[extra_reagent]" = 5, "nutriment" = 6)
- ..()
reagents.add_reagent("[extra_reagent]", 5)
/obj/item/reagent_containers/food/snacks/soup/hotchili
@@ -173,8 +173,8 @@
bonus_reagents = list("nutriment" = 1, "vitamin" = 5)
foodtype = VEGETABLES
-/obj/item/reagent_containers/food/snacks/soup/beet/New()
- ..()
+/obj/item/reagent_containers/food/snacks/soup/beet/Initialize()
+ . = ..()
name = pick("borsch","bortsch","borstch","borsh","borshch","borscht")
tastes = list(name = 1)
diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm
index 82ba8ab405..abca943075 100644
--- a/code/modules/food_and_drinks/pizzabox.dm
+++ b/code/modules/food_and_drinks/pizzabox.dm
@@ -28,9 +28,10 @@
var/const/BOMB_TIMER_MIN = 1
var/const/BOMB_TIMER_MAX = 10
-/obj/item/pizzabox/New()
+/obj/item/pizzabox/Initialize()
+ . = ..()
update_icon()
- ..()
+
/obj/item/pizzabox/Destroy()
unprocess()
@@ -257,29 +258,31 @@
wires = null
update_icon()
-/obj/item/pizzabox/bomb/New()
+/obj/item/pizzabox/bomb/Initialize()
+ . = ..()
var/randompizza = pick(subtypesof(/obj/item/reagent_containers/food/snacks/pizza))
pizza = new randompizza(src)
bomb = new(src)
wires = new /datum/wires/explosive/pizza(src)
- ..()
-/obj/item/pizzabox/margherita/New()
+/obj/item/pizzabox/margherita/Initialize()
+ . = ..()
pizza = new /obj/item/reagent_containers/food/snacks/pizza/margherita(src)
boxtag = "Margherita Deluxe"
- ..()
-/obj/item/pizzabox/vegetable/New()
+
+/obj/item/pizzabox/vegetable/Initialize()
+ . = ..()
pizza = new /obj/item/reagent_containers/food/snacks/pizza/vegetable(src)
boxtag = "Gourmet Vegatable"
- ..()
-/obj/item/pizzabox/mushroom/New()
+
+/obj/item/pizzabox/mushroom/Initialize()
+ . = ..()
pizza = new /obj/item/reagent_containers/food/snacks/pizza/mushroom(src)
boxtag = "Mushroom Special"
- ..()
-/obj/item/pizzabox/meat/New()
+/obj/item/pizzabox/meat/Initialize()
+ . = ..()
pizza = new /obj/item/reagent_containers/food/snacks/pizza/meat(src)
boxtag = "Meatlover's Supreme"
- ..()
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
index 041a58c467..a75510ae9a 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_pastry.dm
@@ -50,7 +50,7 @@
result = /obj/item/reagent_containers/food/snacks/donut/jelly/slimejelly
subcategory = CAT_PASTRY
-////////////////////////////////////////////////WAFFLES////////////////////////////////////////////////
+////////////////////////////////////////////////WAFFLES AND PANCAKES////////////////////////////////////////////////
/datum/crafting_recipe/food/waffles
time = 15
@@ -90,6 +90,33 @@
result = /obj/item/reagent_containers/food/snacks/rofflewaffles
subcategory = CAT_PASTRY
+/datum/crafting_recipe/food/pancakes
+ name = "Pancake"
+ reqs = list(
+ /obj/item/reagent_containers/food/snacks/pastrybase = 1
+ )
+ result = /obj/item/reagent_containers/food/snacks/pancakes
+ subcategory = CAT_PASTRY
+
+/datum/crafting_recipe/food/bbpancakes
+ name = "Blueberry pancake"
+ reqs = list(
+ /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/reagent_containers/food/snacks/grown/berries = 1
+ )
+ result = /obj/item/reagent_containers/food/snacks/pancakes/blueberry
+ subcategory = CAT_PASTRY
+
+/datum/crafting_recipe/food/ccpancakes
+ name = "Chocolate chip pancake"
+ reqs = list(
+ /obj/item/reagent_containers/food/snacks/pastrybase = 1,
+ /obj/item/reagent_containers/food/snacks/chocolatebar = 1
+ )
+ result = /obj/item/reagent_containers/food/snacks/pancakes/chocolatechip
+ subcategory = CAT_PASTRY
+
+
////////////////////////////////////////////////DONKPOCCKETS////////////////////////////////////////////////
/datum/crafting_recipe/food/donkpocket
diff --git a/code/modules/games/cards.dm b/code/modules/games/cards.dm
index 89f6316297..e7bf3ea9d7 100644
--- a/code/modules/games/cards.dm
+++ b/code/modules/games/cards.dm
@@ -16,7 +16,7 @@
var/list/cards = list()
-/obj/item/deck/New()
+/obj/item/deck/Initialize()
. = ..()
var/cardcolor
@@ -187,7 +187,7 @@
ASSERT(H)
usr.visible_message("\The [usr] plays \the [card.name].")
- H.loc = get_step(usr,usr.dir)
+ H.forceMove(get_step(usr,usr.dir))
src.update_icon()
diff --git a/code/modules/goonchat/browserOutput.dm b/code/modules/goonchat/browserOutput.dm
index 5bfcb9963d..13e7ee334f 100644
--- a/code/modules/goonchat/browserOutput.dm
+++ b/code/modules/goonchat/browserOutput.dm
@@ -179,6 +179,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
log_world("\[[time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")]\] Client: [(src.owner.key ? src.owner.key : src.owner)] triggered JS error: [error]")
//Global chat procs
+
/proc/to_chat(target, message)
if(!target)
return
diff --git a/code/modules/holiday/easter.dm b/code/modules/holiday/easter.dm
index 66d92df569..9c1fd87cac 100644
--- a/code/modules/holiday/easter.dm
+++ b/code/modules/holiday/easter.dm
@@ -109,8 +109,8 @@
/obj/item/reagent_containers/food/snacks/egg/loaded
containsPrize = TRUE
-/obj/item/reagent_containers/food/snacks/egg/loaded/New()
- ..()
+/obj/item/reagent_containers/food/snacks/egg/loaded/Initialize()
+ . = ..()
var/eggcolor = pick("blue","green","mime","orange","purple","rainbow","red","yellow")
icon_state = "egg-[eggcolor]"
item_color = "[eggcolor]"
diff --git a/code/modules/holiday/halloween.dm b/code/modules/holiday/halloween.dm
index f8716870e1..a27db8dd38 100644
--- a/code/modules/holiday/halloween.dm
+++ b/code/modules/holiday/halloween.dm
@@ -146,7 +146,7 @@
timer = rand(1,15)
/mob/living/simple_animal/shade/howling_ghost/proc/EtherealMove(direction)
- loc = get_step(src, direction)
+ forceMove(get_step(src, direction))
setDir(direction)
/mob/living/simple_animal/shade/howling_ghost/proc/roam()
@@ -220,7 +220,7 @@
timer = rand(5,15)
playsound(M.loc, pick('sound/spookoween/scary_horn.ogg','sound/spookoween/scary_horn2.ogg', 'sound/spookoween/scary_horn3.ogg'), 300, 1)
spawn(12)
- loc = M.loc
+ forceMove(M.loc)
/mob/living/simple_animal/hostile/retaliate/clown/insane/MoveToTarget()
stalk(target)
diff --git a/code/modules/holodeck/items.dm b/code/modules/holodeck/items.dm
index 54384753d7..1dcab21e16 100644
--- a/code/modules/holodeck/items.dm
+++ b/code/modules/holodeck/items.dm
@@ -25,13 +25,13 @@
armour_penetration = 50
var/active = 0
-/obj/item/holo/esword/green/New()
- ..()
+/obj/item/holo/esword/green/Initialize()
+ . = ..()
item_color = "green"
-/obj/item/holo/esword/red/New()
- ..()
+/obj/item/holo/esword/red/Initialize()
+ . = ..()
item_color = "red"
/obj/item/holo/esword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
@@ -42,9 +42,9 @@
/obj/item/holo/esword/attack(target as mob, mob/user as mob)
..()
-/obj/item/holo/esword/New()
+/obj/item/holo/esword/Initialize()
+ . = ..()
item_color = pick("red","blue","green","purple")
- ..()
/obj/item/holo/esword/attack_self(mob/living/user as mob)
active = !active
@@ -113,7 +113,7 @@
if(user.grab_state < GRAB_AGGRESSIVE)
to_chat(user, "You need a better grip to do that!")
return
- L.loc = src.loc
+ L.forceMove(loc)
L.Knockdown(100)
visible_message("[user] dunks [L] into \the [src]!")
user.stop_pulling()
diff --git a/code/modules/hydroponics/beekeeping/beebox.dm b/code/modules/hydroponics/beekeeping/beebox.dm
index 482a48edfd..cf12ccb3ce 100644
--- a/code/modules/hydroponics/beekeeping/beebox.dm
+++ b/code/modules/hydroponics/beekeeping/beebox.dm
@@ -37,8 +37,8 @@
var/bee_resources = 0
-/obj/structure/beebox/New()
- ..()
+/obj/structure/beebox/Initialize()
+ . = ..()
START_PROCESSING(SSobj, src)
@@ -55,8 +55,8 @@
var/random_reagent = FALSE
-/obj/structure/beebox/premade/New()
- ..()
+/obj/structure/beebox/premade/Initialize()
+ . = ..()
icon_state = "beebox"
var/datum/reagent/R = null
@@ -152,6 +152,7 @@
else
to_chat(user, "There's no room for any more frames in the apiary!")
return
+
if(istype(I, /obj/item/wrench))
if(default_unfasten_wrench(user, I, time = 20))
return
@@ -178,7 +179,7 @@
bees -= B
B.beehome = null
if(B.loc == src)
- B.loc = get_turf(src)
+ B.forceMove(drop_location())
relocated++
if(relocated)
to_chat(user, "This queen has a different reagent to some of the bees who live here, those bees will not return to this apiary!")
@@ -201,7 +202,7 @@
if(B.isqueen)
continue
if(B.loc == src)
- B.loc = get_turf(src)
+ B.forceMove(drop_location())
B.target = user
bees = TRUE
if(bees)
@@ -221,7 +222,7 @@
var/obj/item/honey_frame/HF = pick_n_take(honey_frames)
if(HF)
if(!user.put_in_active_hand(HF))
- HF.loc = get_turf(src)
+ HF.forceMove(drop_location())
visible_message("[user] removes a frame from the apiary.")
var/amtH = HF.honeycomb_capacity
@@ -229,7 +230,7 @@
while(honeycombs.len && amtH) //let's pretend you always grab the frame with the most honeycomb on it
var/obj/item/reagent_containers/honeycomb/HC = pick_n_take(honeycombs)
if(HC)
- HC.loc = get_turf(user)
+ HC.forceMove(drop_location())
amtH--
fallen++
if(fallen)
@@ -241,12 +242,12 @@
to_chat(user, "There is no queen bee to remove!")
return
var/obj/item/queen_bee/QB = new()
- queen_bee.loc = QB
+ queen_bee.forceMove(QB)
bees -= queen_bee
QB.queen = queen_bee
QB.name = queen_bee.name
if(!user.put_in_active_hand(QB))
- QB.loc = get_turf(src)
+ QB.forceMove(drop_location())
visible_message("[user] removes the queen from the apiary.")
queen_bee = null
@@ -254,8 +255,8 @@
new /obj/item/stack/sheet/mineral/wood (loc, 20)
for(var/mob/living/simple_animal/hostile/poison/bees/B in bees)
if(B.loc == src)
- B.loc = get_turf(src)
+ B.forceMove(drop_location())
for(var/obj/item/honey_frame/HF in honey_frames)
if(HF.loc == src)
- HF.loc = get_turf(src)
- qdel(src)
\ No newline at end of file
+ HF.forceMove(drop_location())
+ qdel(src)
diff --git a/code/modules/hydroponics/beekeeping/honeycomb.dm b/code/modules/hydroponics/beekeeping/honeycomb.dm
index 737736efc5..e7faff0209 100644
--- a/code/modules/hydroponics/beekeeping/honeycomb.dm
+++ b/code/modules/hydroponics/beekeeping/honeycomb.dm
@@ -10,10 +10,11 @@
volume = 10
amount_per_transfer_from_this = 0
list_reagents = list("honey" = 5)
+ grind_results = list()
var/honey_color = ""
-/obj/item/reagent_containers/honeycomb/New()
- ..()
+/obj/item/reagent_containers/honeycomb/Initialize()
+ . = ..()
pixel_x = rand(8,-8)
pixel_y = rand(8,-8)
update_icon()
diff --git a/code/modules/hydroponics/biogenerator.dm b/code/modules/hydroponics/biogenerator.dm
index 324a94128d..8939b60138 100644
--- a/code/modules/hydroponics/biogenerator.dm
+++ b/code/modules/hydroponics/biogenerator.dm
@@ -78,7 +78,7 @@
if(default_deconstruction_screwdriver(user, "biogen-empty-o", "biogen-empty", O))
if(beaker)
var/obj/item/reagent_containers/glass/B = beaker
- B.loc = loc
+ B.forceMove(drop_location())
beaker = null
update_icon()
return
diff --git a/code/modules/hydroponics/gene_modder.dm b/code/modules/hydroponics/gene_modder.dm
index bd0215138a..fe8a101053 100644
--- a/code/modules/hydroponics/gene_modder.dm
+++ b/code/modules/hydroponics/gene_modder.dm
@@ -260,7 +260,7 @@
if(href_list["eject_seed"] && !operation)
if (seed)
- seed.loc = src.loc
+ seed.forceMove(drop_location())
seed.verb_pickup()
seed = null
update_genes()
@@ -275,7 +275,7 @@
update_icon()
else if(href_list["eject_disk"] && !operation)
if (disk)
- disk.loc = src.loc
+ disk.forceMove(drop_location())
disk.verb_pickup()
disk = null
update_genes()
@@ -368,7 +368,7 @@
/obj/machinery/plantgenes/proc/insert_seed(obj/item/seeds/S)
if(!istype(S) || seed)
return
- S.loc = src
+ S.forceMove(src)
seed = S
update_genes()
update_icon()
@@ -422,8 +422,8 @@
var/read_only = 0 //Well, it's still a floppy disk
unique_rename = 1
-/obj/item/disk/plantgene/New()
- ..()
+/obj/item/disk/plantgene/Initialize()
+ . = ..()
add_overlay("datadisk_gene")
src.pixel_x = rand(-5, 5)
src.pixel_y = rand(-5, 5)
diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm
index d003f40d4a..643ac056e4 100644
--- a/code/modules/hydroponics/grown.dm
+++ b/code/modules/hydroponics/grown.dm
@@ -15,6 +15,7 @@
// Saves us from having to define each stupid grown's dried_type as itself.
// If you don't want a plant to be driable (watermelons) set this to null in the time definition.
resistance_flags = FLAMMABLE
+ var/dry_grind = FALSE //If TRUE, this object needs to be dry to be ground up
/obj/item/reagent_containers/food/snacks/grown/Initialize(mapload, obj/item/seeds/new_seed)
. = ..()
@@ -137,6 +138,28 @@
return
return ..()
+/obj/item/reagent_containers/food/snacks/grown/grind_requirements()
+ if(dry_grind && !dry)
+ to_chat(usr, "[src] needs to be dry before it can be ground up!")
+ return
+ return TRUE
+
+/obj/item/reagent_containers/food/snacks/grown/on_grind()
+ var/nutriment = reagents.get_reagent_amount("nutriment")
+ if(grind_results.len)
+ for(var/i in 1 to grind_results.len)
+ grind_results[grind_results[i]] = nutriment
+ reagents.del_reagent("nutriment")
+ reagents.del_reagent("vitamin")
+
+/obj/item/reagent_containers/food/snacks/grown/on_juice()
+ var/nutriment = reagents.get_reagent_amount("nutriment")
+ if(juice_results.len)
+ for(var/i in 1 to juice_results.len)
+ juice_results[juice_results[i]] = nutriment
+ reagents.del_reagent("nutriment")
+ reagents.del_reagent("vitamin")
+
// For item-containing growns such as eggy or gatfruit
/obj/item/reagent_containers/food/snacks/grown/shell/attack_self(mob/user)
var/obj/item/T
diff --git a/code/modules/hydroponics/grown/apple.dm b/code/modules/hydroponics/grown/apple.dm
index 7ec9a730ed..8b35fee872 100644
--- a/code/modules/hydroponics/grown/apple.dm
+++ b/code/modules/hydroponics/grown/apple.dm
@@ -15,6 +15,7 @@
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/apple/gold)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.1)
+ juice_results = list("applejuice" = 0)
/obj/item/reagent_containers/food/snacks/grown/apple
seed = /obj/item/seeds/apple
diff --git a/code/modules/hydroponics/grown/banana.dm b/code/modules/hydroponics/grown/banana.dm
index bf71856323..72517e87bc 100644
--- a/code/modules/hydroponics/grown/banana.dm
+++ b/code/modules/hydroponics/grown/banana.dm
@@ -13,6 +13,7 @@
genes = list(/datum/plant_gene/trait/slip, /datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/banana/mime, /obj/item/seeds/banana/bluespace)
reagents_add = list("banana" = 0.1, "potassium" = 0.1, "vitamin" = 0.04, "nutriment" = 0.02)
+ juice_results = list("banana" = 0)
/obj/item/reagent_containers/food/snacks/grown/banana
seed = /obj/item/seeds/banana
diff --git a/code/modules/hydroponics/grown/beans.dm b/code/modules/hydroponics/grown/beans.dm
index 8ca2a5961a..46a7e7979f 100644
--- a/code/modules/hydroponics/grown/beans.dm
+++ b/code/modules/hydroponics/grown/beans.dm
@@ -26,6 +26,7 @@
filling_color = "#F0E68C"
bitesize_mod = 2
foodtype = VEGETABLES
+ grind_results = list("soymilk" = 0)
// Koibean
/obj/item/seeds/soya/koi
diff --git a/code/modules/hydroponics/grown/berries.dm b/code/modules/hydroponics/grown/berries.dm
index 0d8c5d5a9a..541fb1b2a5 100644
--- a/code/modules/hydroponics/grown/berries.dm
+++ b/code/modules/hydroponics/grown/berries.dm
@@ -26,6 +26,7 @@
filling_color = "#FF00FF"
bitesize_mod = 2
foodtype = FRUIT
+ juice_results = list("berryjuice" = 0)
// Poison Berries
/obj/item/seeds/berry/poison
@@ -46,6 +47,7 @@
icon_state = "poisonberrypile"
filling_color = "#C71585"
foodtype = FRUIT | TOXIC
+ juice_results = list("poisonberryjuice" = 0)
// Death Berries
/obj/item/seeds/berry/death
@@ -121,6 +123,7 @@
filling_color = "#FF0000"
bitesize_mod = 2
foodtype = FRUIT
+ grind_results = list("cherryjelly" = 0)
// Blue Cherries
/obj/item/seeds/cherry/blue
@@ -142,6 +145,7 @@
filling_color = "#6495ED"
bitesize_mod = 2
foodtype = FRUIT
+ grind_results = list("bluecherryjelly" = 0)
// Grapes
/obj/item/seeds/grape
@@ -173,6 +177,7 @@
filling_color = "#FF1493"
bitesize_mod = 2
foodtype = FRUIT
+ juice_results = list("grapejuice" = 0)
// Green Grapes
/obj/item/seeds/grape/green
diff --git a/code/modules/hydroponics/grown/cereals.dm b/code/modules/hydroponics/grown/cereals.dm
index 7834ed15e8..d9b724d052 100644
--- a/code/modules/hydroponics/grown/cereals.dm
+++ b/code/modules/hydroponics/grown/cereals.dm
@@ -22,6 +22,7 @@
filling_color = "#F0E68C"
bitesize_mod = 2
foodtype = GRAIN
+ grind_results = list("flour" = 0)
// Oat
/obj/item/seeds/wheat/oat
@@ -42,6 +43,7 @@
filling_color = "#556B2F"
bitesize_mod = 2
foodtype = GRAIN
+ grind_results = list("flour" = 0)
// Rice
/obj/item/seeds/wheat/rice
@@ -63,6 +65,7 @@
filling_color = "#FAFAD2"
bitesize_mod = 2
foodtype = GRAIN
+ grind_results = list("rice" = 0)
//Meatwheat - grows into synthetic meat
/obj/item/seeds/wheat/meat
@@ -83,6 +86,7 @@
bitesize_mod = 2
seed = /obj/item/seeds/wheat/meat
foodtype = MEAT | GRAIN
+ grind_results = list("flour" = 0, "blood" = 0)
/obj/item/reagent_containers/food/snacks/grown/meatwheat/attack_self(mob/living/user)
user.visible_message("[user] crushes [src] into meat.", "You crush [src] into something that resembles meat.")
diff --git a/code/modules/hydroponics/grown/citrus.dm b/code/modules/hydroponics/grown/citrus.dm
index 1b0cdc00d2..38f8a40ec3 100644
--- a/code/modules/hydroponics/grown/citrus.dm
+++ b/code/modules/hydroponics/grown/citrus.dm
@@ -30,6 +30,7 @@
desc = "It's so sour, your face will twist."
icon_state = "lime"
filling_color = "#00FF00"
+ juice_results = list("limejuice" = 0)
// Orange
/obj/item/seeds/orange
@@ -56,6 +57,7 @@
desc = "It's a tangy fruit."
icon_state = "orange"
filling_color = "#FFA500"
+ juice_results = list("orangejuice" = 0)
// Lemon
/obj/item/seeds/lemon
@@ -81,6 +83,7 @@
desc = "When life gives you lemons, make lemonade."
icon_state = "lemon"
filling_color = "#FFD700"
+ juice_results = list("lemonjuice" = 0)
// Combustible lemon
/obj/item/seeds/firelemon //combustible lemon is too long so firelemon
diff --git a/code/modules/hydroponics/grown/corn.dm b/code/modules/hydroponics/grown/corn.dm
index 827deaea47..4454c3c52a 100644
--- a/code/modules/hydroponics/grown/corn.dm
+++ b/code/modules/hydroponics/grown/corn.dm
@@ -25,6 +25,7 @@
trash = /obj/item/grown/corncob
bitesize_mod = 2
foodtype = VEGETABLES
+ juice_results = list("corn_starch" = 0)
/obj/item/grown/corncob
name = "corn cob"
diff --git a/code/modules/hydroponics/grown/flowers.dm b/code/modules/hydroponics/grown/flowers.dm
index e0845ffb2a..18eae2f4fd 100644
--- a/code/modules/hydroponics/grown/flowers.dm
+++ b/code/modules/hydroponics/grown/flowers.dm
@@ -182,6 +182,7 @@
throw_speed = 1
throw_range = 3
attack_verb = list("roasted", "scorched", "burned")
+ grind_results = list("capsaicin" = 0, "condensedcapsaicin" = 0)
/obj/item/grown/novaflower/add_juice()
..()
diff --git a/code/modules/hydroponics/grown/melon.dm b/code/modules/hydroponics/grown/melon.dm
index 5e64d716ec..a64fc4b156 100644
--- a/code/modules/hydroponics/grown/melon.dm
+++ b/code/modules/hydroponics/grown/melon.dm
@@ -33,6 +33,7 @@
filling_color = "#008000"
bitesize_mod = 3
foodtype = FRUIT
+ juice_results = list("watermelonjuice" = 0)
// Holymelon
/obj/item/seeds/watermelon/holy
diff --git a/code/modules/hydroponics/grown/nettle.dm b/code/modules/hydroponics/grown/nettle.dm
index 284f962e45..9ec936c1f2 100644
--- a/code/modules/hydroponics/grown/nettle.dm
+++ b/code/modules/hydroponics/grown/nettle.dm
@@ -43,6 +43,7 @@
throw_speed = 1
throw_range = 3
attack_verb = list("stung")
+ grind_results = list("sacid" = 0)
/obj/item/grown/nettle/suicide_act(mob/user)
user.visible_message("[user] is eating some of [src]! It looks like [user.p_theyre()] trying to commit suicide!")
@@ -91,6 +92,7 @@
icon_state = "deathnettle"
force = 30
throwforce = 15
+ grind_results = list("facid" = 1, "sacid" = 1)
/obj/item/grown/nettle/death/add_juice()
..()
diff --git a/code/modules/hydroponics/grown/potato.dm b/code/modules/hydroponics/grown/potato.dm
index 0a3cbc060c..e127b166ea 100644
--- a/code/modules/hydroponics/grown/potato.dm
+++ b/code/modules/hydroponics/grown/potato.dm
@@ -17,6 +17,7 @@
genes = list(/datum/plant_gene/trait/battery)
mutatelist = list(/obj/item/seeds/potato/sweet)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.1)
+ juice_results = list("potato" = 0)
/obj/item/reagent_containers/food/snacks/grown/potato
seed = /obj/item/seeds/potato
diff --git a/code/modules/hydroponics/grown/pumpkin.dm b/code/modules/hydroponics/grown/pumpkin.dm
index d5257aeee7..7113a8feab 100644
--- a/code/modules/hydroponics/grown/pumpkin.dm
+++ b/code/modules/hydroponics/grown/pumpkin.dm
@@ -24,6 +24,7 @@
filling_color = "#FFA500"
bitesize_mod = 2
foodtype = VEGETABLES
+ juice_results = list("pumpkinjuice" = 0)
/obj/item/reagent_containers/food/snacks/grown/pumpkin/attackby(obj/item/W as obj, mob/user as mob, params)
if(W.is_sharp())
@@ -53,4 +54,5 @@
icon_state = "blumpkin"
filling_color = "#87CEFA"
bitesize_mod = 2
- foodtype = VEGETABLES
\ No newline at end of file
+ foodtype = VEGETABLES
+ juice_results = list("blumpkinjuice" = 0)
diff --git a/code/modules/hydroponics/grown/random.dm b/code/modules/hydroponics/grown/random.dm
index 8f25eff215..04b3ff29fa 100644
--- a/code/modules/hydroponics/grown/random.dm
+++ b/code/modules/hydroponics/grown/random.dm
@@ -12,9 +12,9 @@
icon_harvest = "xpod-harvest"
growthstages = 4
-/obj/item/seeds/random/New()
+/obj/item/seeds/random/Initialize()
+ . = ..()
randomize_stats()
- ..()
if(prob(60))
add_random_reagents(1, 3)
if(prob(50))
diff --git a/code/modules/hydroponics/grown/root.dm b/code/modules/hydroponics/grown/root.dm
index 8666db45a8..fd78fa6ffa 100644
--- a/code/modules/hydroponics/grown/root.dm
+++ b/code/modules/hydroponics/grown/root.dm
@@ -22,6 +22,7 @@
filling_color = "#FFA500"
bitesize_mod = 2
foodtype = VEGETABLES
+ juice_results = list("carrotjuice" = 0)
/obj/item/reagent_containers/food/snacks/grown/carrot/attackby(obj/item/I, mob/user, params)
if(I.is_sharp())
diff --git a/code/modules/hydroponics/grown/tea_coffee.dm b/code/modules/hydroponics/grown/tea_coffee.dm
index bd3b182c13..fc2ed221c5 100644
--- a/code/modules/hydroponics/grown/tea_coffee.dm
+++ b/code/modules/hydroponics/grown/tea_coffee.dm
@@ -14,7 +14,6 @@
icon_dead = "tea-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/tea/astra)
- reagents_add = list("vitamin" = 0.04, "teapowder" = 0.1)
/obj/item/reagent_containers/food/snacks/grown/tea
seed = /obj/item/seeds/tea
@@ -22,6 +21,8 @@
desc = "These aromatic tips of the tea plant can be dried to make tea."
icon_state = "tea_aspera_leaves"
filling_color = "#008000"
+ grind_results = list("teapowder" = 0)
+ dry_grind = TRUE
// Tea Astra
/obj/item/seeds/tea/astra
@@ -39,6 +40,7 @@
name = "Tea Astra tips"
icon_state = "tea_astra_leaves"
filling_color = "#4582B4"
+ grind_results = list("teapowder" = 0, "salglu_solution" = 0)
// Coffee
@@ -67,6 +69,8 @@
icon_state = "coffee_arabica"
filling_color = "#DC143C"
bitesize_mod = 2
+ dry_grind = TRUE
+ grind_results = list("coffeepowder" = 0)
// Coffee Robusta
/obj/item/seeds/coffee/robusta
@@ -84,4 +88,5 @@
seed = /obj/item/seeds/coffee/robusta
name = "coffee robusta beans"
desc = "Increases robustness by 37 percent!"
- icon_state = "coffee_robusta"
\ No newline at end of file
+ icon_state = "coffee_robusta"
+ grind_results = list("coffeepowder" = 0, "morphine" = 0)
diff --git a/code/modules/hydroponics/grown/tomato.dm b/code/modules/hydroponics/grown/tomato.dm
index 1bc42b45c0..4d066e769e 100644
--- a/code/modules/hydroponics/grown/tomato.dm
+++ b/code/modules/hydroponics/grown/tomato.dm
@@ -23,6 +23,8 @@
filling_color = "#FF6347"
bitesize_mod = 2
foodtype = VEGETABLES
+ grind_results = list("ketchup" = 0)
+ juice_results = list("tomatojuice" = 0)
// Blood Tomato
/obj/item/seeds/tomato/blood
@@ -44,6 +46,7 @@
splat_type = /obj/effect/gibspawner/generic
filling_color = "#FF0000"
foodtype = VEGETABLES | GROSS
+ grind_results = list("ketchup" = 0, "blood" = 0)
// Blue Tomato
diff --git a/code/modules/hydroponics/growninedible.dm b/code/modules/hydroponics/growninedible.dm
index a77808f006..3b80fae6c0 100644
--- a/code/modules/hydroponics/growninedible.dm
+++ b/code/modules/hydroponics/growninedible.dm
@@ -62,3 +62,7 @@
/obj/item/grown/microwave_act(obj/machine/microwave/M)
return
+
+/obj/item/grown/on_grind()
+ for(var/i in 1 to grind_results.len)
+ grind_results[grind_results[i]] = round(seed.potency)
diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm
index 9eafcec71b..5c1fafc1c4 100644
--- a/code/modules/hydroponics/hydroponics.dm
+++ b/code/modules/hydroponics/hydroponics.dm
@@ -108,7 +108,7 @@
var/needs_update = 0 // Checks if the icon needs updating so we don't redraw empty trays every time
if(myseed && (myseed.loc != src))
- myseed.loc = src
+ myseed.forceMove(src)
if(self_sustaining)
adjustNutri(1)
diff --git a/code/modules/hydroponics/sample.dm b/code/modules/hydroponics/sample.dm
index 52c2e1052f..fff4c646ac 100644
--- a/code/modules/hydroponics/sample.dm
+++ b/code/modules/hydroponics/sample.dm
@@ -5,8 +5,8 @@
yield = -1
var/sample_color = "#FFFFFF"
-/obj/item/seeds/sample/New()
- ..()
+/obj/item/seeds/sample/Initialize()
+ . = ..()
if(sample_color)
var/mutable_appearance/filling = mutable_appearance(icon, "sample-filling")
filling.color = sample_color
diff --git a/code/modules/hydroponics/seed_extractor.dm b/code/modules/hydroponics/seed_extractor.dm
index 0899a21132..b79d0652aa 100644
--- a/code/modules/hydroponics/seed_extractor.dm
+++ b/code/modules/hydroponics/seed_extractor.dm
@@ -17,7 +17,7 @@
return
while(t_amount < t_max)
var/obj/item/seeds/t_prod = F.seed.Copy()
- t_prod.loc = seedloc
+ t_prod.forceMove(seedloc)
t_amount++
qdel(O)
return 1
@@ -29,7 +29,7 @@
return
while(t_amount < t_max)
var/obj/item/seeds/t_prod = F.seed.Copy()
- t_prod.loc = seedloc
+ t_prod.forceMove(seedloc)
t_amount++
qdel(O)
return 1
@@ -168,7 +168,7 @@
for (var/obj/T in contents)//Now we find the seed we need to vend
var/obj/item/seeds/O = T
if (O.plantname == href_list["name"] && O.lifespan == href_list["li"] && O.endurance == href_list["en"] && O.maturation == href_list["ma"] && O.production == href_list["pr"] && O.yield == href_list["yi"] && O.potency == href_list["pot"])
- O.loc = src.loc
+ O.forceMove(drop_location())
break
src.updateUsrDialog()
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index aa35b4ae07..7294e45a97 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -35,8 +35,8 @@
var/weed_rate = 1 //If the chance below passes, then this many weeds sprout during growth
var/weed_chance = 5 //Percentage chance per tray update to grow weeds
-/obj/item/seeds/New(loc, nogenes = 0)
- ..()
+/obj/item/seeds/Initialize(loc, nogenes = 0)
+ . = ..()
pixel_x = rand(-8, 8)
pixel_y = rand(-8, 8)
diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm
index 276d3d9ca0..4429fd7128 100644
--- a/code/modules/integrated_electronics/subtypes/input.dm
+++ b/code/modules/integrated_electronics/subtypes/input.dm
@@ -478,8 +478,8 @@
power_draw_idle = 5
power_draw_per_use = 40
- var/frequency = 1457
- var/code = 30
+ var/frequency = FREQ_SIGNALER
+ var/code = DEFAULT_SIGNALER_CODE
var/datum/radio_frequency/radio_connection
/obj/item/integrated_circuit/input/signaler/Initialize()
@@ -509,24 +509,16 @@
if(!radio_connection)
return
- var/datum/signal/signal = new
- signal.source = src
- signal.encryption = code
- signal.data["message"] = "ACTIVATE"
+ var/datum/signal/signal = new(list("code" = code))
radio_connection.post_signal(src, signal)
-
activate_pin(2)
/obj/item/integrated_circuit/input/signaler/proc/set_frequency(new_frequency)
if(!frequency)
return
- if(!SSradio)
- sleep(20)
- if(!SSradio)
- return
SSradio.remove_object(src, frequency)
frequency = new_frequency
- radio_connection = SSradio.add_object(src, frequency, GLOB.RADIO_CHAT)
+ radio_connection = SSradio.add_object(src, frequency, RADIO_SIGNALER)
/obj/item/integrated_circuit/input/signaler/receive_signal(datum/signal/signal)
var/new_code = get_pin_data(IC_INPUT, 2)
@@ -536,7 +528,7 @@
code = new_code
if(!signal)
return 0
- if(signal.encryption != code)
+ if(signal.data["code"] != code)
return 0
if(signal.source == src) // Don't trigger ourselves.
return 0
diff --git a/code/modules/integrated_electronics/subtypes/reagents.dm b/code/modules/integrated_electronics/subtypes/reagents.dm
index 564c3a4851..d5a5584f82 100644
--- a/code/modules/integrated_electronics/subtypes/reagents.dm
+++ b/code/modules/integrated_electronics/subtypes/reagents.dm
@@ -288,6 +288,7 @@
activators = list()
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
+
/obj/item/integrated_circuit/reagent/storage/interact(mob/user)
set_pin_data(IC_OUTPUT, 2, WEAKREF(src))
push_data()
diff --git a/code/modules/jobs/job_exp.dm b/code/modules/jobs/job_exp.dm
index 220fa2e9ac..83a2af9b4c 100644
--- a/code/modules/jobs/job_exp.dm
+++ b/code/modules/jobs/job_exp.dm
@@ -263,4 +263,4 @@ GLOBAL_PROTECT(exp_to_update)
prefs.db_flags = text2num(flags_read.item[1])
else if(isnull(prefs.db_flags))
prefs.db_flags = 0 //This PROBABLY won't happen, but better safe than sorry.
- return TRUE
+ return TRUE
\ No newline at end of file
diff --git a/code/modules/jobs/job_types/captain.dm b/code/modules/jobs/job_types/captain.dm
index 03498f1e7b..38418e9916 100755
--- a/code/modules/jobs/job_types/captain.dm
+++ b/code/modules/jobs/job_types/captain.dm
@@ -1,77 +1,77 @@
-/*
-Captain
-*/
-/datum/job/captain
- title = "Captain"
- flag = CAPTAIN
+/*
+Captain
+*/
+/datum/job/captain
+ title = "Captain"
+ flag = CAPTAIN
department_head = list("CentCom")
- department_flag = ENGSEC
- faction = "Station"
- total_positions = 1
- spawn_positions = 1
- supervisors = "Nanotrasen officials and Space law"
- selection_color = "#ccccff"
- req_admin_notify = 1
- minimal_player_age = 14
+ department_flag = ENGSEC
+ faction = "Station"
+ total_positions = 1
+ spawn_positions = 1
+ supervisors = "Nanotrasen officials and Space law"
+ selection_color = "#ccccff"
+ req_admin_notify = 1
+ minimal_player_age = 14
exp_requirements = 180
exp_type = EXP_TYPE_CREW
-
- outfit = /datum/outfit/job/captain
-
- access = list() //See get_access()
- minimal_access = list() //See get_access()
-
-/datum/job/captain/get_access()
- return get_all_accesses()
-
-/datum/job/captain/announce(mob/living/carbon/human/H)
- ..()
- SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, .proc/minor_announce, "Captain [H.real_name] on deck!"))
-
-/datum/outfit/job/captain
- name = "Captain"
- jobtype = /datum/job/captain
-
- id = /obj/item/card/id/gold
- belt = /obj/item/device/pda/captain
- glasses = /obj/item/clothing/glasses/sunglasses
- ears = /obj/item/device/radio/headset/heads/captain/alt
- gloves = /obj/item/clothing/gloves/color/captain
- uniform = /obj/item/clothing/under/rank/captain
- suit = /obj/item/clothing/suit/armor/vest/capcarapace
- shoes = /obj/item/clothing/shoes/sneakers/brown
- head = /obj/item/clothing/head/caphat
- backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/station_charter=1)
-
- backpack = /obj/item/storage/backpack/captain
- satchel = /obj/item/storage/backpack/satchel/cap
- duffelbag = /obj/item/storage/backpack/duffelbag/captain
-
- implants = list(/obj/item/implant/mindshield)
- accessory = /obj/item/clothing/accessory/medal/gold/captain
-
-/*
-Head of Personnel
-*/
-/datum/job/hop
- title = "Head of Personnel"
- flag = HOP
- department_head = list("Captain")
- department_flag = CIVILIAN
- head_announce = list("Supply", "Service")
- faction = "Station"
- total_positions = 1
- spawn_positions = 1
- supervisors = "the captain"
- selection_color = "#ddddff"
- req_admin_notify = 1
- minimal_player_age = 10
+
+ outfit = /datum/outfit/job/captain
+
+ access = list() //See get_access()
+ minimal_access = list() //See get_access()
+
+/datum/job/captain/get_access()
+ return get_all_accesses()
+
+/datum/job/captain/announce(mob/living/carbon/human/H)
+ ..()
+ SSticker.OnRoundstart(CALLBACK(GLOBAL_PROC, .proc/minor_announce, "Captain [H.real_name] on deck!"))
+
+/datum/outfit/job/captain
+ name = "Captain"
+ jobtype = /datum/job/captain
+
+ id = /obj/item/card/id/gold
+ belt = /obj/item/device/pda/captain
+ glasses = /obj/item/clothing/glasses/sunglasses
+ ears = /obj/item/device/radio/headset/heads/captain/alt
+ gloves = /obj/item/clothing/gloves/color/captain
+ uniform = /obj/item/clothing/under/rank/captain
+ suit = /obj/item/clothing/suit/armor/vest/capcarapace
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ head = /obj/item/clothing/head/caphat
+ backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/station_charter=1)
+
+ backpack = /obj/item/storage/backpack/captain
+ satchel = /obj/item/storage/backpack/satchel/cap
+ duffelbag = /obj/item/storage/backpack/duffelbag/captain
+
+ implants = list(/obj/item/implant/mindshield)
+ accessory = /obj/item/clothing/accessory/medal/gold/captain
+
+/*
+Head of Personnel
+*/
+/datum/job/hop
+ title = "Head of Personnel"
+ flag = HOP
+ department_head = list("Captain")
+ department_flag = CIVILIAN
+ head_announce = list("Supply", "Service")
+ faction = "Station"
+ total_positions = 1
+ spawn_positions = 1
+ supervisors = "the captain"
+ selection_color = "#ddddff"
+ req_admin_notify = 1
+ minimal_player_age = 10
exp_requirements = 180
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_SUPPLY
-
- outfit = /datum/outfit/job/hop
-
+
+ outfit = /datum/outfit/job/hop
+
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_COURT, ACCESS_WEAPONS,
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_EVA, ACCESS_HEADS,
ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_MAINT_TUNNELS, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CONSTRUCTION, ACCESS_MORGUE,
@@ -84,17 +84,17 @@ Head of Personnel
ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MAILSORTING, ACCESS_QM, ACCESS_HYDROPONICS, ACCESS_LAWYER,
ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_HEADS_VAULT, ACCESS_MINING_STATION,
ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM)
-
-
-/datum/outfit/job/hop
- name = "Head of Personnel"
- jobtype = /datum/job/hop
-
- id = /obj/item/card/id/silver
- belt = /obj/item/device/pda/heads/hop
- ears = /obj/item/device/radio/headset/heads/hop
- uniform = /obj/item/clothing/under/rank/head_of_personnel
- shoes = /obj/item/clothing/shoes/sneakers/brown
- head = /obj/item/clothing/head/hopcap
- backpack_contents = list(/obj/item/storage/box/ids=1,\
- /obj/item/melee/classic_baton/telescopic=1, /obj/item/device/modular_computer/tablet/preset/advanced = 1)
+
+
+/datum/outfit/job/hop
+ name = "Head of Personnel"
+ jobtype = /datum/job/hop
+
+ id = /obj/item/card/id/silver
+ belt = /obj/item/device/pda/heads/hop
+ ears = /obj/item/device/radio/headset/heads/hop
+ uniform = /obj/item/clothing/under/rank/head_of_personnel
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ head = /obj/item/clothing/head/hopcap
+ backpack_contents = list(/obj/item/storage/box/ids=1,\
+ /obj/item/melee/classic_baton/telescopic=1, /obj/item/device/modular_computer/tablet/preset/advanced = 1)
diff --git a/code/modules/jobs/job_types/job.dm b/code/modules/jobs/job_types/job.dm
index 2e18807541..6720c28710 100644
--- a/code/modules/jobs/job_types/job.dm
+++ b/code/modules/jobs/job_types/job.dm
@@ -72,14 +72,15 @@
H.dna.species.after_equip_job(src, H, visualsOnly)
+ if(CONFIG_GET(flag/enforce_human_authority) && (title in GLOB.command_positions))
+ if(H.dna.species.id != "human")
+ H.set_species(/datum/species/human)
+ H.rename_self("human", H.client)
+ purrbation_remove(H, silent=TRUE)
+
if(!visualsOnly && announce)
announce(H)
- if(CONFIG_GET(flag/enforce_human_authority) && (title in GLOB.command_positions))
- H.dna.features["tail_human"] = "None"
- H.dna.features["ears"] = "None"
- H.regenerate_icons()
-
/datum/job/proc/get_access()
if(!config) //Needed for robots.
return src.minimal_access.Copy()
diff --git a/code/modules/jobs/job_types/medical.dm b/code/modules/jobs/job_types/medical.dm
index 9a33e1e759..151ed213f8 100644
--- a/code/modules/jobs/job_types/medical.dm
+++ b/code/modules/jobs/job_types/medical.dm
@@ -1,191 +1,191 @@
-/*
-Chief Medical Officer
-*/
-/datum/job/cmo
- title = "Chief Medical Officer"
- flag = CMO_JF
- department_head = list("Captain")
- department_flag = MEDSCI
- head_announce = list("Medical")
- faction = "Station"
- total_positions = 1
- spawn_positions = 1
- supervisors = "the captain"
- selection_color = "#ffddf0"
- req_admin_notify = 1
- minimal_player_age = 7
+/*
+Chief Medical Officer
+*/
+/datum/job/cmo
+ title = "Chief Medical Officer"
+ flag = CMO_JF
+ department_head = list("Captain")
+ department_flag = MEDSCI
+ head_announce = list("Medical")
+ faction = "Station"
+ total_positions = 1
+ spawn_positions = 1
+ supervisors = "the captain"
+ selection_color = "#ffddf0"
+ req_admin_notify = 1
+ minimal_player_age = 7
exp_requirements = 180
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_MEDICAL
-
- outfit = /datum/outfit/job/cmo
-
+
+ outfit = /datum/outfit/job/cmo
+
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_HEADS, ACCESS_MINERAL_STOREROOM,
ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_SURGERY, ACCESS_RC_ANNOUNCE,
ACCESS_KEYCARD_AUTH, ACCESS_SEC_DOORS, ACCESS_MAINT_TUNNELS)
minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_HEADS, ACCESS_MINERAL_STOREROOM,
ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_SURGERY, ACCESS_RC_ANNOUNCE,
ACCESS_KEYCARD_AUTH, ACCESS_SEC_DOORS, ACCESS_MAINT_TUNNELS)
-
-/datum/outfit/job/cmo
- name = "Chief Medical Officer"
- jobtype = /datum/job/cmo
-
- id = /obj/item/card/id/silver
- belt = /obj/item/device/pda/heads/cmo
+
+/datum/outfit/job/cmo
+ name = "Chief Medical Officer"
+ jobtype = /datum/job/cmo
+
+ id = /obj/item/card/id/silver
+ belt = /obj/item/device/pda/heads/cmo
l_pocket = /obj/item/pinpointer/crew
- ears = /obj/item/device/radio/headset/heads/cmo
- uniform = /obj/item/clothing/under/rank/chief_medical_officer
- shoes = /obj/item/clothing/shoes/sneakers/brown
- suit = /obj/item/clothing/suit/toggle/labcoat/cmo
- l_hand = /obj/item/storage/firstaid/regular
- suit_store = /obj/item/device/flashlight/pen
- backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1)
-
- backpack = /obj/item/storage/backpack/medic
- satchel = /obj/item/storage/backpack/satchel/med
- duffelbag = /obj/item/storage/backpack/duffelbag/med
-
-/*
-Medical Doctor
-*/
-/datum/job/doctor
- title = "Medical Doctor"
- flag = DOCTOR
- department_head = list("Chief Medical Officer")
- department_flag = MEDSCI
- faction = "Station"
- total_positions = 5
- spawn_positions = 3
- supervisors = "the chief medical officer"
- selection_color = "#ffeef0"
-
- outfit = /datum/outfit/job/doctor
-
+ ears = /obj/item/device/radio/headset/heads/cmo
+ uniform = /obj/item/clothing/under/rank/chief_medical_officer
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ suit = /obj/item/clothing/suit/toggle/labcoat/cmo
+ l_hand = /obj/item/storage/firstaid/regular
+ suit_store = /obj/item/device/flashlight/pen
+ backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1)
+
+ backpack = /obj/item/storage/backpack/medic
+ satchel = /obj/item/storage/backpack/satchel/med
+ duffelbag = /obj/item/storage/backpack/duffelbag/med
+
+/*
+Medical Doctor
+*/
+/datum/job/doctor
+ title = "Medical Doctor"
+ flag = DOCTOR
+ department_head = list("Chief Medical Officer")
+ department_flag = MEDSCI
+ faction = "Station"
+ total_positions = 5
+ spawn_positions = 3
+ supervisors = "the chief medical officer"
+ selection_color = "#ffeef0"
+
+ outfit = /datum/outfit/job/doctor
+
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CLONING)
-
-/datum/outfit/job/doctor
- name = "Medical Doctor"
- jobtype = /datum/job/doctor
-
- belt = /obj/item/device/pda/medical
- ears = /obj/item/device/radio/headset/headset_med
- uniform = /obj/item/clothing/under/rank/medical
- shoes = /obj/item/clothing/shoes/sneakers/white
- suit = /obj/item/clothing/suit/toggle/labcoat
- l_hand = /obj/item/storage/firstaid/regular
- suit_store = /obj/item/device/flashlight/pen
-
- backpack = /obj/item/storage/backpack/medic
- satchel = /obj/item/storage/backpack/satchel/med
- duffelbag = /obj/item/storage/backpack/duffelbag/med
-
-/*
-Chemist
-*/
-/datum/job/chemist
- title = "Chemist"
- flag = CHEMIST
- department_head = list("Chief Medical Officer")
- department_flag = MEDSCI
- faction = "Station"
- total_positions = 2
- spawn_positions = 2
- supervisors = "the chief medical officer"
- selection_color = "#ffeef0"
+
+/datum/outfit/job/doctor
+ name = "Medical Doctor"
+ jobtype = /datum/job/doctor
+
+ belt = /obj/item/device/pda/medical
+ ears = /obj/item/device/radio/headset/headset_med
+ uniform = /obj/item/clothing/under/rank/medical
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat
+ l_hand = /obj/item/storage/firstaid/regular
+ suit_store = /obj/item/device/flashlight/pen
+
+ backpack = /obj/item/storage/backpack/medic
+ satchel = /obj/item/storage/backpack/satchel/med
+ duffelbag = /obj/item/storage/backpack/duffelbag/med
+
+/*
+Chemist
+*/
+/datum/job/chemist
+ title = "Chemist"
+ flag = CHEMIST
+ department_head = list("Chief Medical Officer")
+ department_flag = MEDSCI
+ faction = "Station"
+ total_positions = 2
+ spawn_positions = 2
+ supervisors = "the chief medical officer"
+ selection_color = "#ffeef0"
exp_type = EXP_TYPE_CREW
exp_requirements = 60
-
- outfit = /datum/outfit/job/chemist
-
+
+ outfit = /datum/outfit/job/chemist
+
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_MEDICAL, ACCESS_CHEMISTRY, ACCESS_MINERAL_STOREROOM)
-
-/datum/outfit/job/chemist
- name = "Chemist"
- jobtype = /datum/job/chemist
-
- glasses = /obj/item/clothing/glasses/science
- belt = /obj/item/device/pda/chemist
- ears = /obj/item/device/radio/headset/headset_med
- uniform = /obj/item/clothing/under/rank/chemist
- shoes = /obj/item/clothing/shoes/sneakers/white
- suit = /obj/item/clothing/suit/toggle/labcoat/chemist
- accessory = /obj/item/clothing/accessory/pocketprotector/full
- backpack = /obj/item/storage/backpack/chemistry
- satchel = /obj/item/storage/backpack/satchel/chem
- duffelbag = /obj/item/storage/backpack/duffelbag/med
-
-/*
-Geneticist
-*/
-/datum/job/geneticist
- title = "Geneticist"
- flag = GENETICIST
- department_head = list("Chief Medical Officer", "Research Director")
- department_flag = MEDSCI
- faction = "Station"
- total_positions = 2
- spawn_positions = 2
- supervisors = "the chief medical officer and research director"
- selection_color = "#ffeef0"
+
+/datum/outfit/job/chemist
+ name = "Chemist"
+ jobtype = /datum/job/chemist
+
+ glasses = /obj/item/clothing/glasses/science
+ belt = /obj/item/device/pda/chemist
+ ears = /obj/item/device/radio/headset/headset_med
+ uniform = /obj/item/clothing/under/rank/chemist
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat/chemist
+ accessory = /obj/item/clothing/accessory/pocketprotector/full
+ backpack = /obj/item/storage/backpack/chemistry
+ satchel = /obj/item/storage/backpack/satchel/chem
+ duffelbag = /obj/item/storage/backpack/duffelbag/med
+
+/*
+Geneticist
+*/
+/datum/job/geneticist
+ title = "Geneticist"
+ flag = GENETICIST
+ department_head = list("Chief Medical Officer", "Research Director")
+ department_flag = MEDSCI
+ faction = "Station"
+ total_positions = 2
+ spawn_positions = 2
+ supervisors = "the chief medical officer and research director"
+ selection_color = "#ffeef0"
exp_type = EXP_TYPE_CREW
exp_requirements = 60
-
- outfit = /datum/outfit/job/geneticist
-
+
+ outfit = /datum/outfit/job/geneticist
+
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_CHEMISTRY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_ROBOTICS, ACCESS_MINERAL_STOREROOM, ACCESS_TECH_STORAGE)
minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_RESEARCH)
-
-/datum/outfit/job/geneticist
- name = "Geneticist"
- jobtype = /datum/job/geneticist
-
- belt = /obj/item/device/pda/geneticist
- ears = /obj/item/device/radio/headset/headset_medsci
- uniform = /obj/item/clothing/under/rank/geneticist
- shoes = /obj/item/clothing/shoes/sneakers/white
- suit = /obj/item/clothing/suit/toggle/labcoat/genetics
- suit_store = /obj/item/device/flashlight/pen
-
- backpack = /obj/item/storage/backpack/genetics
- satchel = /obj/item/storage/backpack/satchel/gen
- duffelbag = /obj/item/storage/backpack/duffelbag/med
-
-/*
-Virologist
-*/
-/datum/job/virologist
- title = "Virologist"
- flag = VIROLOGIST
- department_head = list("Chief Medical Officer")
- department_flag = MEDSCI
- faction = "Station"
- total_positions = 1
- spawn_positions = 1
- supervisors = "the chief medical officer"
- selection_color = "#ffeef0"
+
+/datum/outfit/job/geneticist
+ name = "Geneticist"
+ jobtype = /datum/job/geneticist
+
+ belt = /obj/item/device/pda/geneticist
+ ears = /obj/item/device/radio/headset/headset_medsci
+ uniform = /obj/item/clothing/under/rank/geneticist
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat/genetics
+ suit_store = /obj/item/device/flashlight/pen
+
+ backpack = /obj/item/storage/backpack/genetics
+ satchel = /obj/item/storage/backpack/satchel/gen
+ duffelbag = /obj/item/storage/backpack/duffelbag/med
+
+/*
+Virologist
+*/
+/datum/job/virologist
+ title = "Virologist"
+ flag = VIROLOGIST
+ department_head = list("Chief Medical Officer")
+ department_flag = MEDSCI
+ faction = "Station"
+ total_positions = 1
+ spawn_positions = 1
+ supervisors = "the chief medical officer"
+ selection_color = "#ffeef0"
exp_type = EXP_TYPE_CREW
exp_requirements = 60
-
- outfit = /datum/outfit/job/virologist
-
+
+ outfit = /datum/outfit/job/virologist
+
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_CLONING, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_MEDICAL, ACCESS_VIROLOGY, ACCESS_MINERAL_STOREROOM)
-
-/datum/outfit/job/virologist
- name = "Virologist"
- jobtype = /datum/job/virologist
-
- belt = /obj/item/device/pda/viro
- ears = /obj/item/device/radio/headset/headset_med
- uniform = /obj/item/clothing/under/rank/virologist
- mask = /obj/item/clothing/mask/surgical
- shoes = /obj/item/clothing/shoes/sneakers/white
- suit = /obj/item/clothing/suit/toggle/labcoat/virologist
- suit_store = /obj/item/device/flashlight/pen
-
- backpack = /obj/item/storage/backpack/virology
- satchel = /obj/item/storage/backpack/satchel/vir
- duffelbag = /obj/item/storage/backpack/duffelbag/med
+
+/datum/outfit/job/virologist
+ name = "Virologist"
+ jobtype = /datum/job/virologist
+
+ belt = /obj/item/device/pda/viro
+ ears = /obj/item/device/radio/headset/headset_med
+ uniform = /obj/item/clothing/under/rank/virologist
+ mask = /obj/item/clothing/mask/surgical
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat/virologist
+ suit_store = /obj/item/device/flashlight/pen
+
+ backpack = /obj/item/storage/backpack/virology
+ satchel = /obj/item/storage/backpack/satchel/vir
+ duffelbag = /obj/item/storage/backpack/duffelbag/med
diff --git a/code/modules/jobs/job_types/science.dm b/code/modules/jobs/job_types/science.dm
index 4eac15d9f1..7fc1dada77 100644
--- a/code/modules/jobs/job_types/science.dm
+++ b/code/modules/jobs/job_types/science.dm
@@ -1,25 +1,25 @@
-/*
-Research Director
-*/
-/datum/job/rd
- title = "Research Director"
- flag = RD_JF
- department_head = list("Captain")
- department_flag = MEDSCI
- head_announce = list("Science")
- faction = "Station"
- total_positions = 1
- spawn_positions = 1
- supervisors = "the captain"
- selection_color = "#ffddff"
- req_admin_notify = 1
- minimal_player_age = 7
+/*
+Research Director
+*/
+/datum/job/rd
+ title = "Research Director"
+ flag = RD_JF
+ department_head = list("Captain")
+ department_flag = MEDSCI
+ head_announce = list("Science")
+ faction = "Station"
+ total_positions = 1
+ spawn_positions = 1
+ supervisors = "the captain"
+ selection_color = "#ffddff"
+ req_admin_notify = 1
+ minimal_player_age = 7
exp_type_department = EXP_TYPE_SCIENCE
exp_requirements = 180
exp_type = EXP_TYPE_CREW
-
- outfit = /datum/outfit/job/rd
-
+
+ outfit = /datum/outfit/job/rd
+
access = list(ACCESS_RD, ACCESS_HEADS, ACCESS_TOX, ACCESS_GENETICS, ACCESS_MORGUE,
ACCESS_TOX_STORAGE, ACCESS_TELEPORTER, ACCESS_SEC_DOORS,
ACCESS_RESEARCH, ACCESS_ROBOTICS, ACCESS_XENOBIOLOGY, ACCESS_AI_UPLOAD,
@@ -30,101 +30,101 @@ Research Director
ACCESS_RESEARCH, ACCESS_ROBOTICS, ACCESS_XENOBIOLOGY, ACCESS_AI_UPLOAD,
ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_GATEWAY, ACCESS_MINERAL_STOREROOM,
ACCESS_TECH_STORAGE, ACCESS_MINISAT, ACCESS_MAINT_TUNNELS, ACCESS_NETWORK)
-
-/datum/outfit/job/rd
- name = "Research Director"
- jobtype = /datum/job/rd
-
- id = /obj/item/card/id/silver
- belt = /obj/item/device/pda/heads/rd
- ears = /obj/item/device/radio/headset/heads/rd
- uniform = /obj/item/clothing/under/rank/research_director
- shoes = /obj/item/clothing/shoes/sneakers/brown
- suit = /obj/item/clothing/suit/toggle/labcoat
- l_hand = /obj/item/clipboard
- l_pocket = /obj/item/device/laser_pointer
- accessory = /obj/item/clothing/accessory/pocketprotector/full
+
+/datum/outfit/job/rd
+ name = "Research Director"
+ jobtype = /datum/job/rd
+
+ id = /obj/item/card/id/silver
+ belt = /obj/item/device/pda/heads/rd
+ ears = /obj/item/device/radio/headset/heads/rd
+ uniform = /obj/item/clothing/under/rank/research_director
+ shoes = /obj/item/clothing/shoes/sneakers/brown
+ suit = /obj/item/clothing/suit/toggle/labcoat
+ l_hand = /obj/item/clipboard
+ l_pocket = /obj/item/device/laser_pointer
+ accessory = /obj/item/clothing/accessory/pocketprotector/full
backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/device/modular_computer/tablet/preset/advanced=1)
-
- backpack = /obj/item/storage/backpack/science
- satchel = /obj/item/storage/backpack/satchel/tox
-
-/datum/outfit/job/rd/rig
- name = "Research Director (Hardsuit)"
-
- l_hand = null
- mask = /obj/item/clothing/mask/breath
- suit = /obj/item/clothing/suit/space/hardsuit/rd
- suit_store = /obj/item/tank/internals/oxygen
- internals_slot = slot_s_store
-
-/*
-Scientist
-*/
-/datum/job/scientist
- title = "Scientist"
- flag = SCIENTIST
- department_head = list("Research Director")
- department_flag = MEDSCI
- faction = "Station"
- total_positions = 5
- spawn_positions = 3
- supervisors = "the research director"
- selection_color = "#ffeeff"
+
+ backpack = /obj/item/storage/backpack/science
+ satchel = /obj/item/storage/backpack/satchel/tox
+
+/datum/outfit/job/rd/rig
+ name = "Research Director (Hardsuit)"
+
+ l_hand = null
+ mask = /obj/item/clothing/mask/breath
+ suit = /obj/item/clothing/suit/space/hardsuit/rd
+ suit_store = /obj/item/tank/internals/oxygen
+ internals_slot = slot_s_store
+
+/*
+Scientist
+*/
+/datum/job/scientist
+ title = "Scientist"
+ flag = SCIENTIST
+ department_head = list("Research Director")
+ department_flag = MEDSCI
+ faction = "Station"
+ total_positions = 5
+ spawn_positions = 3
+ supervisors = "the research director"
+ selection_color = "#ffeeff"
exp_requirements = 60
exp_type = EXP_TYPE_CREW
-
- outfit = /datum/outfit/job/scientist
-
+
+ outfit = /datum/outfit/job/scientist
+
access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_MINERAL_STOREROOM, ACCESS_TECH_STORAGE, ACCESS_GENETICS)
minimal_access = list(ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_MINERAL_STOREROOM)
-
-/datum/outfit/job/scientist
- name = "Scientist"
- jobtype = /datum/job/scientist
-
- belt = /obj/item/device/pda/toxins
- ears = /obj/item/device/radio/headset/headset_sci
- uniform = /obj/item/clothing/under/rank/scientist
- shoes = /obj/item/clothing/shoes/sneakers/white
- suit = /obj/item/clothing/suit/toggle/labcoat/science
-
- backpack = /obj/item/storage/backpack/science
- satchel = /obj/item/storage/backpack/satchel/tox
- accessory = /obj/item/clothing/accessory/pocketprotector/full
-
-/*
-Roboticist
-*/
-/datum/job/roboticist
- title = "Roboticist"
- flag = ROBOTICIST
- department_head = list("Research Director")
- department_flag = MEDSCI
- faction = "Station"
- total_positions = 2
- spawn_positions = 2
- supervisors = "research director"
- selection_color = "#ffeeff"
+
+/datum/outfit/job/scientist
+ name = "Scientist"
+ jobtype = /datum/job/scientist
+
+ belt = /obj/item/device/pda/toxins
+ ears = /obj/item/device/radio/headset/headset_sci
+ uniform = /obj/item/clothing/under/rank/scientist
+ shoes = /obj/item/clothing/shoes/sneakers/white
+ suit = /obj/item/clothing/suit/toggle/labcoat/science
+
+ backpack = /obj/item/storage/backpack/science
+ satchel = /obj/item/storage/backpack/satchel/tox
+ accessory = /obj/item/clothing/accessory/pocketprotector/full
+
+/*
+Roboticist
+*/
+/datum/job/roboticist
+ title = "Roboticist"
+ flag = ROBOTICIST
+ department_head = list("Research Director")
+ department_flag = MEDSCI
+ faction = "Station"
+ total_positions = 2
+ spawn_positions = 2
+ supervisors = "research director"
+ selection_color = "#ffeeff"
exp_requirements = 60
exp_type = EXP_TYPE_CREW
-
- outfit = /datum/outfit/job/roboticist
-
+
+ outfit = /datum/outfit/job/roboticist
+
access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM, ACCESS_XENOBIOLOGY, ACCESS_GENETICS)
minimal_access = list(ACCESS_ROBOTICS, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM)
-
-/datum/outfit/job/roboticist
- name = "Roboticist"
- jobtype = /datum/job/roboticist
-
- belt = /obj/item/storage/belt/utility/full
- l_pocket = /obj/item/device/pda/roboticist
- ears = /obj/item/device/radio/headset/headset_sci
- uniform = /obj/item/clothing/under/rank/roboticist
- suit = /obj/item/clothing/suit/toggle/labcoat
-
- backpack = /obj/item/storage/backpack/science
- satchel = /obj/item/storage/backpack/satchel/tox
-
- pda_slot = slot_l_store
+
+/datum/outfit/job/roboticist
+ name = "Roboticist"
+ jobtype = /datum/job/roboticist
+
+ belt = /obj/item/storage/belt/utility/full
+ l_pocket = /obj/item/device/pda/roboticist
+ ears = /obj/item/device/radio/headset/headset_sci
+ uniform = /obj/item/clothing/under/rank/roboticist
+ suit = /obj/item/clothing/suit/toggle/labcoat
+
+ backpack = /obj/item/storage/backpack/science
+ satchel = /obj/item/storage/backpack/satchel/tox
+
+ pda_slot = slot_l_store
diff --git a/code/modules/jobs/job_types/silicon.dm b/code/modules/jobs/job_types/silicon.dm
index bc3b31b2bf..4a4893e93d 100644
--- a/code/modules/jobs/job_types/silicon.dm
+++ b/code/modules/jobs/job_types/silicon.dm
@@ -52,4 +52,4 @@ Cyborg
/datum/job/cyborg/after_spawn(mob/living/silicon/robot/R, mob/M)
if(CONFIG_GET(flag/rename_cyborg)) //name can't be set in robot/New without the client
- R.rename_self("cyborg", M.client)
+ R.rename_self("cyborg", M.client)
\ No newline at end of file
diff --git a/code/modules/keybindings/bindings_admin.dm b/code/modules/keybindings/bindings_admin.dm
new file mode 100644
index 0000000000..812bb95784
--- /dev/null
+++ b/code/modules/keybindings/bindings_admin.dm
@@ -0,0 +1,18 @@
+/datum/admins/key_down(_key, client/user)
+ switch(_key)
+ if("F5")
+ user.admin_ghost()
+ return
+ if("F6")
+ player_panel_new()
+ return
+ if("F7")
+ user.togglebuildmodeself()
+ return
+ if("F8")
+ if(user.keys_held["Ctrl"])
+ user.stealth()
+ else
+ user.invisimin()
+ return
+ ..()
diff --git a/code/modules/keybindings/bindings_atom.dm b/code/modules/keybindings/bindings_atom.dm
new file mode 100644
index 0000000000..7bc2ff98fe
--- /dev/null
+++ b/code/modules/keybindings/bindings_atom.dm
@@ -0,0 +1,18 @@
+// You might be wondering why this isn't client level. If focus is null, we don't want you to move.
+// Only way to do that is to tie the behavior into the focus's keyLoop().
+
+/atom/movable/keyLoop(client/user)
+ if(!user.keys_held["Ctrl"])
+ var/movement_dir = NONE
+ for(var/_key in user.keys_held)
+ movement_dir |= GLOB.movement_keys[_key]
+ if(user.next_move_dir_add)
+ movement_dir |= user.next_move_dir_add
+ if(user.next_move_dir_sub)
+ movement_dir &= ~user.next_move_dir_sub
+ // Sanity checks in case you hold left and right and up to make sure you only go up
+ if((movement_dir & NORTH) && (movement_dir & SOUTH))
+ movement_dir &= ~(NORTH|SOUTH)
+ if((movement_dir & EAST) && (movement_dir & WEST))
+ movement_dir &= ~(EAST|WEST)
+ user.Move(get_step(src, movement_dir), movement_dir)
\ No newline at end of file
diff --git a/code/modules/keybindings/bindings_carbon.dm b/code/modules/keybindings/bindings_carbon.dm
new file mode 100644
index 0000000000..d17f10e963
--- /dev/null
+++ b/code/modules/keybindings/bindings_carbon.dm
@@ -0,0 +1,18 @@
+/mob/living/carbon/key_down(_key, client/user)
+ switch(_key)
+ if("R", "Southwest") // Southwest is End
+ toggle_throw_mode()
+ return
+ if("1")
+ a_intent_change("help")
+ return
+ if("2")
+ a_intent_change("disarm")
+ return
+ if("3")
+ a_intent_change("grab")
+ return
+ if("4")
+ a_intent_change("harm")
+ return
+ return ..()
\ No newline at end of file
diff --git a/code/modules/keybindings/bindings_client.dm b/code/modules/keybindings/bindings_client.dm
new file mode 100644
index 0000000000..6bfaedf39d
--- /dev/null
+++ b/code/modules/keybindings/bindings_client.dm
@@ -0,0 +1,50 @@
+// Clients aren't datums so we have to define these procs indpendently.
+// These verbs are called for all key press and release events
+/client/verb/keyDown(_key as text)
+ set instant = TRUE
+ set hidden = TRUE
+
+ keys_held[_key] = world.time
+ var/movement = GLOB.movement_keys[_key]
+ if(!(next_move_dir_sub & movement))
+ next_move_dir_add |= movement
+
+ // Client-level keybindings are ones anyone should be able to do at any time
+ // Things like taking screenshots, hitting tab, and adminhelps.
+
+ switch(_key)
+ if("F1")
+ if(keys_held["Ctrl"] && keys_held["Shift"]) // Is this command ever used?
+ winset(src, null, "command=.options")
+ else
+ adminhelp()
+ if("F2") // Screenshot. Hold shift to choose a name and location to save in
+ winset(src, null, "command=.screenshot [!keys_held["shift"] ? "auto" : ""]")
+ if("F12") // Toggles minimal HUD
+ mob.button_pressed_F12()
+
+ if(holder)
+ holder.key_down(_key, src)
+ if(mob.focus)
+ mob.focus.key_down(_key, src)
+
+/client/verb/keyUp(_key as text)
+ set instant = TRUE
+ set hidden = TRUE
+
+ keys_held -= _key
+ var/movement = GLOB.movement_keys[_key]
+ if(!(next_move_dir_add & movement))
+ next_move_dir_sub |= movement
+
+ if(holder)
+ holder.key_up(_key, src)
+ if(mob.focus)
+ mob.focus.key_up(_key, src)
+
+// Called every game tick
+/client/keyLoop()
+ if(holder)
+ holder.keyLoop(src)
+ if(mob.focus)
+ mob.focus.keyLoop(src)
\ No newline at end of file
diff --git a/code/modules/keybindings/bindings_human.dm b/code/modules/keybindings/bindings_human.dm
new file mode 100644
index 0000000000..10d035305f
--- /dev/null
+++ b/code/modules/keybindings/bindings_human.dm
@@ -0,0 +1,6 @@
+/mob/living/carbon/human/key_down(_key, client/user)
+ switch(_key)
+ if("E")
+ quick_equip()
+ return
+ return ..()
\ No newline at end of file
diff --git a/code/modules/keybindings/bindings_living.dm b/code/modules/keybindings/bindings_living.dm
new file mode 100644
index 0000000000..241bc15b60
--- /dev/null
+++ b/code/modules/keybindings/bindings_living.dm
@@ -0,0 +1,7 @@
+/mob/living/key_down(_key, client/user)
+ switch(_key)
+ if("B")
+ resist()
+ return
+
+ return ..()
\ No newline at end of file
diff --git a/code/modules/keybindings/bindings_mob.dm b/code/modules/keybindings/bindings_mob.dm
new file mode 100644
index 0000000000..1d35694e5f
--- /dev/null
+++ b/code/modules/keybindings/bindings_mob.dm
@@ -0,0 +1,79 @@
+// Technically the client argument is unncessary here since that SHOULD be src.client but let's not assume things
+// All it takes is one badmin setting their focus to someone else's client to mess things up
+// Or we can have NPC's send actual keypresses and detect that by seeing no client
+
+/mob/key_down(_key, client/user)
+ switch(_key)
+ if("Delete", "H")
+ if(!pulling)
+ to_chat(src, "You are not pulling anything.")
+ else
+ stop_pulling()
+ return
+ if("Insert", "G")
+ a_intent_change(INTENT_HOTKEY_RIGHT)
+ return
+ if("F")
+ a_intent_change(INTENT_HOTKEY_LEFT)
+ return
+ if("X", "Northeast") // Northeast is Page-up
+ swap_hand()
+ return
+ if("Y", "Z", "Southeast") // Southeast is Page-down
+ mode() // attack_self(). No idea who came up with "mode()"
+ return
+ if("Q", "Northwest") // Northwest is Home
+ var/obj/item/I = get_active_held_item()
+ if(!I)
+ to_chat(src, "You have nothing to drop in your hand!")
+ else
+ dropItemToGround(I)
+ return
+ if("Alt")
+ toggle_move_intent()
+ return
+ //Bodypart selections
+ if("Numpad8")
+ user.body_toggle_head()
+ return
+ if("Numpad4")
+ user.body_r_arm()
+ return
+ if("Numpad5")
+ user.body_chest()
+ return
+ if("Numpad6")
+ user.body_l_arm()
+ return
+ if("Numpad1")
+ user.body_r_leg()
+ return
+ if("Numpad2")
+ user.body_groin()
+ return
+ if("Numpad3")
+ user.body_l_leg()
+ return
+
+ if(client.keys_held["Ctrl"])
+ switch(GLOB.movement_keys[_key])
+ if(NORTH)
+ northface()
+ return
+ if(SOUTH)
+ southface()
+ return
+ if(WEST)
+ westface()
+ return
+ if(EAST)
+ eastface()
+ return
+ return ..()
+
+/mob/key_up(_key, client/user)
+ switch(_key)
+ if("Alt")
+ toggle_move_intent()
+ return
+ return ..()
\ No newline at end of file
diff --git a/code/modules/keybindings/bindings_robot.dm b/code/modules/keybindings/bindings_robot.dm
new file mode 100644
index 0000000000..2354f33c9e
--- /dev/null
+++ b/code/modules/keybindings/bindings_robot.dm
@@ -0,0 +1,12 @@
+/mob/living/silicon/robot/key_down(_key, client/user)
+ switch(_key)
+ if("1", "2", "3")
+ toggle_module(text2num(_key))
+ return
+ if("4")
+ a_intent_change(INTENT_HOTKEY_LEFT)
+ return
+ if("Q")
+ uneq_active()
+ return
+ return ..()
\ No newline at end of file
diff --git a/code/modules/keybindings/focus.dm b/code/modules/keybindings/focus.dm
new file mode 100644
index 0000000000..9d3e44f059
--- /dev/null
+++ b/code/modules/keybindings/focus.dm
@@ -0,0 +1,20 @@
+/datum
+ var/list/focusers //Only initialized when needed. Contains a list of mobs focusing on this.
+
+/mob
+ var/datum/focus //What receives our keyboard inputs. src by default
+
+/mob/proc/set_focus(datum/new_focus)
+ if(focus == new_focus)
+ return
+
+ if(new_focus)
+ if(!new_focus.focusers) //Set up the new focus
+ new_focus.focusers = list()
+ new_focus.focusers += src
+
+ if(focus)
+ focus.focusers -= src //Tell the old focus we're done with it
+
+ focus = new_focus
+ reset_perspective(focus) //Maybe this should be done manually? You figure it out, reader
\ No newline at end of file
diff --git a/code/modules/keybindings/readme.md b/code/modules/keybindings/readme.md
new file mode 100644
index 0000000000..1170804436
--- /dev/null
+++ b/code/modules/keybindings/readme.md
@@ -0,0 +1,40 @@
+# In-code keypress handling system
+
+This whole system is heavily based off of forum_account's keyboard library.
+Thanks to forum_account for saving the day, the library can be found [here](http://www.byond.com/developer/Forum_account/Keyboard)!
+
+.dmf macros have some very serious shortcomings. For example, they do not allow reusing parts
+of one macro in another, so giving cyborgs their own shortcuts to swap active module couldn't
+inherit the movement that all mobs should have anyways. The webclient only supports one macro,
+so having more than one was problematic. Additionally each keybind has to call an actual
+verb, which meant a lot of hidden verbs that just call one other proc. Also our existing
+macro was really bad and tied unrelated behavior into `Northeast()`, `Southeast()`, `Northwest()`,
+and `Southwest()`.
+
+The basic premise of this system is to not screw with .dmf macro setup at all and handle
+pressing those keys in the code instead. We have every key call `client.keyDown()`
+or `client.keyUp()` with the pressed key as an argument. Certain keys get processed
+directly by the client because they should be doable at any time, then we call
+`keyDown()` or `keyUp()` on the client's holder and the client's mob's focus.
+By default `mob.focus` is the mob itself, but you can set it to any datum to give control of a
+client's keypresses to another object. This would be a good way to handle a menu or driving
+a mech. You can also set it to null to disregard input from a certain user.
+
+Movement is handled by having each client call `client.keyLoop()` every game tick.
+As above, this calls holder and `focus.keyLoop()`. `atom/movable/keyLoop()` handles movement
+Try to keep the calculations in this proc light. It runs every tick for every client after all!
+
+You can also tell which keys are being held down now. Each client a list of keys pressed called
+`keys_held`. Each entry is a key as a text string associated with the world.time when it was
+pressed.
+
+No client-set keybindings at this time, but it shouldn't be too hard if someone wants.
+
+Notes about certain keys
+`Tab` has client-sided behavior but acts normally
+`T`, `O`, and `M` move focus to the input when pressed. This fires the keyUp macro right away.
+`\` needs to be escaped in the dmf so any usage is `\\`
+
+You cannot `TICK_CHECK` or check `world.tick_usage` inside of procs called by key down and up
+events. They happen outside of a byond tick and have no meaning there. Key looping
+works correctly since it's part of a subsystem, not direct input.
\ No newline at end of file
diff --git a/code/modules/keybindings/setup.dm b/code/modules/keybindings/setup.dm
new file mode 100644
index 0000000000..bd7490abaa
--- /dev/null
+++ b/code/modules/keybindings/setup.dm
@@ -0,0 +1,62 @@
+/client
+ var/list/keys_held = list() // A list of any keys held currently
+ // These next two vars are to apply movement for keypresses and releases made while move delayed.
+ // Because discarding that input makes the game less responsive.
+ var/next_move_dir_add // On next move, add this dir to the move that would otherwise be done
+ var/next_move_dir_sub // On next move, subtract this dir from the move that would otherwise be done
+
+// Set a client's focus to an object and override these procs on that object to let it handle keypresses
+
+/datum/proc/key_down(key, client/user) // Called when a key is pressed down initially
+ return
+/datum/proc/key_up(key, client/user) // Called when a key is released
+ return
+/datum/proc/keyLoop(client/user) // Called once every frame
+ return
+
+// Keys used for movement
+GLOBAL_LIST_INIT(movement_keys, list(
+ "W" = NORTH, "A" = WEST, "S" = SOUTH, "D" = EAST, // WASD
+ "North" = NORTH, "West" = WEST, "South" = SOUTH, "East" = EAST, // Arrow keys & Numpad
+ ))
+
+/*
+A horrific battle against shitcode was fought here to find out some use details of winset
+Aparently you need to wrap the entire proc + args in quotes if you intend on using args
+But you don't need the quote wrappings to just call on a proc with no args
+ex. winset(src, "default-Any", "command=keyDown \[\[*\]\]") fail: command = keyDown
+ex. winset(src, "default-Any", "command=keyDown \"\[\[*\]\]\"") fail: same
+ex. winset(src, "default-T", "command=say") works fine
+ex. winset(src, "default-Any", "command=\"keyDown \[\[*\]\]\"") works fine
+Thanks for the useful errors lummox ~ninjanomnom
+*/
+GLOBAL_LIST_INIT(default_macros, list(
+ "Tab" = "\".winset \\\"input.focus=true?map.focus=true input.background-color=#F0F0F0:input.focus=true input.background-color=#D3B5B5\\\"\"",
+ "O" = "ooc",
+ "T" = "say",
+ "M" = "me",
+ "Back" = "\".winset \\\"input.text=\\\"\\\"\\\"\"", // This makes it so backspace can remove default inputs
+ "Any" = "\"KeyDown \[\[*\]\]\"",
+ "Any+UP" = "\"KeyUp \[\[*\]\]\"",
+ ))
+
+/client/proc/set_macros()
+ set waitfor = FALSE
+
+ winset(src, null, "reset=true")
+ winset(src, null, "mainwindow.macro=default")
+ var/list/default = params2list(winget(src, "default.*", "command"))
+ for(var/i in 1 to length(default))
+ var/id = default[i]
+ winset(src, id, "parent=none")
+
+ var/list/default_macros = GLOB.default_macros
+ for(var/i in 1 to length(default_macros))
+ var/input = default_macros[i]
+ var/output = default_macros[input]
+ winset(src, "default-[input]", "parent=default;name=[input];command=[output]")
+
+ if(prefs.hotkeys)
+ winset(src, null, "mapwindow.map.focus=true input.background-color=#e0e0e0")
+ else
+ winset(src, null, "input.focus=true input.background-color=#d3b5b5")
\ No newline at end of file
diff --git a/code/modules/language/codespeak.dm b/code/modules/language/codespeak.dm
index e8398c2b9f..2a140f27de 100644
--- a/code/modules/language/codespeak.dm
+++ b/code/modules/language/codespeak.dm
@@ -3,7 +3,7 @@
desc = "Syndicate operatives can use a series of codewords to convey complex information, while sounding like random concepts and drinks to anyone listening in."
key = "t"
default_priority = 0
- flags_1 = TONGUELESS_SPEECH | LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD
+ flags = TONGUELESS_SPEECH | LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD
icon_state = "codespeak"
/datum/language/codespeak/scramble(input)
diff --git a/code/modules/language/common.dm b/code/modules/language/common.dm
index 162fbf9226..c00ab328ec 100644
--- a/code/modules/language/common.dm
+++ b/code/modules/language/common.dm
@@ -5,7 +5,7 @@
speech_verb = "says"
whisper_verb = "whispers"
key = "0"
- flags_1 = TONGUELESS_SPEECH | LANGUAGE_HIDE_ICON_IF_UNDERSTOOD
+ flags = TONGUELESS_SPEECH | LANGUAGE_HIDE_ICON_IF_UNDERSTOOD
default_priority = 100
icon_state = "galcom"
diff --git a/code/modules/language/draconic.dm b/code/modules/language/draconic.dm
index a85c1c9747..aaa998c2c0 100644
--- a/code/modules/language/draconic.dm
+++ b/code/modules/language/draconic.dm
@@ -5,7 +5,7 @@
ask_verb = "hisses"
exclaim_verb = "roars"
key = "o"
- flags_1 = TONGUELESS_SPEECH
+ flags = TONGUELESS_SPEECH
space_chance = 40
syllables = list(
"za", "az", "ze", "ez", "zi", "iz", "zo", "oz", "zu", "uz", "zs", "sz",
diff --git a/code/modules/language/drone.dm b/code/modules/language/drone.dm
index 32659e263b..390e0027cf 100644
--- a/code/modules/language/drone.dm
+++ b/code/modules/language/drone.dm
@@ -1,12 +1,12 @@
/datum/language/drone
name = "Drone"
- desc = "A heavily encoded damage control coordination stream, with special flags_1 for hats."
+ desc = "A heavily encoded damage control coordination stream, with special flags for hats."
speech_verb = "chitters"
ask_verb = "chitters inquisitively"
exclaim_verb = "chitters loudly"
spans = list(SPAN_ROBOT)
key = "d"
- flags_1 = NO_STUTTER
+ flags = NO_STUTTER
syllables = list(".", "|")
// ...|..||.||||.|.||.|.|.|||.|||
space_chance = 0
diff --git a/code/modules/language/language.dm b/code/modules/language/language.dm
index 67881f7510..8b51429bd3 100644
--- a/code/modules/language/language.dm
+++ b/code/modules/language/language.dm
@@ -11,10 +11,10 @@
var/ask_verb = "asks" // Used when sentence ends in a ?
var/exclaim_verb = "exclaims" // Used when sentence ends in a !
var/whisper_verb = "whispers" // Optional. When not specified speech_verb + quietly/softly is used instead.
- var/list/signlang_verb = list("signs", "gestures") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags_1
+ var/list/signlang_verb = list("signs", "gestures") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags
var/key // Character used to speak in language
// If key is null, then the language isn't real or learnable.
- var/flags_1 // Various language flags_1.
+ var/flags // Various language flags.
var/list/syllables // Used when scrambling text for a non-speaker.
var/sentence_chance = 5 // Likelihood of making a new sentence after each syllable.
var/space_chance = 55 // Likelihood of getting a space in the random scramble string
@@ -28,9 +28,9 @@
/datum/language/proc/display_icon(atom/movable/hearer)
var/understands = hearer.has_language(src.type)
- if(flags_1 & LANGUAGE_HIDE_ICON_IF_UNDERSTOOD && understands)
+ if(flags & LANGUAGE_HIDE_ICON_IF_UNDERSTOOD && understands)
return FALSE
- if(flags_1 & LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD && !understands)
+ if(flags & LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD && !understands)
return FALSE
return TRUE
diff --git a/code/modules/language/machine.dm b/code/modules/language/machine.dm
index e5775040a2..4d88bcb416 100644
--- a/code/modules/language/machine.dm
+++ b/code/modules/language/machine.dm
@@ -6,7 +6,7 @@
exclaim_verb = "whistles loudly"
spans = list(SPAN_ROBOT)
key = "6"
- flags_1 = NO_STUTTER
+ flags = NO_STUTTER
syllables = list("beep","beep","beep","beep","beep","boop","boop","boop","bop","bop","dee","dee","doo","doo","hiss","hss","buzz","buzz","bzz","ksssh","keey","wurr","wahh","tzzz")
space_chance = 10
default_priority = 90
diff --git a/code/modules/language/swarmer.dm b/code/modules/language/swarmer.dm
index ea58775a08..e3b7826706 100644
--- a/code/modules/language/swarmer.dm
+++ b/code/modules/language/swarmer.dm
@@ -6,7 +6,7 @@
exclaim_verb = "tones loudly"
spans = list(SPAN_ROBOT)
key = "s"
- flags_1 = NO_STUTTER
+ flags = NO_STUTTER
space_chance = 100
sentence_chance = 0
default_priority = 60
diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm
index 711ac4f33a..b7673a9640 100644
--- a/code/modules/library/lib_items.dm
+++ b/code/modules/library/lib_items.dm
@@ -49,7 +49,7 @@
anchored = TRUE
for(var/obj/item/I in loc)
if(istype(I, /obj/item/book))
- I.loc = src
+ I.forceMove(src)
update_icon()
@@ -123,7 +123,7 @@
if(!user.get_active_held_item())
user.put_in_hands(choice)
else
- choice.loc = get_turf(src)
+ choice.forceMove(drop_location())
update_icon()
@@ -144,8 +144,8 @@
/obj/structure/bookcase/manuals/medical
name = "medical manuals bookcase"
-/obj/structure/bookcase/manuals/medical/New()
- ..()
+/obj/structure/bookcase/manuals/medical/Initialize()
+ . = ..()
new /obj/item/book/manual/medical_cloning(src)
update_icon()
@@ -153,8 +153,8 @@
/obj/structure/bookcase/manuals/engineering
name = "engineering manuals bookcase"
-/obj/structure/bookcase/manuals/engineering/New()
- ..()
+/obj/structure/bookcase/manuals/engineering/Initialize()
+ . = ..()
new /obj/item/book/manual/wiki/engineering_construction(src)
new /obj/item/book/manual/engineering_particle_accelerator(src)
new /obj/item/book/manual/wiki/engineering_hacking(src)
@@ -167,8 +167,8 @@
/obj/structure/bookcase/manuals/research_and_development
name = "\improper R&D manuals bookcase"
-/obj/structure/bookcase/manuals/research_and_development/New()
- ..()
+/obj/structure/bookcase/manuals/research_and_development/Initialize()
+ . = ..()
new /obj/item/book/manual/research_and_development(src)
update_icon()
@@ -289,7 +289,7 @@
user.put_in_hands(B)
return
else
- B.loc = src.loc
+ B.forceMove(drop_location())
qdel(src)
return
return
diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm
index 52077d2367..54a6caffef 100644
--- a/code/modules/library/lib_machines.dm
+++ b/code/modules/library/lib_machines.dm
@@ -541,7 +541,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
cache = null
if(href_list["eject"])
for(var/obj/item/book/B in contents)
- B.loc = src.loc
+ B.forceMove(drop_location())
src.add_fingerprint(usr)
src.updateUsrDialog()
return
@@ -589,4 +589,4 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums
B.icon_state = "book[rand(1,7)]"
qdel(P)
else
- P.loc = loc
+ P.forceMove(drop_location())
diff --git a/code/modules/mapping/dmm_suite.dm b/code/modules/mapping/dmm_suite.dm
index d272a10673..c4ceec33ee 100644
--- a/code/modules/mapping/dmm_suite.dm
+++ b/code/modules/mapping/dmm_suite.dm
@@ -27,7 +27,7 @@ dmm_suite{
write_map(), which accepts three arguments:
- A turf representing one corner of a three dimensional grid (Required).
- Another turf representing the other corner of the same grid (Required).
- - Any, or a combination, of several bit flags_1 (Optional, see documentation).
+ - Any, or a combination, of several bit flags (Optional, see documentation).
The order in which the turfs are supplied does not matter, the /dmm_writer will
determine the grid containing both, in much the same way as DM's block() function.
diff --git a/code/modules/mapping/ruins.dm b/code/modules/mapping/ruins.dm
index dfc602e725..89d9d07a14 100644
--- a/code/modules/mapping/ruins.dm
+++ b/code/modules/mapping/ruins.dm
@@ -1,3 +1,5 @@
+
+
/proc/seedRuins(list/z_levels = null, budget = 0, whitelist = /area/space, list/potentialRuins)
if(!z_levels || !z_levels.len)
WARNING("No Z levels provided - Not generating ruins")
diff --git a/code/modules/mining/abandoned_crates.dm b/code/modules/mining/abandoned_crates.dm
index 6c445c9ceb..5e7265f043 100644
--- a/code/modules/mining/abandoned_crates.dm
+++ b/code/modules/mining/abandoned_crates.dm
@@ -11,8 +11,8 @@
var/codelen = 4
tamperproof = 90
-/obj/structure/closet/crate/secure/loot/New()
- ..()
+/obj/structure/closet/crate/secure/loot/Initialize()
+ . = ..()
var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
code = ""
for(var/i = 0, i < codelen, i++)
diff --git a/code/modules/mining/aux_base.dm b/code/modules/mining/aux_base.dm
index 6b364e63e7..a434a41873 100644
--- a/code/modules/mining/aux_base.dm
+++ b/code/modules/mining/aux_base.dm
@@ -351,4 +351,4 @@ obj/docking_port/stationary/public_mining_dock
#undef BAD_ZLEVEL
#undef BAD_AREA
#undef BAD_COORDS
-#undef ZONE_SET
+#undef ZONE_SET
\ No newline at end of file
diff --git a/code/modules/mining/equipment/explorer_gear.dm b/code/modules/mining/equipment/explorer_gear.dm
index f2cdefa9a4..729665034e 100644
--- a/code/modules/mining/equipment/explorer_gear.dm
+++ b/code/modules/mining/equipment/explorer_gear.dm
@@ -43,8 +43,8 @@
..()
w_class = mask_adjusted ? WEIGHT_CLASS_NORMAL : WEIGHT_CLASS_SMALL
-/obj/item/clothing/mask/gas/explorer/folded/New()
- ..()
+/obj/item/clothing/mask/gas/explorer/folded/Initialize()
+ . = ..()
adjustmask()
/obj/item/clothing/suit/space/hostile_environment
diff --git a/code/modules/mining/equipment/mineral_scanner.dm b/code/modules/mining/equipment/mineral_scanner.dm
index 52160303cc..ec3dda28a0 100644
--- a/code/modules/mining/equipment/mineral_scanner.dm
+++ b/code/modules/mining/equipment/mineral_scanner.dm
@@ -71,7 +71,7 @@
plane = FULLSCREEN_PLANE
layer = FLASH_LAYER
icon = 'icons/effects/ore_visuals.dmi'
- appearance_flags = 0 //to avoid having TILE_BOUND in the flags_1, so that the 480x480 icon states let you see it no matter where you are
+ appearance_flags = 0 //to avoid having TILE_BOUND in the flags, so that the 480x480 icon states let you see it no matter where you are
duration = 35
pixel_x = -224
pixel_y = -224
diff --git a/code/modules/mining/laborcamp/laborshuttle.dm b/code/modules/mining/laborcamp/laborshuttle.dm
index f2c782c279..60983aa25a 100644
--- a/code/modules/mining/laborcamp/laborshuttle.dm
+++ b/code/modules/mining/laborcamp/laborshuttle.dm
@@ -1,27 +1,27 @@
-/obj/machinery/computer/shuttle/labor
- name = "labor shuttle console"
- desc = "Used to call and send the labor camp shuttle."
- circuit = /obj/item/circuitboard/computer/labor_shuttle
- shuttleId = "laborcamp"
- possible_destinations = "laborcamp_home;laborcamp_away"
+/obj/machinery/computer/shuttle/labor
+ name = "labor shuttle console"
+ desc = "Used to call and send the labor camp shuttle."
+ circuit = /obj/item/circuitboard/computer/labor_shuttle
+ shuttleId = "laborcamp"
+ possible_destinations = "laborcamp_home;laborcamp_away"
req_access = list(ACCESS_BRIG)
-
-
-/obj/machinery/computer/shuttle/labor/one_way
- name = "prisoner shuttle console"
- desc = "A one-way shuttle console, used to summon the shuttle to the labor camp."
- possible_destinations = "laborcamp_away"
- circuit = /obj/item/circuitboard/computer/labor_shuttle/one_way
- req_access = list( )
-
-/obj/machinery/computer/shuttle/labor/one_way/Topic(href, href_list)
- if(href_list["move"])
- var/obj/docking_port/mobile/M = SSshuttle.getShuttle("laborcamp")
- if(!M)
- to_chat(usr, "Cannot locate shuttle!")
- return 0
- var/obj/docking_port/stationary/S = M.get_docked()
- if(S && S.name == "laborcamp_away")
- to_chat(usr, "Shuttle is already at the outpost!")
- return 0
+
+
+/obj/machinery/computer/shuttle/labor/one_way
+ name = "prisoner shuttle console"
+ desc = "A one-way shuttle console, used to summon the shuttle to the labor camp."
+ possible_destinations = "laborcamp_away"
+ circuit = /obj/item/circuitboard/computer/labor_shuttle/one_way
+ req_access = list( )
+
+/obj/machinery/computer/shuttle/labor/one_way/Topic(href, href_list)
+ if(href_list["move"])
+ var/obj/docking_port/mobile/M = SSshuttle.getShuttle("laborcamp")
+ if(!M)
+ to_chat(usr, "Cannot locate shuttle!")
+ return 0
+ var/obj/docking_port/stationary/S = M.get_docked()
+ if(S && S.name == "laborcamp_away")
+ to_chat(usr, "Shuttle is already at the outpost!")
+ return 0
..()
\ No newline at end of file
diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm
index 12c9bfb30e..7b38bc4cb5 100644
--- a/code/modules/mining/laborcamp/laborstacker.dm
+++ b/code/modules/mining/laborcamp/laborstacker.dm
@@ -102,8 +102,8 @@
to_chat(usr, "No permission to dock could be granted.")
else
if(!emagged)
- Radio.set_frequency(GLOB.SEC_FREQ)
- Radio.talk_into(src, "[inserted_id.registered_name] has returned to the station. Minerals and Prisoner ID card ready for retrieval.", GLOB.SEC_FREQ, get_spans(), get_default_language())
+ Radio.set_frequency(FREQ_SECURITY)
+ Radio.talk_into(src, "[inserted_id.registered_name] has returned to the station. Minerals and Prisoner ID card ready for retrieval.", FREQ_SECURITY, get_spans(), get_default_language())
to_chat(usr, "Shuttle received message and will be sent shortly.")
/obj/machinery/mineral/labor_claim_console/proc/check_auth()
diff --git a/code/modules/mining/lavaland/ash_flora.dm b/code/modules/mining/lavaland/ash_flora.dm
index 6ecdc91635..340ba16373 100644
--- a/code/modules/mining/lavaland/ash_flora.dm
+++ b/code/modules/mining/lavaland/ash_flora.dm
@@ -20,8 +20,8 @@
var/regrowth_time_low = 4800
var/regrowth_time_high = 8400
-/obj/structure/flora/ash/New()
- ..()
+/obj/structure/flora/ash/Initialize()
+ . = ..()
base_icon = "[icon_state][rand(1, 4)]"
icon_state = base_icon
if(prob(15))
@@ -153,8 +153,8 @@
max_integrity = 100
seed = /obj/item/seeds/lavaland/polypore
-/obj/item/reagent_containers/food/snacks/grown/ash_flora/New()
- ..()
+/obj/item/reagent_containers/food/snacks/grown/ash_flora/Initialize()
+ . = ..()
pixel_x = rand(-4, 4)
pixel_y = rand(-4, 4)
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 7fdecaaeb6..665654088f 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -107,6 +107,7 @@
/datum/design/unique_modkit
category = list("Mining Designs", "Cyborg Upgrade Modules") //can't be normally obtained
build_type = PROTOLATHE | MECHFAB
+ departmental_flags = DEPARTMENTAL_FLAG_CARGO
/datum/design/unique_modkit/offensive_turf_aoe
name = "Kinetic Accelerator Offensive Mining Explosion Mod"
@@ -172,7 +173,7 @@
to_chat(M, "Your vision returns to normal.")
wisp.stop_orbit()
- wisp.loc = src
+ wisp.forceMove(src)
icon_state = "lantern-blue"
SSblackbox.record_feedback("tally", "wisp_lantern", 1, "Returned")
@@ -412,7 +413,7 @@
/obj/item/device/shared_storage/attackby(obj/item/W, mob/user, params)
if(bag)
- bag.loc = user
+ bag.forceMove(user)
bag.attackby(W, user, params)
@@ -421,7 +422,7 @@
return
if(loc == user && user.back && user.back == src)
if(bag)
- bag.loc = user
+ bag.forceMove(user)
bag.attack_hand(user)
else
..()
diff --git a/code/modules/mining/lavaland/ruins/gym.dm b/code/modules/mining/lavaland/ruins/gym.dm
index 2eb30dc711..efda0f9c8f 100644
--- a/code/modules/mining/lavaland/ruins/gym.dm
+++ b/code/modules/mining/lavaland/ruins/gym.dm
@@ -29,7 +29,7 @@
icon_state = "fitnesslifter2"
user.setDir(SOUTH)
user.Stun(80)
- user.loc = src.loc
+ user.forceMove(src.loc)
var/bragmessage = pick("pushing it to the limit","going into overdrive","burning with determination","rising up to the challenge", "getting strong now","getting ripped")
user.visible_message("[user] is [bragmessage]!")
var/lifts = 0
@@ -67,7 +67,7 @@
icon_state = "fitnessweight-c"
user.setDir(SOUTH)
user.Stun(80)
- user.loc = src.loc
+ user.forceMove(src.loc)
var/mutable_appearance/swole_overlay = mutable_appearance(icon, "fitnessweight-w", WALL_OBJ_LAYER)
add_overlay(swole_overlay)
var/bragmessage = pick("pushing it to the limit","going into overdrive","burning with determination","rising up to the challenge", "getting strong now","getting ripped")
@@ -93,4 +93,4 @@
var/finishmessage = pick("You feel stronger!","You feel like you can take on the world!","You feel robust!","You feel indestructible!")
icon_state = "fitnessweight"
cut_overlay(swole_overlay)
- to_chat(user, "[finishmessage]")
\ No newline at end of file
+ to_chat(user, "[finishmessage]")
diff --git a/code/modules/mining/machine_stacking.dm b/code/modules/mining/machine_stacking.dm
index 3c7e736105..44f13d0a4f 100644
--- a/code/modules/mining/machine_stacking.dm
+++ b/code/modules/mining/machine_stacking.dm
@@ -88,7 +88,7 @@
stack_list[inp.type] = s
var/obj/item/stack/sheet/storage = stack_list[inp.type]
storage.amount += inp.amount //Stack the sheets
- inp.loc = null //Let the old sheet garbage collect
+ qdel(inp) //Let the old sheet garbage collect
while(storage.amount > stack_amt) //Get rid of excessive stackage
var/obj/item/stack/sheet/out = new inp.type()
out.amount = stack_amt
diff --git a/code/modules/mining/machine_unloading.dm b/code/modules/mining/machine_unloading.dm
index 6896a1a805..c22ba5d757 100644
--- a/code/modules/mining/machine_unloading.dm
+++ b/code/modules/mining/machine_unloading.dm
@@ -29,4 +29,4 @@
limit++
if (limit>=10)
return
- CHECK_TICK
+ CHECK_TICK
\ No newline at end of file
diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm
index 1e298604eb..c872756872 100644
--- a/code/modules/mining/machine_vending.dm
+++ b/code/modules/mining/machine_vending.dm
@@ -276,8 +276,8 @@
name = "mining conscription kit"
desc = "A kit containing everything a crewmember needs to support a shaft miner in the field."
-/obj/item/storage/backpack/duffelbag/mining_conscript/New()
- ..()
+/obj/item/storage/backpack/duffelbag/mining_conscript/Initialize()
+ . = ..()
new /obj/item/pickaxe/mini(src)
new /obj/item/clothing/glasses/meson(src)
new /obj/item/device/t_scanner/adv_mining_scanner/lesser(src)
diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm
index 8d36922bdf..8d3f62f18d 100644
--- a/code/modules/mining/mine_items.dm
+++ b/code/modules/mining/mine_items.dm
@@ -8,8 +8,8 @@
var/set_luminosity = 8
var/set_cap = 0
-/obj/effect/light_emitter/New()
- ..()
+/obj/effect/light_emitter/Initialize()
+ . = ..()
set_light(set_luminosity, set_cap)
/obj/effect/light_emitter/singularity_pull()
@@ -73,7 +73,6 @@
possible_destinations = "mining_home;mining_away;landing_zone_dock;mining_public"
no_destination_swap = 1
var/global/list/dumb_rev_heads = list()
- req_access = list(ACCESS_MINING) // should slow the ashwalkers down.
/obj/machinery/computer/shuttle/mining/attack_hand(mob/user)
if((user.z in GLOB.station_z_levels) && user.mind && is_head_revolutionary(user) && !(user.mind in dumb_rev_heads))
@@ -87,4 +86,4 @@
/obj/structure/closet/crate/miningcar
desc = "A mining car. This one doesn't work on rails, but has to be dragged."
name = "Mining car (not for rails)"
- icon_state = "miningcar"
\ No newline at end of file
+ icon_state = "miningcar"
diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm
index f13079861a..befaef31a2 100644
--- a/code/modules/mining/money_bag.dm
+++ b/code/modules/mining/money_bag.dm
@@ -14,8 +14,8 @@
can_hold = list(/obj/item/coin, /obj/item/stack/spacecash)
-/obj/item/storage/bag/money/vault/New()
- ..()
+/obj/item/storage/bag/money/vault/Initialize()
+ . = ..()
new /obj/item/coin/silver(src)
new /obj/item/coin/silver(src)
new /obj/item/coin/silver(src)
diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm
index e058782be1..9a95bc9a4a 100644
--- a/code/modules/mob/camera/camera.dm
+++ b/code/modules/mob/camera/camera.dm
@@ -1,15 +1,18 @@
-// Camera mob, used by AI camera and blob.
-
-/mob/camera
- name = "camera mob"
+// Camera mob, used by AI camera and blob.
+
+/mob/camera
+ name = "camera mob"
density = FALSE
anchored = TRUE
- status_flags = GODMODE // You can't damage it.
+ status_flags = GODMODE // You can't damage it.
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
- see_in_dark = 7
- invisibility = INVISIBILITY_ABSTRACT // No one can see us
- sight = SEE_SELF
- move_on_shuttle = 0
-
-/mob/camera/experience_pressure_difference()
- return
+ see_in_dark = 7
+ invisibility = INVISIBILITY_ABSTRACT // No one can see us
+ sight = SEE_SELF
+ move_on_shuttle = 0
+
+/mob/camera/experience_pressure_difference()
+ return
+
+/mob/camera/forceMove(atom/destination)
+ loc = destination
diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm
index 689ef552d9..59e8911659 100644
--- a/code/modules/mob/dead/dead.dm
+++ b/code/modules/mob/dead/dead.dm
@@ -2,6 +2,9 @@
INITIALIZE_IMMEDIATE(/mob/dead)
+/mob/dead
+ sight = SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
+
/mob/dead/Initialize()
if(initialized)
stack_trace("Warning: [src]([type]) initialized multiple times!")
@@ -11,8 +14,9 @@ INITIALIZE_IMMEDIATE(/mob/dead)
prepare_huds()
- if(CONFIG_GET(string/cross_server_address))
+ if(length(CONFIG_GET(keyed_string_list/cross_server)))
verbs += /mob/dead/proc/server_hop
+ set_focus(src)
return INITIALIZE_HINT_NORMAL
/mob/dead/dust() //ghosts can't be vaporised.
@@ -24,6 +28,9 @@ INITIALIZE_IMMEDIATE(/mob/dead)
/mob/dead/ConveyorMove() //lol
return
+/mob/dead/forceMove(atom/destination)
+ loc = destination
+
/mob/dead/Stat()
..()
@@ -42,26 +49,46 @@ INITIALIZE_IMMEDIATE(/mob/dead)
else
stat(null, "Time To Start: SOON")
+ stat(null, "Players: [SSticker.totalPlayers]")
+ if(client.holder)
+ stat(null, "Players Ready: [SSticker.totalPlayersReady]")
+
/mob/dead/proc/server_hop()
set category = "OOC"
set name = "Server Hop!"
set desc= "Jump to the other server"
if(notransform)
return
- var/csa = CONFIG_GET(string/cross_server_address)
- if(csa)
- verbs -= /mob/dead/proc/server_hop
- to_chat(src, "Server Hop has been disabled.")
+ var/list/csa = CONFIG_GET(keyed_string_list/cross_server)
+ var/pick
+ switch(csa.len)
+ if(0)
+ verbs -= /mob/dead/proc/server_hop
+ to_chat(src, "Server Hop has been disabled.")
+ if(1)
+ pick = csa[0]
+ else
+ pick = input(src, "Pick a server to jump to", "Server Hop") as null|anything in csa
+
+ if(!pick)
return
- if (alert(src, "Jump to server running at [csa]?", "Server Hop", "Yes", "No") != "Yes")
- return 0
- if (client && csa)
- to_chat(src, "Sending you to [csa].")
- new /obj/screen/splash(client)
- notransform = TRUE
- sleep(29) //let the animation play
- notransform = FALSE
- winset(src, null, "command=.options") //other wise the user never knows if byond is downloading resources
- client << link(csa + "?server_hop=[key]")
- else
- to_chat(src, "There is no other server configured!")
+
+ var/addr = csa[pick]
+
+ if(alert(src, "Jump to server [pick] ([addr])?", "Server Hop", "Yes", "No") != "Yes")
+ return
+
+ var/client/C = client
+ to_chat(C, "Sending you to [pick].")
+ new /obj/screen/splash(C)
+
+ notransform = TRUE
+ sleep(29) //let the animation play
+ notransform = FALSE
+
+ if(!C)
+ return
+
+ winset(src, null, "command=.options") //other wise the user never knows if byond is downloading resources
+
+ C << link("[addr]?server_hop=[key]")
diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm
index 458a54aa48..072c2bce8a 100644
--- a/code/modules/mob/dead/new_player/new_player.dm
+++ b/code/modules/mob/dead/new_player/new_player.dm
@@ -21,9 +21,9 @@
S.Fade(TRUE)
if(length(GLOB.newplayer_start))
- loc = pick(GLOB.newplayer_start)
+ forceMove(pick(GLOB.newplayer_start))
else
- loc = locate(1,1,1)
+ forceMove(locate(1,1,1))
ComponentInitialize()
@@ -73,26 +73,6 @@
popup.open(0)
return
-/mob/dead/new_player/Stat()
- ..()
-
- if(statpanel("Lobby"))
- stat("Game Mode:", (SSticker.hide_mode) ? "Secret" : "[GLOB.master_mode]")
- stat("Map:", SSmapping.config.map_name)
-
- if(SSticker.current_state == GAME_STATE_PREGAME)
- var/time_remaining = SSticker.GetTimeLeft()
- if(time_remaining > 0)
- stat("Time To Start:", "[round(time_remaining/10)]s")
- else if(time_remaining == -10)
- stat("Time To Start:", "DELAYED")
- else
- stat("Time To Start:", "SOON")
-
- stat("Players:", "[SSticker.totalPlayers]")
- if(client.holder)
- stat("Players Ready:", "[SSticker.totalPlayersReady]")
-
/mob/dead/new_player/Topic(href, href_list[])
if(src != usr)
@@ -282,7 +262,7 @@
var/obj/effect/landmark/observer_start/O = locate(/obj/effect/landmark/observer_start) in GLOB.landmarks_list
to_chat(src, "Now teleporting.")
if (O)
- observer.loc = O.loc
+ observer.forceMove(O.loc)
else
to_chat(src, "Teleporting failed. Ahelp an admin please")
stack_trace("There's no freaking observer landmark available on this map or you're making observers before the map is initialised")
@@ -317,15 +297,13 @@
return 0
if(job.required_playtime_remaining(client))
return 0
- if(CONFIG_GET(flag/enforce_human_authority) && !client.prefs.pref_species.qualifies_for_rank(rank, client.prefs.features))
- return 0
return 1
/mob/dead/new_player/proc/AttemptLateSpawn(rank)
if(!IsJobAvailable(rank))
alert(src, "[rank] is not available. Please try another.")
- return 0
+ return FALSE
if(SSticker.late_join_disabled)
alert(src, "An administrator has disabled late join spawning.")
diff --git a/code/modules/mob/dead/new_player/preferences_setup.dm b/code/modules/mob/dead/new_player/preferences_setup.dm
index f362f09a65..22d9fa3d9c 100644
--- a/code/modules/mob/dead/new_player/preferences_setup.dm
+++ b/code/modules/mob/dead/new_player/preferences_setup.dm
@@ -1,4 +1,5 @@
-//The mob should have a gender you want before running this proc. Will run fine without H
+
+ //The mob should have a gender you want before running this proc. Will run fine without H
/datum/preferences/proc/random_character(gender_override)
if(gender_override)
gender = gender_override
@@ -19,7 +20,7 @@
features = random_features()
age = rand(AGE_MIN,AGE_MAX)
-/datum/preferences/proc/update_preview_icon(nude = 0)
+/datum/preferences/proc/update_preview_icon()
// Silicons only need a very basic preview since there is no customization for them.
if(job_engsec_high)
switch(job_engsec_high)
@@ -56,7 +57,7 @@
previewJob = job
break
- if(previewJob && !nude)
+ if(previewJob)
mannequin.job = previewJob.title
previewJob.equip(mannequin, TRUE)
COMPILE_OVERLAYS(mannequin)
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index d19f3d4bf8..343f82b6f1 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -13,7 +13,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
density = FALSE
canmove = 0
anchored = TRUE // don't get pushed around
- sight = SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
see_invisible = SEE_INVISIBLE_OBSERVER
see_in_dark = 100
invisibility = INVISIBILITY_OBSERVER
@@ -109,7 +108,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
else
T = locate(round(world.maxx/2), round(world.maxy/2), ZLEVEL_STATION_PRIMARY) //middle of the station
- loc = T
+ forceMove(T)
if(!name) //To prevent nameless ghosts
name = random_unique_name(gender)
@@ -136,13 +135,13 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
/mob/dead/observer/narsie_act()
var/old_color = color
color = "#960000"
- animate(src, color = old_color, time = 10, flags_1 = ANIMATION_PARALLEL)
+ animate(src, color = old_color, time = 10, flags = ANIMATION_PARALLEL)
addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 10)
/mob/dead/observer/ratvar_act()
var/old_color = color
color = "#FAE48C"
- animate(src, color = old_color, time = 10, flags_1 = ANIMATION_PARALLEL)
+ animate(src, color = old_color, time = 10, flags = ANIMATION_PARALLEL)
addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 10)
/mob/dead/observer/Destroy()
@@ -288,10 +287,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/oldloc = loc
if(NewLoc)
- loc = NewLoc
+ forceMove(NewLoc)
update_parallax_contents()
else
- loc = get_turf(src) //Get out of closets and such as a ghost
+ forceMove(get_turf(src)) //Get out of closets and such as a ghost
if((direct & NORTH) && y < world.maxy)
y++
else if((direct & SOUTH) && y > 1)
@@ -371,7 +370,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(!L || !L.len)
to_chat(usr, "No area available.")
- usr.loc = pick(L)
+ usr.forceMove(pick(L))
update_parallax_contents()
/mob/dead/observer/verb/follow()
@@ -445,7 +444,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/turf/T = get_turf(M) //Turf of the destination mob
if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination.
- A.loc = T
+ A.forceMove(T)
A.update_parallax_contents()
else
to_chat(A, "This mob is not located in the game world.")
@@ -767,8 +766,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
//Istype so we filter out points of interest that are not mobs
if(client && mob_eye && istype(mob_eye))
client.eye = mob_eye
- client.screen = list()
if(mob_eye.hud_used)
+ client.screen = list()
LAZYINITLIST(mob_eye.observers)
mob_eye.observers |= src
mob_eye.hud_used.show_hud(mob_eye.hud_used.hud_version, src)
diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm
index ad64c53fc7..435005baf6 100644
--- a/code/modules/mob/dead/observer/say.dm
+++ b/code/modules/mob/dead/observer/say.dm
@@ -1,25 +1,25 @@
-/mob/dead/observer/say(message)
- message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
-
- if (!message)
- return
-
+/mob/dead/observer/say(message)
+ message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
+
+ if (!message)
+ return
+
log_talk(src,"Ghost/[src.key] : [message]", LOGSAY)
-
- . = src.say_dead(message)
-
-/mob/dead/observer/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
- var/atom/movable/to_follow = speaker
- if(radio_freq)
- var/atom/movable/virtualspeaker/V = speaker
-
- if(isAI(V.source))
- var/mob/living/silicon/ai/S = V.source
- to_follow = S.eyeobj
- else
- to_follow = V.source
- var/link = FOLLOW_LINK(src, to_follow)
- // Recompose the message, because it's scrambled by default
- message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
- to_chat(src, "[link] [message]")
-
+
+ . = src.say_dead(message)
+
+/mob/dead/observer/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
+ var/atom/movable/to_follow = speaker
+ if(radio_freq)
+ var/atom/movable/virtualspeaker/V = speaker
+
+ if(isAI(V.source))
+ var/mob/living/silicon/ai/S = V.source
+ to_follow = S.eyeobj
+ else
+ to_follow = V.source
+ var/link = FOLLOW_LINK(src, to_follow)
+ // Recompose the message, because it's scrambled by default
+ message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
+ to_chat(src, "[link] [message]")
+
diff --git a/code/modules/mob/living/brain/MMI.dm b/code/modules/mob/living/brain/MMI.dm
index e4d49d7b70..e090592ba3 100644
--- a/code/modules/mob/living/brain/MMI.dm
+++ b/code/modules/mob/living/brain/MMI.dm
@@ -57,7 +57,7 @@
brainmob = newbrain.brainmob
newbrain.brainmob = null
- brainmob.loc = src
+ brainmob.forceMove(src)
brainmob.container = src
if(!newbrain.damaged_brain) // the brain organ hasn't been beaten to death.
brainmob.stat = CONSCIOUS //we manually revive the brain mob
@@ -90,7 +90,7 @@
/obj/item/device/mmi/proc/eject_brain(mob/user)
brainmob.container = null //Reset brainmob mmi var.
- brainmob.loc = brain //Throw mob into brain.
+ brainmob.forceMove(brain) //Throw mob into brain.
brainmob.stat = DEAD
brainmob.emp_damage = 0
brainmob.reset_perspective() //so the brainmob follows the brain organ instead of the mmi. And to update our vision
@@ -120,7 +120,7 @@
if(ishuman(L))
var/mob/living/carbon/human/H = L
var/obj/item/organ/brain/newbrain = H.getorgan(/obj/item/organ/brain)
- newbrain.loc = src
+ newbrain.forceMove(src)
brain = newbrain
else if(!brain)
brain = new(src)
diff --git a/code/modules/mob/living/brain/posibrain.dm b/code/modules/mob/living/brain/posibrain.dm
index ef704ef136..33a274c762 100644
--- a/code/modules/mob/living/brain/posibrain.dm
+++ b/code/modules/mob/living/brain/posibrain.dm
@@ -157,7 +157,7 @@ GLOBAL_VAR(posibrain_notify_cooldown)
new_name = pick(possible_names)
brainmob.name = "[new_name]-[rand(100, 999)]"
brainmob.real_name = brainmob.name
- brainmob.loc = src
+ brainmob.forceMove(src)
brainmob.container = src
if(autoping)
ping_ghosts("created", TRUE)
diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm
index b0f76df80d..b55abb11f0 100644
--- a/code/modules/mob/living/carbon/alien/alien_defense.dm
+++ b/code/modules/mob/living/carbon/alien/alien_defense.dm
@@ -1,126 +1,126 @@
-
-/mob/living/carbon/alien/get_eye_protection()
- return ..() + 2 //potential cyber implants + natural eye protection
-
-/mob/living/carbon/alien/get_ear_protection()
- return 2 //no ears
-
-/mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush)
+
+/mob/living/carbon/alien/get_eye_protection()
+ return ..() + 2 //potential cyber implants + natural eye protection
+
+/mob/living/carbon/alien/get_ear_protection()
+ return 2 //no ears
+
+/mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush)
..(AM, skipcatch = TRUE, hitpush = FALSE)
-
-
-/*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other.
-As such, they can either help or harm other aliens. Help works like the human help command while harm is a simple nibble.
-In all, this is a lot like the monkey code. /N
-*/
-/mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/M)
- if(isturf(loc) && istype(loc.loc, /area/start))
- to_chat(M, "No attacking people at spawn, you jackass.")
- return
-
- switch(M.a_intent)
-
- if ("help")
- resting = 0
- AdjustStun(-60)
- AdjustKnockdown(-60)
- AdjustUnconscious(-60)
- AdjustSleeping(-100)
- visible_message("[M.name] nuzzles [src] trying to wake [p_them()] up!")
-
- if ("grab")
- grabbedby(M)
-
- else
- if(health > 0)
- M.do_attack_animation(src, ATTACK_EFFECT_BITE)
- playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
- visible_message("[M.name] bites [src]!", \
- "[M.name] bites [src]!", null, COMBAT_MESSAGE_RANGE)
- adjustBruteLoss(1)
- add_logs(M, src, "attacked")
- updatehealth()
- else
- to_chat(M, "[name] is too injured for that.")
-
-
-/mob/living/carbon/alien/attack_larva(mob/living/carbon/alien/larva/L)
- return attack_alien(L)
-
-
-/mob/living/carbon/alien/attack_hand(mob/living/carbon/human/M)
- if(..()) //to allow surgery to return properly.
- return 0
-
- switch(M.a_intent)
- if("help")
- help_shake_act(M)
- if("grab")
- grabbedby(M)
- if ("harm")
- M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
- return 1
- if("disarm")
- M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
- return 1
- return 0
-
-
-/mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M)
- if(..())
- if (stat != DEAD)
- var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
- apply_damage(rand(1, 3), BRUTE, affecting)
-
-
-/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
- . = ..()
- if(.)
- var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
- switch(M.melee_damage_type)
- if(BRUTE)
- adjustBruteLoss(damage)
- if(BURN)
- adjustFireLoss(damage)
- if(TOX)
- adjustToxLoss(damage)
- if(OXY)
- adjustOxyLoss(damage)
- if(CLONE)
- adjustCloneLoss(damage)
- if(STAMINA)
- adjustStaminaLoss(damage)
-
-/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M)
- if(..()) //successful slime attack
- var/damage = rand(5, 35)
- if(M.is_adult)
- damage = rand(10, 40)
- adjustBruteLoss(damage)
- add_logs(M, src, "attacked")
- updatehealth()
-
-/mob/living/carbon/alien/ex_act(severity, target, origin)
- if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
- return
- ..()
- switch (severity)
- if (1)
- gib()
- return
-
- if (2)
- take_overall_damage(60, 60)
- adjustEarDamage(30,120)
-
- if(3)
- take_overall_damage(30,0)
- if(prob(50))
- Unconscious(20)
- adjustEarDamage(15,60)
-
-/mob/living/carbon/alien/soundbang_act(intensity = 1, stun_pwr = 20, damage_pwr = 5, deafen_pwr = 15)
- return 0
-
-/mob/living/carbon/alien/acid_act(acidpwr, acid_volume)
- return 0//aliens are immune to acid.
+
+
+/*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other.
+As such, they can either help or harm other aliens. Help works like the human help command while harm is a simple nibble.
+In all, this is a lot like the monkey code. /N
+*/
+/mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/M)
+ if(isturf(loc) && istype(loc.loc, /area/start))
+ to_chat(M, "No attacking people at spawn, you jackass.")
+ return
+
+ switch(M.a_intent)
+
+ if ("help")
+ resting = 0
+ AdjustStun(-60)
+ AdjustKnockdown(-60)
+ AdjustUnconscious(-60)
+ AdjustSleeping(-100)
+ visible_message("[M.name] nuzzles [src] trying to wake [p_them()] up!")
+
+ if ("grab")
+ grabbedby(M)
+
+ else
+ if(health > 0)
+ M.do_attack_animation(src, ATTACK_EFFECT_BITE)
+ playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
+ visible_message("[M.name] bites [src]!", \
+ "[M.name] bites [src]!", null, COMBAT_MESSAGE_RANGE)
+ adjustBruteLoss(1)
+ add_logs(M, src, "attacked")
+ updatehealth()
+ else
+ to_chat(M, "[name] is too injured for that.")
+
+
+/mob/living/carbon/alien/attack_larva(mob/living/carbon/alien/larva/L)
+ return attack_alien(L)
+
+
+/mob/living/carbon/alien/attack_hand(mob/living/carbon/human/M)
+ if(..()) //to allow surgery to return properly.
+ return 0
+
+ switch(M.a_intent)
+ if("help")
+ help_shake_act(M)
+ if("grab")
+ grabbedby(M)
+ if ("harm")
+ M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
+ return 1
+ if("disarm")
+ M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
+ return 1
+ return 0
+
+
+/mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M)
+ if(..())
+ if (stat != DEAD)
+ var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
+ apply_damage(rand(1, 3), BRUTE, affecting)
+
+
+/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
+ . = ..()
+ if(.)
+ var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
+ switch(M.melee_damage_type)
+ if(BRUTE)
+ adjustBruteLoss(damage)
+ if(BURN)
+ adjustFireLoss(damage)
+ if(TOX)
+ adjustToxLoss(damage)
+ if(OXY)
+ adjustOxyLoss(damage)
+ if(CLONE)
+ adjustCloneLoss(damage)
+ if(STAMINA)
+ adjustStaminaLoss(damage)
+
+/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M)
+ if(..()) //successful slime attack
+ var/damage = rand(5, 35)
+ if(M.is_adult)
+ damage = rand(10, 40)
+ adjustBruteLoss(damage)
+ add_logs(M, src, "attacked")
+ updatehealth()
+
+/mob/living/carbon/alien/ex_act(severity, target, origin)
+ if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
+ return
+ ..()
+ switch (severity)
+ if (1)
+ gib()
+ return
+
+ if (2)
+ take_overall_damage(60, 60)
+ adjustEarDamage(30,120)
+
+ if(3)
+ take_overall_damage(30,0)
+ if(prob(50))
+ Unconscious(20)
+ adjustEarDamage(15,60)
+
+/mob/living/carbon/alien/soundbang_act(intensity = 1, stun_pwr = 20, damage_pwr = 5, deafen_pwr = 15)
+ return 0
+
+/mob/living/carbon/alien/acid_act(acidpwr, acid_volume)
+ return 0//aliens are immune to acid.
diff --git a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
index eb17ecc40a..cf8a833bd8 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/alien_powers.dm
@@ -277,7 +277,7 @@ Doesn't work on other aliens/AI.*/
if(user.stomach_contents.len)
for(var/atom/movable/A in user.stomach_contents)
user.stomach_contents.Remove(A)
- A.loc = user.loc
+ A.forceMove(user.drop_location())
if(isliving(A))
var/mob/M = A
M.reset_perspective()
diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
index e93fed311c..2462242e25 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
@@ -11,7 +11,7 @@
..()
/mob/living/carbon/alien/humanoid/hunter/movement_delay()
- . = -1 //hunters are sanic
+ . = -1 //hunters are sanic
. += ..() //but they still need to slow down on stun
diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm
index 404d285b25..f8cf430d74 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/caste/praetorian.dm
@@ -48,4 +48,4 @@
return 1
else
to_chat(user, "We already have an alive queen.")
- return 0
\ No newline at end of file
+ return 0
diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm
index c0577c0d61..375ef2318b 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/caste/sentinel.dm
@@ -18,4 +18,4 @@
/mob/living/carbon/alien/humanoid/sentinel/movement_delay()
- . = ..()
\ No newline at end of file
+ . = ..()
diff --git a/code/modules/mob/living/carbon/alien/humanoid/death.dm b/code/modules/mob/living/carbon/alien/humanoid/death.dm
index 5d85ace4a6..c6c675ead9 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/death.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/death.dm
@@ -20,4 +20,4 @@
if(istype(node)) // just in case someone would ever add a diffirent node to hivenode slot
node.queen_death()
- return ..()
+ return ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
index fdca497bc3..fc759ec827 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
@@ -106,7 +106,7 @@
for(var/atom/movable/A in stomach_contents)
stomach_contents.Remove(A)
new_xeno.stomach_contents.Add(A)
- A.loc = new_xeno
+ A.forceMove(new_xeno)
..()
//For alien evolution/promotion/queen finder procs. Checks for an active alien of that type
diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm
index 101f1495e2..2e2d1f4188 100644
--- a/code/modules/mob/living/carbon/alien/larva/larva.dm
+++ b/code/modules/mob/living/carbon/alien/larva/larva.dm
@@ -65,4 +65,4 @@
/mob/living/carbon/alien/larva/stripPanelEquip(obj/item/what, mob/who)
to_chat(src, "You don't have the dexterity to do this!")
- return
\ No newline at end of file
+ return
diff --git a/code/modules/mob/living/carbon/alien/organs.dm b/code/modules/mob/living/carbon/alien/organs.dm
index 97d0509dfb..de543651eb 100644
--- a/code/modules/mob/living/carbon/alien/organs.dm
+++ b/code/modules/mob/living/carbon/alien/organs.dm
@@ -2,12 +2,12 @@
icon_state = "xgibmid2"
var/list/alien_powers = list()
-/obj/item/organ/alien/New()
+/obj/item/organ/alien/Initialize()
+ . = ..()
for(var/A in alien_powers)
if(ispath(A))
alien_powers -= A
alien_powers += new A(src)
- ..()
/obj/item/organ/alien/Insert(mob/living/carbon/M, special = 0)
..()
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index e2ae973d43..13aa33aaca 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -8,7 +8,7 @@
GLOB.carbon_list += src
/mob/living/carbon/Destroy()
-//This must be done first, so the mob ghosts correctly before DNA etc is nulled
+ //This must be done first, so the mob ghosts correctly before DNA etc is nulled
. = ..()
QDEL_LIST(internal_organs)
@@ -38,7 +38,7 @@
if(prob(src.getBruteLoss() - 50))
for(var/atom/movable/A in stomach_contents)
- A.loc = loc
+ A.forceMove(drop_location())
stomach_contents.Remove(A)
src.gib()
@@ -332,7 +332,7 @@
if (client)
client.screen -= W
if (W)
- W.loc = loc
+ W.forceMove(drop_location())
W.dropped(src)
if (W)
W.layer = initial(W.layer)
@@ -345,7 +345,7 @@
if (client)
client.screen -= W
if (W)
- W.loc = loc
+ W.forceMove(drop_location())
W.dropped(src)
if (W)
W.layer = initial(W.layer)
@@ -372,7 +372,7 @@
else
if(I == handcuffed)
- handcuffed.loc = loc
+ handcuffed.forceMove(drop_location())
handcuffed.dropped(src)
handcuffed = null
if(buckled && buckled.buckle_requires_restraints)
@@ -380,7 +380,7 @@
update_handcuffed()
return
if(I == legcuffed)
- legcuffed.loc = loc
+ legcuffed.forceMove(drop_location())
legcuffed.dropped()
legcuffed = null
update_inv_legcuffed()
@@ -786,7 +786,7 @@
if(prob(50))
organs_amt++
O.Remove(src)
- O.loc = get_turf(src)
+ O.forceMove(drop_location())
if(organs_amt)
to_chat(user, "You retrieve some of [src]\'s internal organs!")
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 0bfa287a09..d876e2dab1 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -78,7 +78,6 @@
send_item_attack_message(I, user, affecting.name)
if(I.force)
apply_damage(I.force, I.damtype, affecting)
- damage_clothes(I.force, I.damtype, "melee", affecting.body_zone)
if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC)
if(prob(33))
I.add_mob_blood(src)
diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm
index e2555d4a8b..37b5539d33 100644
--- a/code/modules/mob/living/carbon/carbon_movement.dm
+++ b/code/modules/mob/living/carbon/carbon_movement.dm
@@ -19,7 +19,7 @@
if(stat == SOFT_CRIT)
. += SOFTCRIT_ADD_SLOWDOWN
-
+
/mob/living/carbon/slip(knockdown_amount, obj/O, lube)
if(movement_type & FLYING)
return 0
diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm
index 991fd7a94d..752a9d6471 100644
--- a/code/modules/mob/living/carbon/human/emote.dm
+++ b/code/modules/mob/living/carbon/human/emote.dm
@@ -151,7 +151,7 @@
var/mob/living/carbon/human/H = user
if(H.dna && H.dna.species && (H.dna.features["wings"] != "None"))
return TRUE
-
+
/mob/living/carbon/human/proc/OpenWings()
if(!dna || !dna.species)
return
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 6ed9291b83..de83812aab 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -230,14 +230,13 @@
msg += "[t_He] [t_is] plump and delicious looking - Like a fat little piggy. A tasty piggy.\n"
else
msg += "[t_He] [t_is] quite chubby.\n"
-
switch(disgust)
if(DISGUST_LEVEL_GROSS to DISGUST_LEVEL_VERYGROSS)
- msg += "[t_He] looks a bit grossed out.\n"
+ msg += "[t_He] look[p_s()] a bit grossed out.\n"
if(DISGUST_LEVEL_VERYGROSS to DISGUST_LEVEL_DISGUSTED)
- msg += "[t_He] looks really grossed out.\n"
+ msg += "[t_He] look[p_s()] really grossed out.\n"
if(DISGUST_LEVEL_DISGUSTED to INFINITY)
- msg += "[t_He] looks disgusted.\n"
+ msg += "[t_He] look[p_s()] extremely disgusted.\n"
if(blood_volume < BLOOD_VOLUME_SAFE)
msg += "[t_He] [t_has] pale skin.\n"
@@ -342,6 +341,7 @@
R = find_record("name", perpname, GLOB.data_core.security)
if(R)
criminal = R.fields["criminal"]
+
msg += "Criminal status:\[[criminal]\]\n"
msg += "Security record:\[View\] "
msg += "\[Add crime\] "
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index f0c630421d..711af9958b 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -263,7 +263,7 @@
// Display a warning if the user mocks up
to_chat(src, "You feel your [pocket_side] pocket being fumbled with!")
- ..()
+ ..()
///////HUDs///////
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index e8d4baba63..8899c34e1e 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -131,7 +131,7 @@
var/obj/item/bodypart/L = pick(bodyparts)
L.embedded_objects |= I
I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
- I.loc = src
+ I.forceMove(src)
L.receive_damage(I.w_class*I.embedded_impact_pain_multiplier)
visible_message("[I] embeds itself in [src]'s [L.name]!","[I] embeds itself in your [L.name]!")
hitpush = FALSE
@@ -140,8 +140,8 @@
return ..()
/mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0)
- if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && isliving(pulling))
- vore_attack(user, pulling)
+ if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && (disabilities & FAT) && ismonkey(pulling))
+ devour_mob(pulling)
else
..()
@@ -180,7 +180,6 @@
visible_message("[message]", \
"[message]")
adjustBruteLoss(15)
- damage_clothes(15, BRUTE, "melee")
return 1
/mob/living/carbon/human/attack_hand(mob/user)
@@ -200,7 +199,8 @@
return 0
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stunned instead.
- if(dropItemToGround(get_active_held_item()))
+ var/obj/item/I = get_active_held_item()
+ if(I && dropItemToGround(I))
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
visible_message("[M] disarmed [src]!", \
"[M] disarmed [src]!")
@@ -221,7 +221,6 @@
return 0
if(stat != DEAD)
apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee"))
- damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
return 1
/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M)
@@ -251,10 +250,10 @@
if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful
return 1
apply_damage(damage, BRUTE, affecting, armor_block)
- damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stun instead.
- if(dropItemToGround(get_active_held_item()))
+ var/obj/item/I = get_active_held_item()
+ if(I && dropItemToGround(I))
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
visible_message("[M] disarmed [src]!", \
"[M] disarmed [src]!")
@@ -279,7 +278,6 @@
affecting = get_bodypart("chest")
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
- damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M)
@@ -296,7 +294,6 @@
affecting = get_bodypart("chest")
var/armor = run_armor_check(affecting, "melee", armour_penetration = M.armour_penetration)
apply_damage(damage, M.melee_damage_type, affecting, armor)
- damage_clothes(damage, M.melee_damage_type, "melee", affecting.body_zone)
/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M)
@@ -317,7 +314,6 @@
affecting = get_bodypart("chest")
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
- damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
/mob/living/carbon/human/mech_melee_attack(obj/mecha/M)
@@ -335,11 +331,9 @@
Unconscious(20)
update |= temp.receive_damage(dmg, 0)
playsound(src, 'sound/weapons/punch4.ogg', 50, 1)
- damage_clothes(dmg, BRUTE, "melee", temp.body_zone)
if("fire")
update |= temp.receive_damage(0, dmg)
playsound(src, 'sound/items/welder.ogg', 50, 1)
- damage_clothes(dmg, BURN, "melee", temp.body_zone)
if("tox")
M.mech_toxin_damage(src)
else
@@ -374,6 +368,9 @@
throw_at(throw_target, 200, 4)
damage_clothes(400 - bomb_armor, BRUTE, "bomb")
else
+ for(var/I in contents)
+ var/atom/A = I
+ A.ex_act(severity)
gib()
return
diff --git a/code/modules/mob/living/carbon/human/interactive.dm b/code/modules/mob/living/carbon/human/interactive.dm
index 9fd2cbf8de..1bce4fadb5 100644
--- a/code/modules/mob/living/carbon/human/interactive.dm
+++ b/code/modules/mob/living/carbon/human/interactive.dm
@@ -219,7 +219,7 @@
if(prob(25))
var/cType = pick(list(SNPC_BRUTE,SNPC_STEALTH,SNPC_MARTYR,SNPC_PSYCHO))
T.makeTraitor(cType)
- T.loc = pick(get_area_turfs(T.job2area(T.myjob)))
+ T.forceMove(pick(get_area_turfs(T.job2area(T.myjob))))
if(choice == "Custom")
var/cjob = input("Choose Job") as null|anything in SSjob.occupations
if(cjob)
@@ -256,7 +256,7 @@
var/doTele = input("Place the SNPC in their department?") as null|anything in list("Yes","No")
if(doTele)
if(doTele == "Yes")
- T.loc = pick(get_area_turfs(T.job2area(T.myjob)))
+ T.forceMove(pick(get_area_turfs(T.job2area(T.myjob))))
/mob/living/carbon/human/interactive/proc/doSetup()
Path_ID = new /obj/item/card/id(src)
@@ -506,7 +506,7 @@
var/list/slots = list ("left pocket" = slot_l_store,"right pocket" = slot_r_store,"left hand" = slot_hands,"right hand" = slot_hands)
if(hands)
slots = list ("left hand" = slot_hands,"right hand" = slot_hands)
- G.loc = src
+ G.forceMove(src)
if(G.force && G.force > best_force)
best_force = G.force
equip_in_one_of_slots(G, slots)
@@ -931,7 +931,7 @@
/mob/living/carbon/human/interactive/proc/npcDrop(var/obj/item/A,var/blacklist = 0)
if(blacklist)
blacklistItems += A
- A.loc = get_turf(src) // drop item works inconsistently
+ A.forceMove(drop_location()) // drop item works inconsistently
enforce_hands()
update_icons()
@@ -956,7 +956,7 @@
retal_target = traitorTarget
else
var/obj/item/I = traitorTarget
- I.loc = get_turf(traitorTarget) // pull it outta them
+ I.forceMove(get_turf(I)) // pull it outta them
else
take_to_slot(traitorTarget)
if(SNPC_MARTYR)
@@ -1315,7 +1315,7 @@
customEmote("[src] [pick("gibbers","drools","slobbers","claps wildly","spits")], grabbing various foodstuffs from [SF] and sticking them in it's mouth!")
for(var/obj/item/A in SF.contents)
if(prob(smartness/2))
- A.loc = src
+ A.forceMove(src)
if(foundCustom)
@@ -1398,7 +1398,7 @@
if(!Adjacent(toGrab))
tryWalk(toGrab)
else
- toGrab.loc = src
+ toGrab.forceMove(src)
if(finishedList.len > 0)
var/obj/structure/table/reinforced/RT
@@ -1563,7 +1563,7 @@
var/obj/item/W = main_hand
W.attack(TARGET,src)
else
- G.loc = get_turf(src) // drop item works inconsistently
+ G.forceMove(drop_location()) // drop item works inconsistently
enforce_hands()
update_icons()
else
@@ -1622,4 +1622,4 @@
TRAITS |= TRAIT_ROBUST
TRAITS |= TRAIT_SMART
faction += "bot_power"
- . = ..()
\ No newline at end of file
+ . = ..()
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index cca672d3d8..51d0a731dd 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -32,8 +32,7 @@
handle_arousal()
if(..()) //not dead
- for(var/datum/mutation/human/HM in dna.mutations)
- HM.on_life(src)
+ handle_active_genes()
if(stat != DEAD)
//heart attack stuff
@@ -153,7 +152,7 @@
//END FIRE CODE
-//This proc returns a number made up of the flags_1 for body parts which you are protected on. (such as HEAD, CHEST, GROIN, etc. See setup.dm for the full list)
+//This proc returns a number made up of the flags for body parts which you are protected on. (such as HEAD, CHEST, GROIN, etc. See setup.dm for the full list)
/mob/living/carbon/human/proc/get_heat_protection_flags(temperature) //Temperature is the temperature you're being exposed to.
var/thermal_protection_flags = 0
//Handle normal clothing
@@ -314,7 +313,7 @@
if(prob(I.embedded_fall_chance))
BP.receive_damage(I.w_class*I.embedded_fall_pain_multiplier)
BP.embedded_objects -= I
- I.loc = get_turf(src)
+ I.forceMove(drop_location())
visible_message("[I] falls out of [name]'s [BP.name]!","[I] falls out of your [BP.name]!")
if(!has_embedded_objects())
clear_alert("embeddedobject")
@@ -343,6 +342,9 @@
heart.beating = !status
+/mob/living/carbon/human/proc/handle_active_genes()
+ for(var/datum/mutation/human/HM in dna.mutations)
+ HM.on_life(src)
/mob/living/carbon/human/proc/handle_heart()
if(!can_heartattack())
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 0b02a2c711..d58c9b5c7e 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -53,7 +53,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/damage_overlay_type = "human" //what kind of damage overlays (if any) appear on our species when wounded?
var/fixed_mut_color = "" //to use MUTCOLOR with a fixed color that's independent of dna.feature["mcolor"]
- // species flags_1. these can be found in flags_1.dm
+ // species flags. these can be found in flags.dm
var/list/species_traits = list()
var/attack_verb = "punch" // punch-specific attack verb
@@ -125,12 +125,11 @@ GLOBAL_LIST_EMPTY(roundstart_races)
randname += " [pick(GLOB.last_names)]"
return randname
-
+
//Called when cloning, copies some vars that should be kept
/datum/species/proc/copy_properties_from(datum/species/old_species)
return
-
//Please override this locally if you want to define when what species qualifies for what rank if human authority is enforced.
/datum/species/proc/qualifies_for_rank(rank, list/features)
if(rank in GLOB.command_positions)
@@ -1093,7 +1092,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
/datum/species/proc/get_spans()
return list()
-/datum/species/proc/check_weakness(obj/item/weapon, mob/living/attacker)
+/datum/species/proc/check_weakness(obj/item, mob/living/attacker)
return 0
////////
@@ -1476,7 +1475,6 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/weakness = H.check_weakness(I, user)
apply_damage(I.force * weakness, I.damtype, def_zone, armor_block, H)
- H.damage_clothes(I.force, I.damtype, "melee", affecting.body_zone)
H.send_item_attack_message(I, user, hit_area)
diff --git a/code/modules/mob/living/carbon/human/species_types/angel.dm b/code/modules/mob/living/carbon/human/species_types/angel.dm
index de0120028c..fed10446f1 100644
--- a/code/modules/mob/living/carbon/human/species_types/angel.dm
+++ b/code/modules/mob/living/carbon/human/species_types/angel.dm
@@ -136,4 +136,4 @@
H.movement_type &= ~FLYING
override_float = FALSE
H.pass_flags &= ~PASSTABLE
- H.CloseWings()
+ H.CloseWings()
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species_types/corporate.dm b/code/modules/mob/living/carbon/human/species_types/corporate.dm
index d78d2b5262..bc1fcc9b1e 100644
--- a/code/modules/mob/living/carbon/human/species_types/corporate.dm
+++ b/code/modules/mob/living/carbon/human/species_types/corporate.dm
@@ -16,4 +16,4 @@
blacklisted = 1
use_skintones = 0
species_traits = list(SPECIES_ORGANIC,RADIMMUNE,VIRUSIMMUNE,NOBLOOD,PIERCEIMMUNE,EYECOLOR,NODISMEMBER,NOHUNGER)
- sexes = 0
+ sexes = 0
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm
index d2c83fa39f..2063238cd3 100644
--- a/code/modules/mob/living/carbon/human/species_types/golems.dm
+++ b/code/modules/mob/living/carbon/human/species_types/golems.dm
@@ -595,6 +595,7 @@
H.adjustFireLoss(-4)
H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM)
+
/datum/species/golem/clockwork
name = "Clockwork Golem"
id = "clockwork golem"
@@ -647,6 +648,7 @@
dangerous_existence = TRUE
random_eligible = FALSE
+
/datum/species/golem/cloth
name = "Cloth Golem"
id = "cloth golem"
diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm
index fe0acc4feb..cec82a62d9 100644
--- a/code/modules/mob/living/carbon/human/species_types/humans.dm
+++ b/code/modules/mob/living/carbon/human/species_types/humans.dm
@@ -12,7 +12,7 @@
/datum/species/human/qualifies_for_rank(rank, list/features)
- return TRUE
+ return TRUE //Pure humans are always allowed in all roles.
//Curiosity killed the cat's wagging tail.
/datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
index 09c9df5f9f..17f5bafc42 100644
--- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
@@ -182,7 +182,9 @@
var/mob/living/L = AM
if(iscyborg(AM))
var/mob/living/silicon/robot/borg = AM
- borg.update_headlamp(TRUE, 100)
+ if(!borg.lamp_cooldown)
+ borg.update_headlamp(TRUE, INFINITY)
+ to_chat(borg, "Your headlamp is fried! You'll need a human to help replace it.")
else
for(var/obj/item/O in AM)
if(O.light_range && O.light_power)
diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
index 0a55ae0134..be56909b7c 100644
--- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm
+++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm
@@ -15,4 +15,4 @@
/datum/species/skeleton/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
return TRUE
- return ..()
+ return ..()
diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm
index 4592d76138..62e1a53355 100644
--- a/code/modules/mob/living/carbon/inventory.dm
+++ b/code/modules/mob/living/carbon/inventory.dm
@@ -1,142 +1,142 @@
-/mob/living/carbon/get_item_by_slot(slot_id)
- switch(slot_id)
- if(slot_back)
- return back
- if(slot_wear_mask)
- return wear_mask
- if(slot_neck)
- return wear_neck
- if(slot_head)
- return head
- if(slot_handcuffed)
- return handcuffed
- if(slot_legcuffed)
- return legcuffed
- return null
-
-/mob/living/carbon/proc/equip_in_one_of_slots(obj/item/I, list/slots, qdel_on_fail = 1)
- for(var/slot in slots)
- if(equip_to_slot_if_possible(I, slots[slot], qdel_on_fail = 0, disable_warning = TRUE))
- return slot
- if(qdel_on_fail)
- qdel(I)
- return null
-
-//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
-/mob/living/carbon/equip_to_slot(obj/item/I, slot)
- if(!slot)
- return
- if(!istype(I))
- return
-
- var/index = get_held_index_of_item(I)
- if(index)
- held_items[index] = null
-
- if(I.pulledby)
- I.pulledby.stop_pulling()
-
- I.screen_loc = null
- if(client)
- client.screen -= I
- if(observers && observers.len)
- for(var/M in observers)
- var/mob/dead/observe = M
- if(observe.client)
- observe.client.screen -= I
+/mob/living/carbon/get_item_by_slot(slot_id)
+ switch(slot_id)
+ if(slot_back)
+ return back
+ if(slot_wear_mask)
+ return wear_mask
+ if(slot_neck)
+ return wear_neck
+ if(slot_head)
+ return head
+ if(slot_handcuffed)
+ return handcuffed
+ if(slot_legcuffed)
+ return legcuffed
+ return null
+
+/mob/living/carbon/proc/equip_in_one_of_slots(obj/item/I, list/slots, qdel_on_fail = 1)
+ for(var/slot in slots)
+ if(equip_to_slot_if_possible(I, slots[slot], qdel_on_fail = 0, disable_warning = TRUE))
+ return slot
+ if(qdel_on_fail)
+ qdel(I)
+ return null
+
+//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
+/mob/living/carbon/equip_to_slot(obj/item/I, slot)
+ if(!slot)
+ return
+ if(!istype(I))
+ return
+
+ var/index = get_held_index_of_item(I)
+ if(index)
+ held_items[index] = null
+
+ if(I.pulledby)
+ I.pulledby.stop_pulling()
+
+ I.screen_loc = null
+ if(client)
+ client.screen -= I
+ if(observers && observers.len)
+ for(var/M in observers)
+ var/mob/dead/observe = M
+ if(observe.client)
+ observe.client.screen -= I
I.forceMove(src)
- I.layer = ABOVE_HUD_LAYER
- I.plane = ABOVE_HUD_PLANE
- I.appearance_flags |= NO_CLIENT_COLOR
- var/not_handled = FALSE
- switch(slot)
- if(slot_back)
- back = I
- update_inv_back()
- if(slot_wear_mask)
- wear_mask = I
- wear_mask_update(I, toggle_off = 0)
- if(slot_head)
- head = I
- head_update(I)
- if(slot_neck)
- wear_neck = I
- update_inv_neck(I)
- if(slot_handcuffed)
- handcuffed = I
- update_handcuffed()
- if(slot_legcuffed)
- legcuffed = I
- update_inv_legcuffed()
- if(slot_hands)
- put_in_hands(I)
- update_inv_hands()
- if(slot_in_backpack)
- var/obj/item/storage/B = back
- var/prev_jimmies = B.rustle_jimmies
- B.rustle_jimmies = FALSE //don't conspicously rustle
- B.handle_item_insertion(I, 1, src)
- B.rustle_jimmies = prev_jimmies
- else
- not_handled = TRUE
-
- //Item has been handled at this point and equipped callback can be safely called
- //We cannot call it for items that have not been handled as they are not yet correctly
- //in a slot (handled further down inheritance chain, probably living/carbon/human/equip_to_slot
- if(!not_handled)
- I.equipped(src, slot)
-
- return not_handled
-
-/mob/living/carbon/doUnEquip(obj/item/I)
- . = ..() //Sets the default return value to what the parent returns.
- if(!. || !I) //We don't want to set anything to null if the parent returned 0.
- return
-
- if(I == head)
- head = null
+ I.layer = ABOVE_HUD_LAYER
+ I.plane = ABOVE_HUD_PLANE
+ I.appearance_flags |= NO_CLIENT_COLOR
+ var/not_handled = FALSE
+ switch(slot)
+ if(slot_back)
+ back = I
+ update_inv_back()
+ if(slot_wear_mask)
+ wear_mask = I
+ wear_mask_update(I, toggle_off = 0)
+ if(slot_head)
+ head = I
+ head_update(I)
+ if(slot_neck)
+ wear_neck = I
+ update_inv_neck(I)
+ if(slot_handcuffed)
+ handcuffed = I
+ update_handcuffed()
+ if(slot_legcuffed)
+ legcuffed = I
+ update_inv_legcuffed()
+ if(slot_hands)
+ put_in_hands(I)
+ update_inv_hands()
+ if(slot_in_backpack)
+ var/obj/item/storage/B = back
+ var/prev_jimmies = B.rustle_jimmies
+ B.rustle_jimmies = FALSE //don't conspicously rustle
+ B.handle_item_insertion(I, 1, src)
+ B.rustle_jimmies = prev_jimmies
+ else
+ not_handled = TRUE
+
+ //Item has been handled at this point and equipped callback can be safely called
+ //We cannot call it for items that have not been handled as they are not yet correctly
+ //in a slot (handled further down inheritance chain, probably living/carbon/human/equip_to_slot
+ if(!not_handled)
+ I.equipped(src, slot)
+
+ return not_handled
+
+/mob/living/carbon/doUnEquip(obj/item/I)
+ . = ..() //Sets the default return value to what the parent returns.
+ if(!. || !I) //We don't want to set anything to null if the parent returned 0.
+ return
+
+ if(I == head)
+ head = null
if(!QDELETED(src))
head_update(I)
- else if(I == back)
- back = null
+ else if(I == back)
+ back = null
if(!QDELETED(src))
update_inv_back()
- else if(I == wear_mask)
- wear_mask = null
+ else if(I == wear_mask)
+ wear_mask = null
if(!QDELETED(src))
wear_mask_update(I, toggle_off = 1)
- if(I == wear_neck)
- wear_neck = null
+ if(I == wear_neck)
+ wear_neck = null
if(!QDELETED(src))
update_inv_neck(I)
- else if(I == handcuffed)
- handcuffed = null
- if(buckled && buckled.buckle_requires_restraints)
- buckled.unbuckle_mob(src)
+ else if(I == handcuffed)
+ handcuffed = null
+ if(buckled && buckled.buckle_requires_restraints)
+ buckled.unbuckle_mob(src)
if(!QDELETED(src))
update_handcuffed()
- else if(I == legcuffed)
- legcuffed = null
+ else if(I == legcuffed)
+ legcuffed = null
if(!QDELETED(src))
update_inv_legcuffed()
-
-//handle stuff to update when a mob equips/unequips a mask.
-/mob/living/proc/wear_mask_update(obj/item/clothing/C, toggle_off = 1)
- update_inv_wear_mask()
-
-/mob/living/carbon/wear_mask_update(obj/item/clothing/C, toggle_off = 1)
- if(C.tint || initial(C.tint))
- update_tint()
- update_inv_wear_mask()
-
-//handle stuff to update when a mob equips/unequips a headgear.
-/mob/living/carbon/proc/head_update(obj/item/I, forced)
- if(istype(I, /obj/item/clothing))
- var/obj/item/clothing/C = I
- if(C.tint || initial(C.tint))
- update_tint()
- update_sight()
- if(I.flags_inv & HIDEMASK || forced)
- update_inv_wear_mask()
- update_inv_head()
-
+
+//handle stuff to update when a mob equips/unequips a mask.
+/mob/living/proc/wear_mask_update(obj/item/clothing/C, toggle_off = 1)
+ update_inv_wear_mask()
+
+/mob/living/carbon/wear_mask_update(obj/item/clothing/C, toggle_off = 1)
+ if(C.tint || initial(C.tint))
+ update_tint()
+ update_inv_wear_mask()
+
+//handle stuff to update when a mob equips/unequips a headgear.
+/mob/living/carbon/proc/head_update(obj/item/I, forced)
+ if(istype(I, /obj/item/clothing))
+ var/obj/item/clothing/C = I
+ if(C.tint || initial(C.tint))
+ update_tint()
+ update_sight()
+ if(I.flags_inv & HIDEMASK || forced)
+ update_inv_wear_mask()
+ update_inv_head()
+
diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm
index 5eb09a8d83..97785fef12 100644
--- a/code/modules/mob/living/carbon/life.dm
+++ b/code/modules/mob/living/carbon/life.dm
@@ -49,10 +49,6 @@
return
if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
return
- if(istype(loc, /obj/item/device/dogborg/sleeper))
- return
- if(ismob(loc))
- return
var/datum/gas_mixture/environment
if(loc)
@@ -460,4 +456,4 @@
death()
var/obj/item/organ/brain/B = getorganslot(ORGAN_SLOT_BRAIN)
if(B)
- B.damaged_brain = TRUE
+ B.damaged_brain = TRUE
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm
index d6afdbdbc2..b61bd21a64 100644
--- a/code/modules/mob/living/carbon/monkey/combat.dm
+++ b/code/modules/mob/living/carbon/monkey/combat.dm
@@ -77,7 +77,7 @@
return FALSE
// WEAPONS
- if(istype(I, /obj/item/weapon))
+ if(istype(I, /obj/item))
var/obj/item/W = I
if(W.force >= best_force)
put_in_hands(W)
@@ -150,7 +150,7 @@
return TRUE
// have we been disarmed
- if(!locate(/obj/item/weapon) in held_items)
+ if(!locate(/obj/item) in held_items)
best_force = 0
if(restrained() || blacklistItems[pickupTarget] || (pickupTarget && (pickupTarget.flags_1 & NODROP_1)))
@@ -388,7 +388,7 @@
// attack using a held weapon otherwise bite the enemy, then if we are angry there is a chance we might calm down a little
/mob/living/carbon/monkey/proc/monkey_attack(mob/living/L)
- var/obj/item/Weapon = locate(/obj/item/weapon) in held_items
+ var/obj/item/Weapon = locate(/obj/item) in held_items
// attack with weapon if we have one
if(Weapon)
diff --git a/code/modules/mob/living/carbon/monkey/life.dm b/code/modules/mob/living/carbon/monkey/life.dm
index 613a04bd17..7ddb9190a2 100644
--- a/code/modules/mob/living/carbon/monkey/life.dm
+++ b/code/modules/mob/living/carbon/monkey/life.dm
@@ -133,7 +133,6 @@
/mob/living/carbon/monkey/has_smoke_protection()
if(wear_mask)
-
if(wear_mask.flags_1 & BLOCK_GAS_SMOKE_EFFECT_1)
return 1
diff --git a/code/modules/mob/living/carbon/monkey/monkey_defense.dm b/code/modules/mob/living/carbon/monkey/monkey_defense.dm
index 96cafa4501..e51017d899 100644
--- a/code/modules/mob/living/carbon/monkey/monkey_defense.dm
+++ b/code/modules/mob/living/carbon/monkey/monkey_defense.dm
@@ -16,9 +16,6 @@
if(stat != DEAD)
var/dmg = rand(1, 5)
apply_damage(dmg, BRUTE, affecting)
- damage_clothes(dmg, BRUTE, "melee", affecting.body_zone)
-
-
/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L)
if(..()) //successful larva bite.
@@ -29,7 +26,6 @@
if(!affecting)
affecting = get_bodypart("chest")
apply_damage(damage, BRUTE, affecting)
- damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M)
if(..()) //To allow surgery to return properly.
@@ -58,7 +54,6 @@
if(!affecting)
affecting = get_bodypart("chest")
apply_damage(damage, BRUTE, affecting)
- damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
add_logs(M, src, "attacked")
else
@@ -101,7 +96,6 @@
if(!dismembering_strike(M, affecting.body_zone)) //Dismemberment successful
return 1
apply_damage(damage, BRUTE, affecting)
- damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
else
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
@@ -136,9 +130,6 @@
if(!affecting)
affecting = get_bodypart("chest")
apply_damage(damage, M.melee_damage_type, affecting)
- damage_clothes(damage, M.melee_damage_type, "melee", affecting.body_zone)
-
-
/mob/living/carbon/monkey/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
@@ -152,8 +143,6 @@
if(!affecting)
affecting = get_bodypart("chest")
apply_damage(damage, BRUTE, affecting)
- damage_clothes(damage, BRUTE, "melee", affecting.body_zone)
-
/mob/living/carbon/monkey/acid_act(acidpwr, acid_volume, bodyzone_hit)
. = 1
diff --git a/code/modules/mob/living/carbon/monkey/punpun.dm b/code/modules/mob/living/carbon/monkey/punpun.dm
index 767268f8dc..fc0d97e3cb 100644
--- a/code/modules/mob/living/carbon/monkey/punpun.dm
+++ b/code/modules/mob/living/carbon/monkey/punpun.dm
@@ -74,4 +74,4 @@
file_data["relic_hat"] = head ? head.type : null
file_data["relic_mask"] = wear_mask ? wear_mask.type : null
fdel(json_file)
- WRITE_FILE(json_file, json_encode(file_data))
\ No newline at end of file
+ WRITE_FILE(json_file, json_encode(file_data))
diff --git a/code/modules/mob/living/carbon/say.dm b/code/modules/mob/living/carbon/say.dm
index c1a6af9688..83d943ccbf 100644
--- a/code/modules/mob/living/carbon/say.dm
+++ b/code/modules/mob/living/carbon/say.dm
@@ -36,7 +36,7 @@
if(T)
. = T.could_speak_in_language(dt)
else
- . = initial(dt.flags_1) & TONGUELESS_SPEECH
+ . = initial(dt.flags) & TONGUELESS_SPEECH
/mob/living/carbon/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
if(!client)
@@ -44,4 +44,4 @@
for(var/T in get_traumas())
var/datum/brain_trauma/trauma = T
message = trauma.on_hear(message, speaker, message_language, raw_message, radio_freq)
- return ..()
+ return ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index f589ecbb20..8c712b33fb 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -979,7 +979,6 @@
stop_pulling()
else if(has_legs || ignore_legs)
lying = 0
-
if(buckled)
lying = 90*buckle_lying
else if(!lying)
diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm
index b1d0484086..385f48c8d9 100644
--- a/code/modules/mob/living/say.dm
+++ b/code/modules/mob/living/say.dm
@@ -72,7 +72,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
/mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE)
var/static/list/crit_allowed_modes = list(MODE_WHISPER = TRUE, MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
var/static/list/unconscious_allowed_modes = list(MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
- var/key = get_key(message)
+ var/talk_key = get_key(message)
var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE)
@@ -134,12 +134,10 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
// Detection of language needs to be before inherent channels, because
// AIs use inherent channels for the holopad. Most inherent channels
// ignore the language argument however.
-
- var/datum/saymode/SM = SSradio.saymodes[key]
- if(key && SM)
- if(!SM.handle_message(src, message, language) && !message_mode)
- return
-
+
+ var/datum/saymode/SM = SSradio.saymodes[talk_key]
+ if(SM && !SM.handle_message(src, message, language))
+ return
if(!can_speak_vocal(message))
to_chat(src, "You find yourself unable to speak!")
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 47d5a0ffd8..86314e33d7 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -117,7 +117,7 @@
job = "AI"
eyeobj.ai = src
- eyeobj.loc = src.loc
+ eyeobj.forceMove(src.loc)
rename_self("ai")
holo_icon = getHologramIcon(icon('icons/mob/ai.dmi',"default"))
diff --git a/code/modules/mob/living/silicon/ai/examine.dm b/code/modules/mob/living/silicon/ai/examine.dm
index 3af95cec4c..025d3d8e6d 100644
--- a/code/modules/mob/living/silicon/ai/examine.dm
+++ b/code/modules/mob/living/silicon/ai/examine.dm
@@ -1,26 +1,26 @@
-/mob/living/silicon/ai/examine(mob/user)
+/mob/living/silicon/ai/examine(mob/user)
var/msg = "*---------*\nThis is [icon2html(src, user)] [src]!\n"
- if (stat == DEAD)
- msg += "It appears to be powered-down.\n"
- else
- msg += ""
- if (getBruteLoss())
- if (getBruteLoss() < 30)
- msg += "It looks slightly dented.\n"
- else
- msg += "It looks severely dented!\n"
- if (getFireLoss())
- if (getFireLoss() < 30)
- msg += "It looks slightly charred.\n"
- else
- msg += "Its casing is melted and heat-warped!\n"
- msg += ""
- if(deployed_shell)
- msg += "The wireless networking light is blinking.\n"
- else if (!shunted && !client)
- msg += "[src]Core.exe has stopped responding! NTOS is searching for a solution to the problem...\n"
- msg += "*---------*"
-
- to_chat(user, msg)
-
+ if (stat == DEAD)
+ msg += "It appears to be powered-down.\n"
+ else
+ msg += ""
+ if (getBruteLoss())
+ if (getBruteLoss() < 30)
+ msg += "It looks slightly dented.\n"
+ else
+ msg += "It looks severely dented!\n"
+ if (getFireLoss())
+ if (getFireLoss() < 30)
+ msg += "It looks slightly charred.\n"
+ else
+ msg += "Its casing is melted and heat-warped!\n"
+ msg += ""
+ if(deployed_shell)
+ msg += "The wireless networking light is blinking.\n"
+ else if (!shunted && !client)
+ msg += "[src]Core.exe has stopped responding! NTOS is searching for a solution to the problem...\n"
+ msg += "*---------*"
+
+ to_chat(user, msg)
+
..()
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm
index 2a009d4d00..a76c02f3b5 100644
--- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm
+++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm
@@ -173,4 +173,4 @@
obscured += t.obscured
#undef UPDATE_BUFFER
-#undef CHUNK_SIZE
+#undef CHUNK_SIZE
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/death.dm b/code/modules/mob/living/silicon/death.dm
index 7537697d71..2e1adb1959 100644
--- a/code/modules/mob/living/silicon/death.dm
+++ b/code/modules/mob/living/silicon/death.dm
@@ -1,13 +1,13 @@
-/mob/living/silicon/spawn_gibs()
+/mob/living/silicon/spawn_gibs()
new /obj/effect/gibspawner/robot(get_turf(src))
-
-/mob/living/silicon/spawn_dust()
- new /obj/effect/decal/remains/robot(loc)
-
-/mob/living/silicon/death(gibbed)
- if(!gibbed)
- emote("deathgasp")
- diag_hud_set_status()
- diag_hud_set_health()
- update_health_hud()
+
+/mob/living/silicon/spawn_dust()
+ new /obj/effect/decal/remains/robot(loc)
+
+/mob/living/silicon/death(gibbed)
+ if(!gibbed)
+ emote("deathgasp")
+ diag_hud_set_status()
+ diag_hud_set_health()
+ update_health_hud()
. = ..()
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index b12430d26d..3042ddc5df 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -51,7 +51,7 @@
var/obj/machinery/door/hackdoor // The airlock being hacked
var/hackprogress = 0 // Possible values: 0 - 100, >= 100 means the hack is complete and will be reset upon next check
- var/obj/item/radio/integrated/signal/sradio // AI's signaller
+ var/obj/item/integrated_signaler/signaler // AI's signaller
var/holoform = FALSE
var/canholo = TRUE
@@ -101,7 +101,7 @@
P.setPersonality(src)
forceMove(P)
card = P
- sradio = new(src)
+ signaler = new(src)
if(!radio)
radio = new /obj/item/device/radio(src)
diff --git a/code/modules/mob/living/silicon/pai/software.dm b/code/modules/mob/living/silicon/pai/software.dm
index e73792e705..bb057f7774 100644
--- a/code/modules/mob/living/silicon/pai/software.dm
+++ b/code/modules/mob/living/silicon/pai/software.dm
@@ -169,23 +169,20 @@
if("signaller")
if(href_list["send"])
-
- sradio.send_signal("ACTIVATE")
+ signaler.send_activation()
audible_message("[icon2html(src, world)] *beep* *beep*")
if(href_list["freq"])
-
- var/new_frequency = (sradio.frequency + text2num(href_list["freq"]))
- if(new_frequency < 1200 || new_frequency > 1600)
+ var/new_frequency = (signaler.frequency + text2num(href_list["freq"]))
+ if(new_frequency < MIN_FREE_FREQ || new_frequency > MAX_FREE_FREQ)
new_frequency = sanitize_frequency(new_frequency)
- sradio.set_frequency(new_frequency)
+ signaler.set_frequency(new_frequency)
if(href_list["code"])
-
- sradio.code += text2num(href_list["code"])
- sradio.code = round(sradio.code)
- sradio.code = min(100, sradio.code)
- sradio.code = max(1, sradio.code)
+ signaler.code += text2num(href_list["code"])
+ signaler.code = round(signaler.code)
+ signaler.code = min(100, signaler.code)
+ signaler.code = max(1, signaler.code)
@@ -397,14 +394,14 @@
Frequency:
--
- [format_frequency(sradio.frequency)]
+ [format_frequency(signaler.frequency)]
++
Code:
--
- [sradio.code]
+ [signaler.code]
++
diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm
index aab1f204f6..d09f8cd4a2 100644
--- a/code/modules/mob/living/silicon/robot/life.dm
+++ b/code/modules/mob/living/silicon/robot/life.dm
@@ -50,6 +50,7 @@
if(!mind.special_role)
mind.special_role = "traitor"
SSticker.mode.traitors += mind
+ mind.add_antag_datum(/datum/antagonist/auto_custom) // ????
/mob/living/silicon/robot/update_health_hud()
diff --git a/code/modules/mob/living/silicon/robot/login.dm b/code/modules/mob/living/silicon/robot/login.dm
index cf55cdd5f9..8fb58b9472 100644
--- a/code/modules/mob/living/silicon/robot/login.dm
+++ b/code/modules/mob/living/silicon/robot/login.dm
@@ -1,3 +1,4 @@
+
/mob/living/silicon/robot/Login()
..()
regenerate_icons()
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index db10f4a81c..71b58fddd0 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -5,8 +5,6 @@
icon_state = "robot"
maxHealth = 100
health = 100
- macro_default = "robot-default"
- macro_hotkeys = "robot-hotkeys"
bubble_icon = "robot"
designation = "Default" //used for displaying the prefix & getting the current module of cyborg
has_limbs = 1
@@ -248,17 +246,6 @@
return //won't work if dead
robot_alerts()
-//for borg hotkeys, here module refers to borg inv slot, not core module
-/mob/living/silicon/robot/verb/cmd_toggle_module(module as num)
- set name = "Toggle Module"
- set hidden = 1
- toggle_module(module)
-
-/mob/living/silicon/robot/verb/cmd_unequip_module()
- set name = "Unequip Module"
- set hidden = 1
- uneq_active()
-
/mob/living/silicon/robot/proc/robot_alerts()
var/dat = ""
for (var/cat in alarms)
@@ -537,6 +524,19 @@
toner = tonermax
qdel(W)
to_chat(user, "You fill the toner level of [src] to its max capacity.")
+
+ else if(istype(W, /obj/item/device/flashlight))
+ if(!opened)
+ to_chat(user, "You need to open the panel to repair the headlamp!")
+ if(lamp_cooldown <= world.time)
+ to_chat(user, "The headlamp is already functional!")
+ else
+ if(!user.temporarilyRemoveItemFromInventory(W))
+ to_chat(user, "[W] seems to be stuck to your hand. You'll have to find a different light.")
+ return
+ lamp_cooldown = 0
+ qdel(W)
+ to_chat(user, "You replace the headlamp bulbs.")
else
return ..()
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index b1be1c3076..253cb14a89 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -33,8 +33,8 @@
var/ride_allow_incapacitated = FALSE
var/allow_riding = TRUE
-/obj/item/robot_module/New()
- ..()
+/obj/item/robot_module/Initialize()
+ . = ..()
for(var/i in basic_modules)
var/obj/item/I = new i(src)
basic_modules += I
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index b19bc401e3..383cdd268d 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -72,7 +72,7 @@
var/nearest_beacon // the nearest beacon's tag
var/turf/nearest_beacon_loc // the nearest beacon's location
- var/beacon_freq = 1445 // navigation beacon frequency
+ var/beacon_freq = FREQ_NAV_BEACON
var/model = "" //The type of bot it is.
var/bot_type = 0 //The type of bot it is, for radio control.
var/data_hud_type = DATA_HUD_DIAGNOSTIC_BASIC //The type of data HUD the bot uses. Diagnostic by default.
@@ -108,6 +108,7 @@
if(stat)
return FALSE
on = TRUE
+ canmove = TRUE
set_light(initial(light_range))
update_icon()
diag_hud_set_botstat()
@@ -115,6 +116,7 @@
/mob/living/simple_animal/bot/proc/turn_off()
on = FALSE
+ canmove = FALSE
set_light(0)
bot_reset() //Resets an AI's call, should it exist.
update_icon()
@@ -129,7 +131,7 @@
Radio = new/obj/item/device/radio(src)
if(radio_key)
Radio.keyslot = new radio_key
- Radio.subspace_transmission = 1
+ Radio.subspace_transmission = TRUE
Radio.canhear_range = 0 // anything greater will have the bot broadcast the channel as if it were saying it out loud.
Radio.recalculateChannels()
diff --git a/code/modules/mob/living/simple_animal/bot/construction.dm b/code/modules/mob/living/simple_animal/bot/construction.dm
index 0ef926f942..a4e8d09121 100644
--- a/code/modules/mob/living/simple_animal/bot/construction.dm
+++ b/code/modules/mob/living/simple_animal/bot/construction.dm
@@ -282,8 +282,8 @@
var/skin = null //Same as medbot, set to tox or ointment for the respective kits.
w_class = WEIGHT_CLASS_NORMAL
-/obj/item/firstaid_arm_assembly/New()
- ..()
+/obj/item/firstaid_arm_assembly/Initialize()
+ . = ..()
spawn(5)
if(skin)
add_overlay("kit_skin_[skin]")
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index 0e6ecf1672..8046daf55d 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -360,8 +360,14 @@
..()
/datum/action/innate/seek_master/Activate()
- if(!SSticker.mode.eldergod)
- the_construct.master = GLOB.blood_target
+ var/datum/antagonist/cult/C = owner.mind.has_antag_datum(/datum/antagonist/cult)
+ if(!C)
+ return
+ var/datum/objective/eldergod/summon_objective = locate() in C.cult_team.objectives
+
+ if(summon_objective.check_completion())
+ the_construct.master = C.cult_team.blood_target
+
if(!the_construct.master)
to_chat(the_construct, "You have no master to seek!")
the_construct.seeking = FALSE
diff --git a/code/modules/mob/living/simple_animal/friendly/crab.dm b/code/modules/mob/living/simple_animal/friendly/crab.dm
index 35d7d12174..d2f408e687 100644
--- a/code/modules/mob/living/simple_animal/friendly/crab.dm
+++ b/code/modules/mob/living/simple_animal/friendly/crab.dm
@@ -75,4 +75,4 @@
real_name = "Evil Kreb"
icon_state = "evilkreb"
icon_living = "evilkreb"
- icon_dead = "evilkreb_dead"
+ icon_dead = "evilkreb_dead"
diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm
index 6ea4d2ef94..adc88c5633 100644
--- a/code/modules/mob/living/simple_animal/friendly/dog.dm
+++ b/code/modules/mob/living/simple_animal/friendly/dog.dm
@@ -135,7 +135,7 @@
switch(remove_from)
if("head")
if(inventory_head)
- inventory_head.loc = src.loc
+ inventory_head.forceMove(drop_location())
inventory_head = null
update_corgi_fluff()
regenerate_icons()
@@ -144,7 +144,7 @@
return
if("back")
if(inventory_back)
- inventory_back.loc = src.loc
+ inventory_back.forceMove(drop_location())
inventory_back = null
update_corgi_fluff()
regenerate_icons()
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm b/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm
index 7a2c9e6b39..3b23e4adc0 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/drones_as_items.dm
@@ -15,8 +15,8 @@
icon_state = "drone_maint_hat"//yes reuse the _hat state.
var/drone_type = /mob/living/simple_animal/drone //Type of drone that will be spawned
-/obj/item/drone_shell/New()
- ..()
+/obj/item/drone_shell/Initialize()
+ . = ..()
var/area/A = get_area(src)
if(A)
notify_ghosts("A drone shell has been created in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE)
@@ -67,7 +67,7 @@
L.dropItemToGround(src)
contents -= drone
- drone.loc = get_turf(src)
+ drone.forceMove(drop_location())
drone.reset_perspective()
drone.setDir(SOUTH )//Looks better
drone.visible_message("[drone] uncurls!")
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
index 3aa1153133..65ef28baee 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm
@@ -153,7 +153,7 @@
/mob/living/simple_animal/drone/cogscarab/Login()
..()
- add_servant_of_ratvar(src, TRUE)
+ add_servant_of_ratvar(src, TRUE, GLOB.servants_active)
to_chat(src,"You yourself are one of these servants, and will be able to utilize almost anything they can[GLOB.ratvar_awakens ? "":", excluding a clockwork slab"].") // this can't go with flavortext because i'm assuming it requires them to be ratvar'd
/mob/living/simple_animal/drone/cogscarab/binarycheck()
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/verbs.dm b/code/modules/mob/living/simple_animal/friendly/drone/verbs.dm
index 49faea14b3..70116d53b6 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/verbs.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/verbs.dm
@@ -15,7 +15,6 @@
/mob/living/simple_animal/drone/verb/toggle_light()
set category = "Drone"
set name = "Toggle drone light"
-
if(stat == DEAD)
to_chat(src, "There's no light in your life... by that I mean you're dead.")
return
@@ -40,7 +39,6 @@
var/msg = "DRONE PING: [name]: [alert_s] priority alert in [A.name]!"
alert_drones(msg)
-
/mob/living/simple_animal/drone/verb/toggle_statics()
set name = "Change Vision Filter"
set desc = "Change the filter on the system used to remove non drone beings from your viewscreen."
diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
index cbd14bb376..34ed273c5b 100644
--- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
+++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm
@@ -66,7 +66,7 @@
src.visible_message("[src] gets an evil-looking gleam in [p_their()] eye.")
/mob/living/simple_animal/hostile/retaliate/goat/Move()
- ..()
+ . = ..()
if(!stat)
eat_plants()
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index 85ec19bfb9..809681ed6b 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -110,3 +110,7 @@
eatverb = "devours"
list_reagents = list("nutriment" = 3, "vitamin" = 2)
foodtype = GROSS | MEAT | RAW
+ grind_results = list("blood" = 20, "liquidgibs" = 5)
+
+/obj/item/reagent_containers/food/snacks/deadmouse/on_grind()
+ reagents.clear_reagents()
diff --git a/code/modules/mob/living/simple_animal/friendly/pet.dm b/code/modules/mob/living/simple_animal/friendly/pet.dm
index 3200c8b7d7..7dc2b0f8ca 100644
--- a/code/modules/mob/living/simple_animal/friendly/pet.dm
+++ b/code/modules/mob/living/simple_animal/friendly/pet.dm
@@ -9,17 +9,20 @@
/mob/living/simple_animal/pet/attackby(obj/item/O, mob/user, params)
if(istype(O, /obj/item/clothing/neck/petcollar) && !pcollar)
- var/obj/item/clothing/neck/petcollar/P = O
- pcollar = P
- collar = "[icon_state]collar"
- pettag = "[icon_state]tag"
- regenerate_icons()
- to_chat(user, "You put the [P] around [src]'s neck.")
- if(P.tagname)
- real_name = "\proper [P.tagname]"
- name = real_name
- qdel(P)
- return
+ var/pet_icon_states = icon_states("[icon]")
+ if("[icon_state]collar" in pet_icon_states)
+ var/obj/item/clothing/neck/petcollar/P = O
+ pcollar = P
+ collar = "[icon_state]collar"
+ pettag = "[icon_state]tag"
+ regenerate_icons()
+ to_chat(user, "You put the [P] around [src]'s neck.")
+ if(P.tagname)
+ real_name = "\proper [P.tagname]"
+ name = real_name
+ qdel(P)
+ return
+
if(istype(O, /obj/item/newspaper))
if(!stat)
user.visible_message("[user] baps [name] on the nose with the rolled up [O].")
@@ -51,3 +54,4 @@
add_overlay(collar)
if(pettag)
add_overlay(pettag)
+
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index 577eba1858..efb418a817 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -57,7 +57,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
. = ..()
/mob/living/simple_animal/hostile/guardian/med_hud_set_health()
- if(!QDELETED(summoner))
+ if(summoner)
var/image/holder = hud_list[HEALTH_HUD]
holder.icon_state = "hud[RoundHealth(summoner)]"
diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm
index 2929e146f1..0650f90fc6 100644
--- a/code/modules/mob/living/simple_animal/hostile/faithless.dm
+++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm
@@ -39,4 +39,4 @@
var/mob/living/carbon/C = target
C.Knockdown(60)
C.visible_message("\The [src] knocks down \the [C]!", \
- "\The [src] knocks you down!")
+ "\The [src] knocks you down!")
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
index 84bb54f242..09d97c946d 100644
--- a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
+++ b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm
@@ -105,3 +105,4 @@
if(oogas >= rand(2,6))
playsound(src, "sound/creatures/gorilla.ogg", 200)
oogas = 0
+
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 10d9fd93d7..0b75dc5be8 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -28,9 +28,6 @@
var/ranged_message = "fires" //Fluff text for ranged mobs
var/ranged_cooldown = 0 //What the current cooldown on ranged attacks is, generally world.time + ranged_cooldown_time
var/ranged_cooldown_time = 30 //How long, in deciseconds, the cooldown of ranged attacks is
- var/ranged_telegraph = "prepares to fire at *TARGET*!" //A message shown when the mob prepares to fire; use *TARGET* if you want to show the target's name
- var/ranged_telegraph_sound //A sound played when the mob prepares to fire
- var/ranged_telegraph_time = 0 //In deciseconds, how long between the telegraph and ranged shot
var/ranged_ignores_vision = FALSE //if it'll fire ranged attacks even if it lacks vision on its target, only works with environment smash
var/check_friendly_fire = 0 // Should the ranged mob check for friendlies when shooting
var/retreat_distance = null //If our mob runs from players when they're too close, set in tile distance. By default, mobs do not retreat.
@@ -231,9 +228,6 @@
if(!target || !CanAttack(target))
LoseTarget()
return 0
- if(ismob(target.loc))
- LoseTarget()
- return 0
if(target in possible_targets)
if(target.z != z)
LoseTarget()
@@ -241,14 +235,7 @@
var/target_distance = get_dist(targets_from,target)
if(ranged) //We ranged? Shoot at em
if(!target.Adjacent(targets_from) && ranged_cooldown <= world.time) //But make sure they're not in range for a melee attack and our range attack is off cooldown
- if(!ranged_telegraph_time || client)
- OpenFire(target)
- else
- if(ranged_telegraph)
- visible_message("[src] [replacetext(ranged_telegraph, "*TARGET*", "[target]")]")
- if(ranged_telegraph_sound)
- playsound(src, ranged_telegraph_sound, 75, FALSE)
- addtimer(CALLBACK(src, .proc/OpenFire, target), ranged_telegraph_time)
+ OpenFire(target)
if(!Process_Spacemove()) //Drifting
walk(src,0)
return 1
@@ -412,7 +399,6 @@ mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with mega
DestroyObjectsInDirection(dir)
-
/mob/living/simple_animal/hostile/proc/EscapeConfinement()
if(buckled)
buckled.attack_animal(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm b/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm
index f9868771ac..a1cb61c115 100644
--- a/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm
@@ -283,9 +283,8 @@
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/Move(NewLoc,Dir=0,step_x=0,step_y=0)
if(mecha && loc == mecha)
- mecha.relaymove(src, Dir)
- return
- ..()
+ return mecha.relaymove(src, Dir)
+ return ..()
/mob/living/simple_animal/hostile/syndicate/mecha_pilot/Goto(target, delay, minimum_distance)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
index 03f466ddfd..1db7855e10 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm
@@ -114,7 +114,7 @@ Difficulty: Medium
if(L.stat == DEAD)
visible_message("[src] butchers [L]!",
"You butcher [L], restoring your health!")
- if(!(z in GLOB.station_z_levels && !client)) //NPC monsters won't heal while on station
+ if(!(z in GLOB.station_z_levels) || client) //NPC monsters won't heal while on station
if(guidance)
adjustHealth(-L.maxHealth)
else
@@ -251,9 +251,9 @@ Difficulty: Medium
animate(src, transform = M, pixel_y = -6, dir = final_dir, time = 2, easing = EASE_IN|EASE_OUT)
sleep(5)
- animate(src, color = list("#A7A19E", "#A7A19E", "#A7A19E", list(0, 0, 0)), time = 10, easing = EASE_IN, flags_1 = ANIMATION_PARALLEL)
+ animate(src, color = list("#A7A19E", "#A7A19E", "#A7A19E", list(0, 0, 0)), time = 10, easing = EASE_IN, flags = ANIMATION_PARALLEL)
sleep(4)
- animate(src, alpha = 0, time = 6, easing = EASE_OUT, flags_1 = ANIMATION_PARALLEL)
+ animate(src, alpha = 0, time = 6, easing = EASE_OUT, flags = ANIMATION_PARALLEL)
/obj/item/device/gps/internal/miner
icon_state = null
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index 58e3e0837b..fe6e7f7974 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -783,4 +783,4 @@ Difficulty: Very Hard
#undef ACTIVATE_WEAPON
#undef ACTIVATE_MAGIC
-#undef MEDAL_PREFIX
\ No newline at end of file
+#undef MEDAL_PREFIX
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm
index 7f12e684e8..8ec955892f 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/dragon.dm
@@ -192,7 +192,7 @@ Difficulty: Medium
qdel(F)
if(stat == DEAD)
swooping &= ~SWOOP_DAMAGEABLE
- animate(src, alpha = 255, transform = oldtransform, time = 0, flags_1 = ANIMATION_END_NOW) //reset immediately
+ animate(src, alpha = 255, transform = oldtransform, time = 0, flags = ANIMATION_END_NOW) //reset immediately
return
animate(src, alpha = 100, transform = matrix()*0.7, time = 7)
swooping |= SWOOP_INVULNERABLE
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
index 5c95c2ec26..385ab2c668 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -89,15 +89,11 @@
. = ..()
if(. && isliving(target))
var/mob/living/L = target
- if(L.stat >= SOFT_CRIT)
- if(vore_active == TRUE && L.devourable == TRUE)
- dragon_feeding(src,L)
- else if(L.stat == DEAD)
- devour(L)
+ if(L.stat != DEAD)
+ if(!client && ranged && ranged_cooldown <= world.time)
+ OpenFire()
else
- if(L.stat != DEAD)
- if(!client && ranged && ranged_cooldown <= world.time)
- OpenFire()
+ devour(L)
/mob/living/simple_animal/hostile/megafauna/proc/devour(mob/living/L)
if(!L)
@@ -105,7 +101,7 @@
visible_message(
"[src] devours [L]!",
"You feast on [L], restoring your health!")
- if(!(z in GLOB.station_z_levels && !client)) //NPC monsters won't heal while on station
+ if(!(z in GLOB.station_z_levels) || client) //NPC monsters won't heal while on station
adjustBruteLoss(-L.maxHealth/2)
L.gib()
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
index 7a3a85c35b..bc4686fd42 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
@@ -14,9 +14,6 @@
ranged = 1
ranged_message = "stares"
ranged_cooldown_time = 30
- ranged_telegraph = "gathers energy and stares at *TARGET*!"
- ranged_telegraph_sound = 'sound/magic/magic_missile.ogg'
- ranged_telegraph_time = 7
throw_message = "does nothing against the hard shell of"
vision_range = 2
speed = 3
@@ -74,11 +71,9 @@
melee_damage_lower = 15
melee_damage_upper = 15
attacktext = "impales"
- ranged_telegraph = "fixates on *TARGET* as its eye shines blue!"
- ranged_telegraph_sound = 'sound/magic/tail_swing.ogg'
- ranged_telegraph_time = 5
a_intent = INTENT_HARM
speak_emote = list("telepathically cries")
+ attack_sound = 'sound/weapons/bladeslice.ogg'
stat_attack = UNCONSCIOUS
movement_type = FLYING
robust_searching = 1
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm
index ad7edb1716..3c40bacde8 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm
@@ -123,7 +123,8 @@
/obj/item/udder/gutlunch
name = "nutrient sac"
-/obj/item/udder/gutlunch/New()
+/obj/item/udder/gutlunch/Initialize()
+ . = ..()
reagents = new(50)
reagents.my_atom = src
diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm
index 8ad8babb36..7479b1aaa2 100644
--- a/code/modules/mob/living/simple_animal/hostile/pirate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm
@@ -64,3 +64,4 @@
projectiletype = /obj/item/projectile/beam/laser
loot = list(/obj/effect/mob_spawn/human/corpse/pirate/ranged,
/obj/item/gun/energy/laser)
+
diff --git a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm
index 8355bd2e27..29bc2cbff0 100644
--- a/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm
+++ b/code/modules/mob/living/simple_animal/hostile/venus_human_trap.dm
@@ -12,8 +12,8 @@
var/growth_time = 1200
-/obj/structure/alien/resin/flower_bud_enemy/New()
- ..()
+/obj/structure/alien/resin/flower_bud_enemy/Initialize()
+ . = ..()
var/list/anchors = list()
anchors += locate(x-2,y+2,z)
anchors += locate(x+2,y+2,z)
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
index 681f36e6d9..d6c8403d8f 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -127,7 +127,7 @@
/mob/living/simple_animal/parrot/death(gibbed)
if(held_item)
- held_item.loc = src.loc
+ held_item.forceMove(drop_location())
held_item = null
walk(src,0)
@@ -702,7 +702,7 @@
continue
held_item = I
- I.loc = src
+ I.forceMove(src)
visible_message("[src] grabs [held_item]!", "You grab [held_item]!", "You hear the sounds of wings flapping furiously.")
return held_item
@@ -777,7 +777,7 @@
if(!drop_gently)
if(istype(held_item, /obj/item/grenade))
var/obj/item/grenade/G = held_item
- G.loc = src.loc
+ G.forceMove(drop_location())
G.prime()
to_chat(src, "You let go of [held_item]!")
held_item = null
@@ -785,7 +785,7 @@
to_chat(src, "You drop [held_item].")
- held_item.loc = src.loc
+ held_item.forceMove(drop_location())
held_item = null
return 1
@@ -801,7 +801,7 @@
for(var/atom/movable/AM in view(src,1))
for(var/perch_path in desired_perches)
if(istype(AM, perch_path))
- src.loc = AM.loc
+ src.forceMove(AM.loc)
icon_state = icon_sit
return
to_chat(src, "There is no perch nearby to sit on!")
@@ -838,7 +838,7 @@
/mob/living/simple_animal/parrot/proc/perch_on_human(mob/living/carbon/human/H)
if(!H)
return
- loc = get_turf(H)
+ forceMove(get_turf(H))
H.buckle_mob(src, force=1)
pixel_y = 9
pixel_x = pick(-8,8) //pick left or right shoulder
@@ -996,11 +996,12 @@
return
var/datum/disease/parrot_possession/P = new
P.parrot = src
- loc = H
+ forceMove(H)
H.ForceContractDisease(P)
parrot_interest = null
H.visible_message("[src] dive bombs into [H]'s chest and vanishes!", "[src] dive bombs into your chest, vanishing! This can't be good!")
+
/mob/living/simple_animal/parrot/clock_hawk
name = "clock hawk"
desc = "Cbyl jnaan penpxre! Fdhnnnjx!"
diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm
index 9ffbff5619..7e7a86a9e4 100644
--- a/code/modules/mob/login.dm
+++ b/code/modules/mob/login.dm
@@ -30,8 +30,6 @@
sync_mind()
- client.sethotkeys() //set mob specific hotkeys
-
//Reload alternate appearances
for(var/v in GLOB.active_alternate_appearances)
if(!v)
@@ -45,6 +43,10 @@
client.change_view(CONFIG_GET(string/default_view)) // Resets the client.view in case it was changed.
+ if(client.player_details.player_actions.len)
+ for(var/datum/action/A in client.player_details.player_actions)
+ A.Grant(src)
+
if(!GLOB.individual_log_list[ckey])
GLOB.individual_log_list[ckey] = logging
else
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index b19af6342c..4b08876daa 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -30,6 +30,7 @@
GLOB.dead_mob_list += src
else
GLOB.alive_mob_list += src
+ set_focus(src)
prepare_huds()
for(var/v in GLOB.active_alternate_appearances)
if(!v)
@@ -125,7 +126,7 @@
if(self_message)
msg = self_message
else
- if(M.see_invisibleThis mob type cannot throw items.")
- return
-
-
-/client/Northwest()
- var/obj/item/I = usr.get_active_held_item()
- if(!I)
- to_chat(usr, "You have nothing to drop in your hand!")
- return
- usr.dropItemToGround(I)
-
-//This gets called when you press the delete button.
-/client/verb/delete_key_pressed()
- set hidden = 1
-
- if(!isliving(usr))
- return
- if(!usr.pulling)
- to_chat(usr, "You are not pulling anything.")
- return
- usr.stop_pulling()
-
-/client/verb/swap_hand()
- set category = "IC"
- set name = "Swap hands"
-
- if(mob)
- mob.swap_hand()
-
-/client/verb/attack_self()
- set hidden = 1
- if(mob)
- mob.mode()
- return
-
-
/client/verb/drop_item()
set hidden = 1
if(!iscyborg(mob) && mob.stat == CONSCIOUS)
mob.dropItemToGround(mob.get_active_held_item())
return
-
-/client/Center()
- if(isobj(mob.loc))
- var/obj/O = mob.loc
- if(mob.canmove)
- return O.relaymove(mob, 0)
- return
-
-
/client/proc/Move_object(direct)
if(mob && mob.control_object)
if(mob.control_object.density)
@@ -107,26 +25,30 @@
return
mob.control_object.setDir(direct)
else
- mob.control_object.loc = get_step(mob.control_object,direct)
+ mob.control_object.forceMove(get_step(mob.control_object,direct))
return
#define MOVEMENT_DELAY_BUFFER 0.75
#define MOVEMENT_DELAY_BUFFER_DELTA 1.25
/client/Move(n, direct)
- if(world.time < move_delay)
+ if(world.time < move_delay) //do not move anything ahead of this check please
return FALSE
+ else
+ next_move_dir_add = 0
+ next_move_dir_sub = 0
var/old_move_delay = move_delay
move_delay = world.time+world.tick_lag //this is here because Move() can now be called mutiple times per tick
if(!mob || !mob.loc)
return FALSE
- var/oldloc = mob.loc
+ if(!n || !direct)
+ return FALSE
if(mob.notransform)
return FALSE //This is sota the goto stop mobs from moving var
if(mob.control_object)
return Move_object(direct)
if(!isliving(mob))
- return mob.Move(n,direct)
+ return mob.Move(n, direct)
if(mob.stat == DEAD)
mob.ghostize()
return FALSE
@@ -159,26 +81,32 @@
if(!mob.Process_Spacemove(direct))
return FALSE
-
//We are now going to move
- var/delay = mob.movement_delay()
- if(old_move_delay + (delay*MOVEMENT_DELAY_BUFFER_DELTA) + MOVEMENT_DELAY_BUFFER > world.time)
- move_delay = old_move_delay + delay
+ var/add_delay = mob.movement_delay()
+ if(old_move_delay + (add_delay*MOVEMENT_DELAY_BUFFER_DELTA) + MOVEMENT_DELAY_BUFFER > world.time)
+ move_delay = old_move_delay
else
- move_delay = delay + world.time
+ move_delay = world.time
+ var/oldloc = mob.loc
if(mob.confused)
+ var/newdir = 0
if(mob.confused > 40)
- step(mob, pick(GLOB.cardinals))
+ newdir = pick(GLOB.alldirs)
else if(prob(mob.confused * 1.5))
- step(mob, angle2dir(dir2angle(direct) + pick(90, -90)))
+ newdir = angle2dir(dir2angle(direct) + pick(90, -90))
else if(prob(mob.confused * 3))
- step(mob, angle2dir(dir2angle(direct) + pick(45, -45)))
- else
- step(mob, direct)
- else
- . = ..()
+ newdir = angle2dir(dir2angle(direct) + pick(45, -45))
+ if(newdir)
+ direct = newdir
+ n = get_step(mob, direct)
+ . = ..()
+
+ if((direct & (direct - 1)) && mob.loc == n) //moved diagonally successfully
+ add_delay *= 2
+ if(mob.loc != oldloc)
+ move_delay += add_delay
if(.) // If mob is null here, we deserve the runtime
if(mob.throwing)
mob.throwing.finalize(FALSE)
@@ -186,7 +114,7 @@
if(LAZYLEN(mob.user_movement_hooks))
for(var/obj/O in mob.user_movement_hooks)
O.intercept_user_move(direct, mob, n, oldloc)
-
+
var/atom/movable/P = mob.pulling
if(P && !ismob(P) && P.density)
mob.dir = turn(mob.dir, 180)
diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm
index 1ee7f27452..ef1523bf43 100644
--- a/code/modules/mob/say.dm
+++ b/code/modules/mob/say.dm
@@ -5,7 +5,8 @@
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "Speech is currently admin-disabled.")
return
- usr.say(message)
+ if(message)
+ say(message)
/mob/verb/whisper_verb(message as text)
diff --git a/code/modules/mob/say_readme.dm b/code/modules/mob/say_readme.dm
index a4f85c1422..00e0f66246 100644
--- a/code/modules/mob/say_readme.dm
+++ b/code/modules/mob/say_readme.dm
@@ -11,7 +11,7 @@ This rewrite was needed, but is far from perfect. Report any bugs you come acros
Radio code, while very much related to saycode, is not something I wanted to touch, so the code related to that may be messy.
If you came here to see how to use saycode, all you will ever really need to call is say(message).
-To have things react when other things speak around them, add the HEAR_1 flag to their flags_1 variable and
+To have things react when other things speak around them, add the HEAR_1 flag to their flags variable and
override their Hear() proc.
=======================PROCS & VARIABLES=======================
@@ -43,7 +43,7 @@ global procs
Attaches span classes around input.
/atom/movable
- flags_1
+ flags
The HEAR_1 flag determines whether something is a hearer or not.
Hear() is only called on procs with this flag.
diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm
index 534307f727..c501984de8 100644
--- a/code/modules/mob/transform_procs.dm
+++ b/code/modules/mob/transform_procs.dm
@@ -58,7 +58,6 @@
O.suiciding = suiciding
if(hellbound)
O.hellbound = hellbound
- O.loc = loc
O.a_intent = INTENT_HARM
//keep viruses?
@@ -113,7 +112,7 @@
var/obj/item/bodypart/chest/torso = O.get_bodypart("chest")
if(cavity_object)
torso.cavity_item = cavity_object //cavity item is given to the new chest
- cavity_object.loc = O
+ cavity_object.forceMove(O)
for(var/missing_zone in missing_bodyparts_zones)
var/obj/item/bodypart/BP = O.get_bodypart(missing_zone)
@@ -220,8 +219,6 @@
if(hellbound)
O.hellbound = hellbound
- O.loc = loc
-
//keep viruses?
if (tr_flags & TR_KEEPVIRUS)
O.viruses = viruses
@@ -276,7 +273,7 @@
var/obj/item/bodypart/chest/torso = get_bodypart("chest")
if(cavity_object)
torso.cavity_item = cavity_object //cavity item is given to the new chest
- cavity_object.loc = O
+ cavity_object.forceMove(O)
for(var/missing_zone in missing_bodyparts_zones)
var/obj/item/bodypart/BP = O.get_bodypart(missing_zone)
@@ -401,7 +398,6 @@
R.mmi.brainmob.real_name = real_name //the name of the brain inside the cyborg is the robotized human's name.
R.mmi.brainmob.name = real_name
- R.loc = loc
R.job = "Cyborg"
R.notify_ai(NEW_BORG)
@@ -472,11 +468,7 @@
qdel(src)
/mob/proc/become_overmind(starting_points = 60)
- var/turf/T = get_turf(loc) //just to avoid messing up in lockers
- var/area/A = get_area(T)
- if(((A && !A.blob_allowed) || !(T.z in GLOB.station_z_levels)) && LAZYLEN(GLOB.blobstart))
- T = get_turf(pick(GLOB.blobstart))
- var/mob/camera/blob/B = new /mob/camera/blob(T, starting_points)
+ var/mob/camera/blob/B = new /mob/camera/blob(get_turf(src), starting_points)
B.key = key
. = B
qdel(src)
diff --git a/code/modules/modular_computers/computers/item/laptop_presets.dm b/code/modules/modular_computers/computers/item/laptop_presets.dm
index 78270fb0d9..a1f5f7e37f 100644
--- a/code/modules/modular_computers/computers/item/laptop_presets.dm
+++ b/code/modules/modular_computers/computers/item/laptop_presets.dm
@@ -1,4 +1,4 @@
-/obj/item/device/modular_computer/laptop/preset/New()
+/obj/item/device/modular_computer/laptop/preset/Initialize()
. = ..()
install_component(new /obj/item/computer_hardware/processor_unit/small)
install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer))
diff --git a/code/modules/modular_computers/computers/item/tablet_presets.dm b/code/modules/modular_computers/computers/item/tablet_presets.dm
index c8f9282380..21080e593f 100644
--- a/code/modules/modular_computers/computers/item/tablet_presets.dm
+++ b/code/modules/modular_computers/computers/item/tablet_presets.dm
@@ -3,7 +3,7 @@
/obj/item/device/modular_computer/tablet/preset/cheap
desc = "A low-end tablet often seen among low ranked station personnel."
-/obj/item/device/modular_computer/tablet/preset/cheap/New()
+/obj/item/device/modular_computer/tablet/preset/cheap/Initialize()
. = ..()
install_component(new /obj/item/computer_hardware/processor_unit/small)
install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer/micro))
@@ -11,7 +11,7 @@
install_component(new /obj/item/computer_hardware/network_card)
// Alternative version, an average one, for higher ranked positions mostly
-/obj/item/device/modular_computer/tablet/preset/advanced/New()
+/obj/item/device/modular_computer/tablet/preset/advanced/Initialize()
. = ..()
install_component(new /obj/item/computer_hardware/processor_unit/small)
install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer))
@@ -20,7 +20,7 @@
install_component(new /obj/item/computer_hardware/card_slot)
install_component(new /obj/item/computer_hardware/printer/mini)
-/obj/item/device/modular_computer/tablet/preset/cargo/New()
+/obj/item/device/modular_computer/tablet/preset/cargo/Initialize()
. = ..()
install_component(new /obj/item/computer_hardware/processor_unit/small)
install_component(new /obj/item/computer_hardware/battery(src, /obj/item/stock_parts/cell/computer))
diff --git a/code/modules/modular_computers/hardware/hard_drive.dm b/code/modules/modular_computers/hardware/hard_drive.dm
index 62d8ff5d86..54e26d2e63 100644
--- a/code/modules/modular_computers/hardware/hard_drive.dm
+++ b/code/modules/modular_computers/hardware/hard_drive.dm
@@ -120,9 +120,9 @@
stored_files = null
return ..()
-/obj/item/computer_hardware/hard_drive/New()
+/obj/item/computer_hardware/hard_drive/Initialize()
+ . = ..()
install_default_programs()
- ..()
/obj/item/computer_hardware/hard_drive/advanced
diff --git a/code/modules/ninja/ninja_event.dm b/code/modules/ninja/ninja_event.dm
index 1656a43505..b26d01d880 100644
--- a/code/modules/ninja/ninja_event.dm
+++ b/code/modules/ninja/ninja_event.dm
@@ -95,7 +95,7 @@ Contents:
var/datum/mind/Mind = new /datum/mind(key)
Mind.assigned_role = "Space Ninja"
Mind.special_role = "Space Ninja"
- SSticker.mode.traitors |= Mind //Adds them to current traitor list. Which is really the extra antagonist list.
+ SSticker.mode.traitors |= Mind //Adds them to current traitor list. TODO : Remove this in admin tools refeactor.
return Mind
diff --git a/code/modules/ninja/suit/suit.dm b/code/modules/ninja/suit/suit.dm
index 82c7dfa0bf..4e7ad477e2 100644
--- a/code/modules/ninja/suit/suit.dm
+++ b/code/modules/ninja/suit/suit.dm
@@ -58,8 +58,8 @@ Contents:
/obj/item/clothing/suit/space/space_ninja/get_cell()
return cell
-/obj/item/clothing/suit/space/space_ninja/New()
- ..()
+/obj/item/clothing/suit/space/space_ninja/Initialize()
+ . = ..()
//Spark Init
spark_system = new
@@ -97,7 +97,7 @@ Contents:
if(!istype(H))
return FALSE
if(!is_ninja(H))
- to_chat(H, "fTaL RRoR: 382200-*#00CDE RED\nUNAU?HORIZED US DETC???eD\nCoMMNCING SUB-R0U?IN3 13...\nTRMInATING U-U-USR...")
+ to_chat(H, "fÄTaL ÈÈRRoR: 382200-*#00CÖDE RED\nUNAUHORIZED USÈ DETÈCeD\nCoMMÈNCING SUB-R0UIN3 13...\nTÈRMInATING U-U-USÈR...")
H.gib()
return FALSE
if(!istype(H.head, /obj/item/clothing/head/helmet/space/space_ninja))
diff --git a/code/modules/ninja/suit/suit_initialisation.dm b/code/modules/ninja/suit/suit_initialisation.dm
index e19e67404d..4b159557bc 100644
--- a/code/modules/ninja/suit/suit_initialisation.dm
+++ b/code/modules/ninja/suit/suit_initialisation.dm
@@ -28,7 +28,7 @@
/obj/item/clothing/suit/space/space_ninja/proc/ninitialize_four(delay, mob/living/carbon/human/U)
if(U.stat == DEAD|| U.health <= 0)
- to_chat(U, "F?AL �Rr�R: 344--93#�&&21 BR��N |/|/aV� PATT$RN RED\nA-A-aB�rT�NG...")
+ to_chat(U, "FÄAL �Rr�R: 344--93#�&&21 BR��N |/|/aV� PATT$RN RED\nA-A-aB�rT�NG...")
unlock_suit()
s_busy = FALSE
return
diff --git a/code/modules/orbit/orbit.dm b/code/modules/orbit/orbit.dm
index 89d1d89e58..0293886fd4 100644
--- a/code/modules/orbit/orbit.dm
+++ b/code/modules/orbit/orbit.dm
@@ -43,6 +43,10 @@
if (!orbiter.orbiting) //admin wants to stop the orbit.
orbiter.orbiting = src //set it back to us first
orbiter.stop_orbit()
+ var/atom/movable/AM = orbiting
+ if(istype(AM) && AM.orbiting && AM.orbiting.orbiting == orbiter)
+ orbiter.stop_orbit()
+ return
lastprocess = world.time
if (!targetloc)
targetloc = get_turf(orbiting)
@@ -54,7 +58,7 @@
lastloc = orbiter.loc
for(var/other_orbit in orbiter.orbiters)
var/datum/orbit/OO = other_orbit
- if(OO == src)
+ if(OO == src || OO.orbiter == orbiting)
continue
OO.Check(targetloc)
diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm
index d9d220b0ef..e8487b3344 100644
--- a/code/modules/paperwork/clipboard.dm
+++ b/code/modules/paperwork/clipboard.dm
@@ -73,7 +73,7 @@
if(href_list["pen"])
if(haspen)
- haspen.loc = usr.loc
+ haspen.forceMove(usr.loc)
usr.put_in_hands(haspen)
haspen = null
@@ -96,7 +96,7 @@
if(href_list["remove"])
var/obj/item/P = locate(href_list["remove"])
if(istype(P) && P.loc == src)
- P.loc = usr.loc
+ P.forceMove(usr.loc)
usr.put_in_hands(P)
if(P == toppaper)
toppaper = null
diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm
index 0d963d4be8..fed93fabd3 100644
--- a/code/modules/paperwork/filingcabinet.dm
+++ b/code/modules/paperwork/filingcabinet.dm
@@ -187,7 +187,6 @@ GLOBAL_LIST_EMPTY(employmentCabinets)
/obj/structure/filingcabinet/employment/Initialize()
. = ..()
GLOB.employmentCabinets += src
- return ..()
/obj/structure/filingcabinet/employment/Destroy()
GLOB.employmentCabinets -= src
@@ -199,8 +198,9 @@ GLOBAL_LIST_EMPTY(employmentCabinets)
var/datum/data/record/G = record
if(!G)
continue
- if(G.fields["reference"])
- addFile(G.fields["reference"])
+ var/datum/mind/M = G.fields["mindref"]
+ if(M && ishuman(M.current))
+ addFile(M.current)
/obj/structure/filingcabinet/employment/proc/addFile(mob/living/carbon/human/employee)
diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm
index 3221a2c8db..c81ab37591 100644
--- a/code/modules/paperwork/folders.dm
+++ b/code/modules/paperwork/folders.dm
@@ -62,7 +62,7 @@
if(href_list["remove"])
var/obj/item/I = locate(href_list["remove"])
if(istype(I) && I.loc == src)
- I.loc = usr.loc
+ I.forceMove(usr.loc)
usr.put_in_hands(I)
if(href_list["read"])
diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm
index 1fb1846f4c..3dd47a0dab 100644
--- a/code/modules/paperwork/paper.dm
+++ b/code/modules/paperwork/paper.dm
@@ -374,4 +374,3 @@
/obj/item/paper/crumpled/bloody
icon_state = "scrap_bloodied"
-
diff --git a/code/modules/paperwork/paper_cutter.dm b/code/modules/paperwork/paper_cutter.dm
index fbf6e7b6e4..df69e9548a 100644
--- a/code/modules/paperwork/paper_cutter.dm
+++ b/code/modules/paperwork/paper_cutter.dm
@@ -12,8 +12,8 @@
pass_flags = PASSTABLE
-/obj/item/papercutter/New()
- ..()
+/obj/item/papercutter/Initialize()
+ . = ..()
storedcutter = new /obj/item/hatchet/cutterblade(src)
update_icon()
@@ -111,8 +111,8 @@
resistance_flags = FLAMMABLE
max_integrity = 50
-/obj/item/paperslip/New()
- ..()
+/obj/item/paperslip/Initialize()
+ . = ..()
pixel_x = rand(-5, 5)
pixel_y = rand(-5, 5)
diff --git a/code/modules/paperwork/paper_premade.dm b/code/modules/paperwork/paper_premade.dm
index 7d0d2d8cef..dbf13367ed 100644
--- a/code/modules/paperwork/paper_premade.dm
+++ b/code/modules/paperwork/paper_premade.dm
@@ -14,8 +14,7 @@
/obj/item/paper/guides/jobs/hydroponics
name = "paper- 'Greetings from Billy Bob'"
- info = "Hey fellow botanist! \n \nI didn't trust the station folk so I left \na couple of weeks ago. But here's some \ninstructions on how to operate things here. \nYou can grow plants and each iteration they become \nstronger, more potent and have better yield, if you \nknow which ones to pick. Use your botanist's analyzer \nfor that. You can turn harvested plants into seeds \nat the seed extractor, and replant them for better stuff! \nSometimes if the weed level gets high in the tray \nmutations into different mushroom or weed species have \nbeen witnessed. On the rare occassion even weeds mutate! \n \nEither way, have fun! \n \nBest regards, \nBilly Bob Johnson. \n \nPS. \nHere's a few tips: \nIn nettles, potency = damage \nIn amanitas, potency = deadliness + side effect \nIn Liberty caps, potency = drug power + effect \nIn chilis, potency = heat \nNutrients keep mushrooms alive! \nWater keeps weeds such as nettles alive! \nAll other plants need both."
-
+ info = "Hey fellow botanist! \n \nI didn't trust the station folk so I left \na couple of weeks ago. But here's some \ninstructions on how to operate things here. \nYou can grow plants and each iteration they become \nstronger, more potent and have better yield, if you \nknow which ones to pick. Use your botanist's analyzer \nfor that. You can turn harvested plants into seeds \nat the seed extractor, and replant them for better stuff! \nSometimes if the weed level gets high in the tray \nmutations into different mushroom or weed species have \nbeen witnessed. On the rare occasion even weeds mutate! \n \nEither way, have fun! \n \nBest regards, \nBilly Bob Johnson. \n \nPS. \nHere's a few tips: \nIn nettles, potency = damage \nIn amanitas, potency = deadliness + side effect \nIn Liberty caps, potency = drug power + effect \nIn chilies, potency = heat \nNutrients keep mushrooms alive! \nWater keeps weeds such as nettles alive! \nAll other plants need both."
/obj/item/paper/fluff/jobs/security/beepsky_mom
name = "Note from Beepsky's Mom"
@@ -27,7 +26,7 @@
/obj/item/paper/guides/jobs/security/labor_camp
name = "Labor Camp Operating Guide"
- info = "Labor Camp Facility Operation Guide
Hello there, proud operator of an NT-Sec Prisoner Rehabilitation Center. A solution to rising crime rates and falling productivity, these facilities are specifically designed for the safe, productive imprisonment of your most dangerous criminals.
To press a long-term prisoner into the service of the station, replace his equipment with prisoners' garb at one of the prison lockers, as per normal operating procedure. Before assigning a prisoner his ID, insert the ID into a prisoner management console and assign the prisoner a quota, based on the severity of his crime. A single sheet of most materials produces five points for the prisoner, and points can be expected to be produced at a rate of about 100 per minute, though punishments as severe as forced labor should be reserved for serious crimes of sentences not less than five minutes long. Once you have prepared the prisoner, place him in the secure northern half of the labor shuttle, and send him to the station. Once he meets his quota by feeding sheets to the stacker, he will be allowed to return to the station, and will be able to open the secure door to the prisoner release area.
In the case of dangerous prisoners, surveilance may be needed. To that end, there is a prisoner monitoring room on the mining station, equipped with a remote flasher and a lockdown button. The mine itself is patrolled by a securibot, so the nearby security records console can also be used to secure hostile prisoners on the mine."
+ info = "Labor Camp Facility Operation Guide
Hello there, proud operator of an NT-Sec Prisoner Rehabilitation Center. A solution to rising crime rates and falling productivity, these facilities are specifically designed for the safe, productive imprisonment of your most dangerous criminals.
To press a long-term prisoner into the service of the station, replace his equipment with prisoners' garb at one of the prison lockers, as per normal operating procedure. Before assigning a prisoner his ID, insert the ID into a prisoner management console and assign the prisoner a quota, based on the severity of his crime. A single sheet of most materials produces five points for the prisoner, and points can be expected to be produced at a rate of about 100 per minute, though punishments as severe as forced labor should be reserved for serious crimes of sentences not less than five minutes long. Once you have prepared the prisoner, place him in the secure northern half of the labor shuttle, and send him to the station. Once he meets his quota by feeding sheets to the stacker, he will be allowed to return to the station, and will be able to open the secure door to the prisoner release area.
In the case of dangerous prisoners, surveillance may be needed. To that end, there is a prisoner monitoring room on the mining station, equipped with a remote flasher and a lockdown button. The mine itself is patrolled by a securibot, so the nearby security records console can also be used to secure hostile prisoners on the mine."
/obj/item/paper/guides/jobs/security/range
name = "paper- Firing Range Instructions"
@@ -35,7 +34,7 @@
/obj/item/paper/fluff/jobs/jobs
name = "paper- 'Job Information'"
- info = "Information on all formal jobs that can be assigned on Space Station 13 can be found on this document. \nThe data will be in the following form. \nGenerally lower ranking positions come first in this list. \n \nJob Name general access>lab access-engine access-systems access (atmosphere control) \n\tJob Description \nJob Duties (in no particular order) \nTips (where applicable) \n \nResearch Assistant 1>1-0-0 \n\tThis is probably the lowest level position. Anyone who enters the space station after the initial job\nassignment will automatically receive this position. Access with this is restricted. Head of Personnel should\nappropriate the correct level of assistance. \n1. Assist the researchers. \n2. Clean up the labs. \n3. Prepare materials. \n \nStaff Assistant 2>0-0-0 \n\tThis position assists the security officer in his duties. The staff assisstants should primarily br\npatrolling the ship waiting until they are needed to maintain ship safety.\n(Addendum: Updated/Elevated Security Protocols admit issuing of low level weapons to security personnel) \n1. Patrol ship/Guard key areas \n2. Assist security officer \n3. Perform other security duties. \n \nTechnical Assistant 1>0-0-1 \n\tThis is yet another low level position. The technical assistant helps the engineer and the statian\ntechnician with the upkeep and maintenance of the station. This job is very important because it usually\ngets to be a heavy workload on station technician and these helpers will alleviate that. \n1. Assist Station technician and Engineers. \n2. Perform general maintenance of station. \n3. Prepare materials. \n \nMedical Assistant 1>1-0-0 \n\tThis is the fourth position yet it is slightly less common. This position doesn't have much power\noutside of the med bay. Consider this position like a nurse who helps to upkeep medical records and the\nmaterials (filling syringes and checking vitals) \n1. Assist the medical personnel. \n2. Update medical files. \n3. Prepare materials for medical operations. \n \nResearch Technician 2>3-0-0 \n\tThis job is primarily a step up from research assistant. These people generally do not get their own lab\nbut are more hands on in the experimentation process. At this level they are permitted to work as consultants to\nthe others formally. \n1. Inform superiors of research. \n2. Perform research alongside of official researchers. \n \nDetective 3>2-0-0 \n\tThis job is in most cases slightly boring at best. Their sole duty is to\nperform investigations of crine scenes and analysis of the crime scene. This\nalleviates SOME of the burden from the security officer. This person's duty\nis to draw conclusions as to what happened and testify in court. Said person\nalso should stroe the evidence ly. \n1. Perform crime-scene investigations/draw conclusions. \n2. Store and catalogue evidence properly. \n3. Testify to superiors/inquieries on findings. \n \nStation Technician 2>0-2-3 \n\tPeople assigned to this position must work to make sure all the systems aboard Space Station 13 are operable.\nThey should primarily work in the computer lab and repairing faulty equipment. They should work with the\natmospheric technician. \n1. Maintain SS13 systems. \n2. Repair equipment. \n \nAtmospheric Technician 3>0-0-4 \n\tThese people should primarily work in the atmospheric control center and lab. They have the very important\njob of maintaining the delicate atmosphere on SS13. \n1. Maintain atmosphere on SS13 \n2. Research atmospheres on the space station. (safely please!) \n \nEngineer 2>1-3-0 \n\tPeople working as this should generally have detailed knowledge as to how the propulsion systems on SS13\nwork. They are one of the few classes that have unrestricted access to the engine area. \n1. Upkeep the engine. \n2. Prevent fires in the engine. \n3. Maintain a safe orbit. \n \nMedical Researcher 2>5-0-0 \n\tThis position may need a little clarification. Their duty is to make sure that all experiments are safe and\nto conduct experiments that may help to improve the station. They will be generally idle until a new laboratory\nis constructed. \n1. Make sure the station is kept safe. \n2. Research medical properties of materials studied of Space Station 13. \n \nScientist 2>5-0-0 \n\tThese people study the properties, particularly the toxic properties, of materials handled on SS13.\nTechnically they can also be called Plasma Technicians as plasma is the material they routinly handle. \n1. Research plasma \n2. Make sure all plasma is properly handled. \n \nMedical Doctor (Officer) 2>0-0-0 \n\tPeople working this job should primarily stay in the medical area. They should make sure everyone goes to\nthe medical bay for treatment and examination. Also they should make sure that medical supplies are kept in\norder. \n1. Heal wounded people. \n2. Perform examinations of all personnel. \n3. Monitor usage of medical equipment. \n \nSecurity Officer 3>0-0-0 \n\tThese people should attempt to keep the peace inside the station and make sure the station is kept safe. One\nside duty is to assist in repairing the station. They also work like general maintenance personnel. They are not\ngiven a weapon and must use their own resources. \n(Addendum: Updated/Elevated Security Protocols admit issuing of weapons to security personnel) \n1. Maintain order. \n2. Assist others. \n3. Repair structural problems. \n \nHead of Security 4>5-2-2 \n\tPeople assigned as Head of Security should issue orders to the security staff. They should\nalso carefully moderate the usage of all security equipment. All security matters should be reported to this person. \n1. Oversee security. \n2. Assign patrol duties. \n3. Protect the station and staff. \n \nHead of Personnel 4>4-2-2 \n\tPeople assigned as head of personnel will find themselves moderating all actions done by personnel. \nAlso they have the ability to assign jobs and access levels. \n1. Assign duties. \n2. Moderate personnel. \n3. Moderate research. \n \nCaptain 5>5-5-5 (unrestricted station wide access) \n\tThis is the highest position youi can aquire on Space Station 13. They are allowed anywhere inside the\nspace station and therefore should protect their ID card. They also have the ability to assign positions\nand access levels. They should not abuse their power. \n1. Assign all positions on SS13 \n2. Inspect the station for any problems. \n3. Perform administrative duties. \n"
+ info = "Information on all formal jobs that can be assigned on Space Station 13 can be found on this document. \nThe data will be in the following form. \nGenerally lower ranking positions come first in this list. \n \nJob Name general access>lab access-engine access-systems access (atmosphere control) \n\tJob Description \nJob Duties (in no particular order) \nTips (where applicable) \n \nResearch Assistant 1>1-0-0 \n\tThis is probably the lowest level position. Anyone who enters the space station after the initial job\nassignment will automatically receive this position. Access with this is restricted. Head of Personnel should\nappropriate the correct level of assistance. \n1. Assist the researchers. \n2. Clean up the labs. \n3. Prepare materials. \n \nStaff Assistant 2>0-0-0 \n\tThis position assists the security officer in his duties. The staff assistants should primarily br\npatrolling the ship waiting until they are needed to maintain ship safety.\n(Addendum: Updated/Elevated Security Protocols admit issuing of low level weapons to security personnel) \n1. Patrol ship/Guard key areas \n2. Assist security officer \n3. Perform other security duties. \n \nTechnical Assistant 1>0-0-1 \n\tThis is yet another low level position. The technical assistant helps the engineer and the station\ntechnician with the upkeep and maintenance of the station. This job is very important because it usually\ngets to be a heavy workload on station technician and these helpers will alleviate that. \n1. Assist Station technician and Engineers. \n2. Perform general maintenance of station. \n3. Prepare materials. \n \nMedical Assistant 1>1-0-0 \n\tThis is the fourth position yet it is slightly less common. This position doesn't have much power\noutside of the med bay. Consider this position like a nurse who helps to upkeep medical records and the\nmaterials (filling syringes and checking vitals) \n1. Assist the medical personnel. \n2. Update medical files. \n3. Prepare materials for medical operations. \n \nResearch Technician 2>3-0-0 \n\tThis job is primarily a step up from research assistant. These people generally do not get their own lab\nbut are more hands on in the experimentation process. At this level they are permitted to work as consultants to\nthe others formally. \n1. Inform superiors of research. \n2. Perform research alongside of official researchers. \n \nDetective 3>2-0-0 \n\tThis job is in most cases slightly boring at best. Their sole duty is to\nperform investigations of crime scenes and analysis of the crime scene. This\nalleviates SOME of the burden from the security officer. This person's duty\nis to draw conclusions as to what happened and testify in court. Said person\nalso should store the evidence ly. \n1. Perform crime-scene investigations/draw conclusions. \n2. Store and catalogue evidence properly. \n3. Testify to superiors/inquiries on findings. \n \nStation Technician 2>0-2-3 \n\tPeople assigned to this position must work to make sure all the systems aboard Space Station 13 are operable.\nThey should primarily work in the computer lab and repairing faulty equipment. They should work with the\natmospheric technician. \n1. Maintain SS13 systems. \n2. Repair equipment. \n \nAtmospheric Technician 3>0-0-4 \n\tThese people should primarily work in the atmospheric control center and lab. They have the very important\njob of maintaining the delicate atmosphere on SS13. \n1. Maintain atmosphere on SS13 \n2. Research atmospheres on the space station. (safely please!) \n \nEngineer 2>1-3-0 \n\tPeople working as this should generally have detailed knowledge as to how the propulsion systems on SS13\nwork. They are one of the few classes that have unrestricted access to the engine area. \n1. Upkeep the engine. \n2. Prevent fires in the engine. \n3. Maintain a safe orbit. \n \nMedical Researcher 2>5-0-0 \n\tThis position may need a little clarification. Their duty is to make sure that all experiments are safe and\nto conduct experiments that may help to improve the station. They will be generally idle until a new laboratory\nis constructed. \n1. Make sure the station is kept safe. \n2. Research medical properties of materials studied of Space Station 13. \n \nScientist 2>5-0-0 \n\tThese people study the properties, particularly the toxic properties, of materials handled on SS13.\nTechnically they can also be called Plasma Technicians as plasma is the material they routinely handle. \n1. Research plasma \n2. Make sure all plasma is properly handled. \n \nMedical Doctor (Officer) 2>0-0-0 \n\tPeople working this job should primarily stay in the medical area. They should make sure everyone goes to\nthe medical bay for treatment and examination. Also they should make sure that medical supplies are kept in\norder. \n1. Heal wounded people. \n2. Perform examinations of all personnel. \n3. Monitor usage of medical equipment. \n \nSecurity Officer 3>0-0-0 \n\tThese people should attempt to keep the peace inside the station and make sure the station is kept safe. One\nside duty is to assist in repairing the station. They also work like general maintenance personnel. They are not\ngiven a weapon and must use their own resources. \n(Addendum: Updated/Elevated Security Protocols admit issuing of weapons to security personnel) \n1. Maintain order. \n2. Assist others. \n3. Repair structural problems. \n \nHead of Security 4>5-2-2 \n\tPeople assigned as Head of Security should issue orders to the security staff. They should\nalso carefully moderate the usage of all security equipment. All security matters should be reported to this person. \n1. Oversee security. \n2. Assign patrol duties. \n3. Protect the station and staff. \n \nHead of Personnel 4>4-2-2 \n\tPeople assigned as head of personnel will find themselves moderating all actions done by personnel. \nAlso they have the ability to assign jobs and access levels. \n1. Assign duties. \n2. Moderate personnel. \n3. Moderate research. \n \nCaptain 5>5-5-5 (unrestricted station wide access) \n\tThis is the highest position you can acquire on Space Station 13. They are allowed anywhere inside the\nspace station and therefore should protect their ID card. They also have the ability to assign positions\nand access levels. They should not abuse their power. \n1. Assign all positions on SS13 \n2. Inspect the station for any problems. \n3. Perform administrative duties. \n"
/obj/item/paper/fluff/jobs/mining/smelter_notice
name = "paper- Smelting Operations Closed"
@@ -49,60 +48,24 @@
name = "paper- 'Chemical Information'"
info = "Known Onboard Toxins: \n\tGrade A Semi-Liquid Plasma: \n\t\tHighly poisonous. You cannot sustain concentrations above 15 units. \n\t\tA gas mask fails to filter plasma after 50 units. \n\t\tWill attempt to diffuse like a gas. \n\t\tFiltered by scrubbers. \n\t\tThere is a bottled version which is very different \n\t\t\tfrom the version found in canisters! \n \n\t\tWARNING: Highly Flammable. Keep away from heat sources \n\t\texcept in an enclosed fire area! \n\t\tWARNING: It is a crime to use this without authorization. \nKnown Onboard Anti-Toxin: \n\tAnti-Toxin Type 01P: Works against Grade A Plasma. \n\t\tBest if injected directly into bloodstream. \n\t\tA full injection is in every regular Med-Kit. \n\t\tSpecial toxin Kits hold around 7. \n \nKnown Onboard Chemicals (other): \n\tRejuvenation T#001: \n\t\tEven 1 unit injected directly into the bloodstream \n\t\t\twill cure unconscious and sleep toxins. \n\t\tIf administered to a dying patient it will prevent \n\t\t\tfurther damage for about units*3 seconds. \n\t\t\tit will not cure them or allow them to be cured. \n\t\tIt can be administered to a non-dying patient \n\t\t\tbut the chemicals disappear just as fast. \n\tMorphine T#054: \n\t\t5 units will induce precisely 1 minute of sleep. \n\t\t\tThe effect are cumulative. \n\t\tWARNING: It is a crime to use this without authorization"
+
/*
* Stations
*/
-////////// Cere fluff
-/obj/item/paper/fluff/stations/cere/abandoned_dock
- name = "Disclaimer Notice"
- info = "This station needs clearing out within the next few weeks as construction is almost complete and NT expects most of the equipment off-site before then. Throw most of the shit in here for now and we'll come back later with a pod to haul the heavier stuff. Shouldn't be too big of an issue."
-
-/obj/item/paper/fluff/stations/cere/janitor
- name = "Janitor Notice"
- info = "You got a big job ahead of you, pal. This is a big station, lots of floors and assholes to dirty said floors without any thought for you. It might not be a bad idea to check on the external waste belts every now and again to make sure some foriegn object hasn't clogged the disposal loop, either."
-
-/obj/item/paper/fluff/stations/cere/gateway
- name = "NOTICE - GATEWAY STATUS"
- info = "
Nanotrasen Exploration and Colonization Program
Due to recent shutdowns of the Exploration and Colonization department shortly after this gateway was delivered on-site during station construction, this room has been condemmed and an engineering team will be on-site within the next few months to recollect the gate. Thank you for your cooperation."
-
-/obj/item/paper/fluff/stations/cere/journal/journal
- name = "Journal Log"
- info = "
2XXX - 2nd Trimestor
I hide in here, away from the masses, not like it matters much considering how fucking huge this place is. "
-
-/obj/item/paper/fluff/stations/cere/journal/journal_2
- name = "Journal Log 2"
- info = "
2XXX - 3rd Trimestor
I hear strange whispers from the halls, longing for blood. Something isn't right here. Why did they transfer us here to work in the first place? "
-
-/obj/item/paper/crumpled/stations/cere/empty_station
- info = "I can't be here for much longer, this station is too empty for its own good. Something is wrong..."
-
-/obj/item/paper/crumpled/bloody/hop
- info = "...THE HOPLINE CALLS...IT THIRSTS FOR BLOOD...I MUST GO..."
-
-/obj/item/paper/crumpled/stations/cere/rocks1
- info = "...SOMETHING IN THE ROCKS, IT WATCHES US ALL..."
-
-/obj/item/paper/crumpled/stations/cere/rocks2
- info = "...THEY SENT US HERE FOR A REASON...TERRIBLE..."
-
-/obj/item/paper/crumpled/stations/cere/rocks3
- info = "...EMPTY HALLS...USELESS SPACE..."
-
-
-/////////// Centcom
+/////////// CentCom
/obj/item/paper/fluff/stations/centcom/disk_memo
name = "memo"
info = "GET DAT FUKKEN DISK"
/obj/item/paper/fluff/stations/centcom/broken_evac
- info = "Due to circumstances beyond our control, your Emergency Evacuation Shuttle is out of service.
We apologise for the inconvinience this may cause you.
Please enjoy the use of this complementary book.
Sincerely, Centcom Operations Demolitions Examination Retribution Bugfixing Underlining Services"
+ info = "Due to circumstances beyond our control, your Emergency Evacuation Shuttle is out of service.
We apologize for the inconvenience this may cause you.
Please enjoy the use of this complementary book.
Sincerely, CentCom Operations Demolitions Examination Retribution Bugfixing Underlining Services"
/obj/item/paper/fluff/stations/centcom/bulletin
name = "paper- 'Official Bulletin'"
- info = " Centcom Security Port Division Official Bulletin
Inspector, There is an emergency shuttle arriving today.
Approval is restricted to Nanotrasen employees only. Deny all other entrants.
Centcom Port Commissioner"
+ info = " CentCom Security Port Division Official Bulletin
Inspector, There is an emergency shuttle arriving today.
Approval is restricted to Nanotrasen employees only. Deny all other entrants.
CentCom Port Commissioner"
/////////// Lavaland
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 0826a49c7c..68be3e1462 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -23,6 +23,7 @@
throw_range = 7
materials = list(MAT_METAL=10)
pressure_resistance = 2
+ grind_results = list("iron" = 2, "iodine" = 1)
var/colour = "black" //what colour the ink is!
var/traitor_unlock_degrees = 0
var/degrees = 0
@@ -174,12 +175,12 @@
reagents.trans_to(M, reagents.total_volume)
-/obj/item/pen/sleepy/New()
+/obj/item/pen/sleepy/Initialize()
+ . = ..()
create_reagents(45)
reagents.add_reagent("chloralhydrate2", 20)
reagents.add_reagent("mutetoxin", 15)
reagents.add_reagent("tirizene", 10)
- ..()
/*
* (Alan) Edaggers
diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm
index 20038f5745..e065fd8c03 100644
--- a/code/modules/paperwork/photocopier.dm
+++ b/code/modules/paperwork/photocopier.dm
@@ -247,10 +247,10 @@
/obj/machinery/photocopier/proc/remove_photocopy(obj/item/O, mob/user)
if(!issilicon(user)) //surprised this check didn't exist before, putting stuff in AI's hand is bad
- O.loc = user.loc
+ O.forceMove(user.loc)
user.put_in_hands(O)
else
- O.loc = src.loc
+ O.forceMove(drop_location())
to_chat(user, "You take [O] out of [src].")
/obj/machinery/photocopier/attackby(obj/item/O, mob/user, params)
@@ -338,16 +338,16 @@
else
user.visible_message("[user] puts [target] onto the photocopier!", "You put [target] onto the photocopier.")
- target.loc = get_turf(src)
+ target.forceMove(drop_location())
ass = target
if(photocopy)
- photocopy.loc = src.loc
+ photocopy.forceMove(drop_location())
visible_message("[photocopy] is shoved out of the way by [ass]!")
photocopy = null
else if(copy)
- copy.loc = src.loc
+ copy.forceMove(drop_location())
visible_message("[copy] is shoved out of the way by [ass]!")
copy = null
updateUsrDialog()
@@ -391,5 +391,6 @@
/obj/item/device/toner
name = "toner cartridge"
icon_state = "tonercartridge"
+ grind_results = list("iodine" = 40, "iron" = 10)
var/charges = 5
var/max_charges = 5
diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm
index 48b045f680..6e908c0f6a 100644
--- a/code/modules/paperwork/photography.dm
+++ b/code/modules/paperwork/photography.dm
@@ -33,6 +33,7 @@
w_class = WEIGHT_CLASS_TINY
resistance_flags = FLAMMABLE
max_integrity = 50
+ grind_results = list("iodine" = 4)
var/icon/img //Big photo image
var/scribble //Scribble on the back.
var/blueprints = 0 //Does it include the blueprints?
diff --git a/code/modules/power/antimatter/control.dm b/code/modules/power/antimatter/control.dm
index a37344d635..f8b8cae22a 100644
--- a/code/modules/power/antimatter/control.dm
+++ b/code/modules/power/antimatter/control.dm
@@ -339,7 +339,7 @@
if(href_list["ejectjar"])
if(fueljar)
- fueljar.loc = src.loc
+ fueljar.forceMove(drop_location())
fueljar = null
//fueljar.control_unit = null currently it does not care where it is
//update_icon() when we have the icon for it
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 7f3b428978..cbe8f335de 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -972,7 +972,7 @@
else
to_chat(occupier, "Primary core damaged, unable to return core processes.")
if(forced)
- occupier.loc = src.loc
+ occupier.forceMove(drop_location())
occupier.death()
occupier.gib()
for(var/obj/item/pinpointer/nuke/P in GLOB.pinpointer_list)
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index 9e4e29ceb5..ca424cb80d 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -427,7 +427,7 @@ By design, d1 is the smallest direction and d2 is the highest
var/obj/O = P_list[1]
// remove the cut cable from its turf and powernet, so that it doesn't get count in propagate_network worklist
if(remove)
- loc = null
+ moveToNullspace()
powernet.remove_cable(src) //remove the cut cable from its powernet
addtimer(CALLBACK(O, .proc/auto_propogate_cut_cable, O), 0) //so we don't rebuild the network X times when singulo/explosion destroys a line of X cables
@@ -472,6 +472,7 @@ GLOBAL_LIST_INIT(cable_coil_recipes, list (new/datum/stack_recipe("cable restrai
attack_verb = list("whipped", "lashed", "disciplined", "flogged")
singular_name = "cable piece"
full_w_class = WEIGHT_CLASS_SMALL
+ grind_results = list("copper" = 2) //2 copper per cable in the coil
/obj/item/stack/cable_coil/cyborg
is_cyborg = 1
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index 1e1407e852..d6781f63c3 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -14,6 +14,7 @@
var/charge = 0 // note %age conveted to actual charge in New
var/maxcharge = 1000
materials = list(MAT_METAL=700, MAT_GLASS=50)
+ grind_results = list("lithium" = 15, "iron" = 5, "silicon" = 5)
var/rigged = 0 // true if rigged to explode
var/chargerate = 100 //how much power is given every tick in a recharger
var/self_recharge = 0 //does it self recharge, over time, or not?
@@ -75,7 +76,7 @@
return 0
charge = (charge - amount)
if(!istype(loc, /obj/machinery/power/apc))
- SSblackbox.record_feedback("tally", "cell_used", 1, "[src.type]")
+ SSblackbox.record_feedback("tally", "cell_used", 1, type)
return 1
// recharge the cell
@@ -107,6 +108,7 @@
to_chat(user, "You inject the solution into the power cell.")
if(S.reagents.has_reagent("plasma", 5))
rigged = 1
+ grind_results["plasma"] = 5
S.reagents.clear_reagents()
diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm
index 65e6d4c0e4..1c4ce4a5c1 100644
--- a/code/modules/power/gravitygenerator.dm
+++ b/code/modules/power/gravitygenerator.dm
@@ -53,7 +53,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne
// You aren't allowed to move.
/obj/machinery/gravity_generator/Move()
- ..()
+ . = ..()
qdel(src)
/obj/machinery/gravity_generator/proc/set_broken()
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 3acac6cee5..f83a4f41d8 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -246,15 +246,15 @@
. = ..()
status = LIGHT_EMPTY
update(0)
- ..()
/obj/machinery/light/small/built
icon_state = "bulb-empty"
-/obj/machinery/light/small/built/New()
+/obj/machinery/light/small/built/Initialize()
+ . = ..()
status = LIGHT_EMPTY
update(0)
- ..()
+
// create a new lighting fixture
@@ -680,6 +680,7 @@
var/base_state
var/switchcount = 0 // number of times switched
materials = list(MAT_GLASS=100)
+ grind_results = list("silicon" = 5, "nitrogen" = 10) //Nitrogen is used as a cheaper alternative to argon in incandescent lighbulbs
var/rigged = 0 // true if rigged to explode
var/brightness = 2 //how much light it gives off
@@ -726,8 +727,8 @@
desc = "A broken [name]."
-/obj/item/light/New()
- ..()
+/obj/item/light/Initialize()
+ . = ..()
update()
diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm
index 0ede336ef6..36dd615e86 100644
--- a/code/modules/power/singularity/collector.dm
+++ b/code/modules/power/singularity/collector.dm
@@ -132,7 +132,7 @@
var/obj/item/tank/internals/plasma/Z = src.loaded_tank
if (!Z)
return
- Z.loc = get_turf(src)
+ Z.forceMove(drop_location())
Z.layer = initial(Z.layer)
Z.plane = initial(Z.plane)
src.loaded_tank = null
diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm
index c2610ebc44..70772f74f9 100644
--- a/code/modules/power/singularity/containment_field.dm
+++ b/code/modules/power/singularity/containment_field.dm
@@ -76,6 +76,7 @@
/obj/machinery/field/containment/Move()
qdel(src)
+ return FALSE
// Abstract Field Class
diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm
index 74aa140721..cdfbb35b34 100644
--- a/code/modules/power/singularity/field_generator.dm
+++ b/code/modules/power/singularity/field_generator.dm
@@ -285,9 +285,8 @@ field_generator power level display
var/field_dir = get_dir(T,get_step(G.loc, NSEW))
T = get_step(T, NSEW)
if(!locate(/obj/machinery/field/containment) in T)
- var/obj/machinery/field/containment/CF = new/obj/machinery/field/containment()
+ var/obj/machinery/field/containment/CF = new(T)
CF.set_master(src,G)
- CF.loc = T
CF.setDir(field_dir)
fields += CF
G.fields += CF
diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm
index 22712e970d..9801e98614 100644
--- a/code/modules/power/singularity/narsie.dm
+++ b/code/modules/power/singularity/narsie.dm
@@ -47,8 +47,15 @@
/obj/singularity/narsie/large/cult/Initialize()
. = ..()
GLOB.cult_narsie = src
- deltimer(GLOB.blood_target_reset_timer)
- GLOB.blood_target = src
+ var/list/all_cults = list()
+ for(var/datum/antagonist/cult/C in GLOB.antagonists)
+ all_cults |= C.cult_team
+ for(var/datum/objective_team/cult/T in all_cults)
+ deltimer(T.blood_target_reset_timer)
+ T.blood_target = src
+ var/datum/objective/eldergod/summon_objective = locate() in T.objectives
+ if(summon_objective)
+ summon_objective.summoned = TRUE
for(var/datum/mind/cult_mind in SSticker.mode.cult)
if(isliving(cult_mind.current))
var/mob/living/L = cult_mind.current
diff --git a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
index eebe4ef8c0..33c8a19982 100644
--- a/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
+++ b/code/modules/power/singularity/particle_accelerator/particle_accelerator.dm
@@ -152,7 +152,7 @@
qdel(src)
/obj/structure/particle_accelerator/Move()
- ..()
+ . = ..()
if(master && master.active)
master.toggle_power()
investigate_log("was moved whilst active; it powered down.", INVESTIGATE_SINGULO)
diff --git a/code/modules/power/singularity/particle_accelerator/particle_control.dm b/code/modules/power/singularity/particle_accelerator/particle_control.dm
index 266e5b22f5..c1ba907ada 100644
--- a/code/modules/power/singularity/particle_accelerator/particle_control.dm
+++ b/code/modules/power/singularity/particle_accelerator/particle_control.dm
@@ -17,7 +17,7 @@
var/active = 0
var/strength = 0
var/powered = 0
- mouse_opacity = 2
+ mouse_opacity = MOUSE_OPACITY_OPAQUE
/obj/machinery/particle_accelerator/control_box/Initialize()
. = ..()
diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm
index 681bb88c6b..f4b749c0e0 100644
--- a/code/modules/power/singularity/singularity.dm
+++ b/code/modules/power/singularity/singularity.dm
@@ -164,7 +164,7 @@
dissipate_track = 0
dissipate_strength = 1
if(STAGE_TWO)
- if((check_turfs_in(1,1))&&(check_turfs_in(2,1))&&(check_turfs_in(4,1))&&(check_turfs_in(8,1)))
+ if(check_cardinals_range(1, TRUE))
current_size = STAGE_TWO
icon = 'icons/effects/96x96.dmi'
icon_state = "singularity_s3"
@@ -176,7 +176,7 @@
dissipate_track = 0
dissipate_strength = 5
if(STAGE_THREE)
- if((check_turfs_in(1,2))&&(check_turfs_in(2,2))&&(check_turfs_in(4,2))&&(check_turfs_in(8,2)))
+ if(check_cardinals_range(2, TRUE))
current_size = STAGE_THREE
icon = 'icons/effects/160x160.dmi'
icon_state = "singularity_s5"
@@ -188,7 +188,7 @@
dissipate_track = 0
dissipate_strength = 20
if(STAGE_FOUR)
- if((check_turfs_in(1,3))&&(check_turfs_in(2,3))&&(check_turfs_in(4,3))&&(check_turfs_in(8,3)))
+ if(check_cardinals_range(3, TRUE))
current_size = STAGE_FOUR
icon = 'icons/effects/224x224.dmi'
icon_state = "singularity_s7"
@@ -296,6 +296,16 @@
step(src, movement_dir)
+/obj/singularity/proc/check_cardinals_range(steps, retry_with_move = FALSE)
+ . = length(GLOB.cardinals) //Should be 4.
+ for(var/i in GLOB.cardinals)
+ . -= check_turfs_in(i, steps) //-1 for each working direction
+ if(. && retry_with_move) //If there's still a positive value it means it didn't pass. Retry with move if applicable
+ for(var/i in GLOB.cardinals)
+ if(step(src, i)) //Move in each direction.
+ if(check_cardinals_range(steps, FALSE)) //New location passes, return true.
+ return TRUE
+ . = !.
/obj/singularity/proc/check_turfs_in(direction = 0, step = 0)
if(!direction)
diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm
index fb530f128f..435cfe4156 100644
--- a/code/modules/power/solar.dm
+++ b/code/modules/power/solar.dm
@@ -419,7 +419,7 @@
new /obj/item/shard( src.loc )
var/obj/item/circuitboard/computer/solar_control/M = new /obj/item/circuitboard/computer/solar_control( A )
for (var/obj/C in src)
- C.loc = src.loc
+ C.forceMove(drop_location())
A.circuit = M
A.state = 3
A.icon_state = "3"
@@ -430,7 +430,7 @@
var/obj/structure/frame/computer/A = new /obj/structure/frame/computer( src.loc )
var/obj/item/circuitboard/computer/solar_control/M = new /obj/item/circuitboard/computer/solar_control( A )
for (var/obj/C in src)
- C.loc = src.loc
+ C.forceMove(drop_location())
A.circuit = M
A.state = 4
A.icon_state = "4"
diff --git a/code/modules/power/tracker.dm b/code/modules/power/tracker.dm
index 5e129acf8f..a46627b7ca 100644
--- a/code/modules/power/tracker.dm
+++ b/code/modules/power/tracker.dm
@@ -47,7 +47,7 @@
S.glass_type = /obj/item/stack/sheet/glass
S.tracker = 1
S.anchored = TRUE
- S.loc = src
+ S.forceMove(src)
update_icon()
//updates the tracker icon and the facing angle for the control computer
@@ -94,4 +94,4 @@
// Tracker Electronic
/obj/item/electronics/tracker
- name = "tracker electronics"
\ No newline at end of file
+ name = "tracker electronics"
diff --git a/code/modules/procedural_mapping/mapGeneratorReadme.dm b/code/modules/procedural_mapping/mapGeneratorReadme.dm
index 85f937b41b..c4ced7674b 100644
--- a/code/modules/procedural_mapping/mapGeneratorReadme.dm
+++ b/code/modules/procedural_mapping/mapGeneratorReadme.dm
@@ -127,7 +127,7 @@ Variable Breakdown (For Mappers):
clusterCheckFlags - A Bitfield that controls how the cluster checks work, All based on clusterMin and clusterMax guides
allowAtomsOnSpace - A Boolean for if we allow atoms to spawn on space tiles
- clusterCheckFlags flags_1:
+ clusterCheckFlags flags:
CLUSTER_CHECK_NONE 0 //No checks are done, cluster as much as possible
CLUSTER_CHECK_DIFFERENT_TURFS 2 //Don't let turfs of DIFFERENT types cluster
CLUSTER_CHECK_DIFFERENT_ATOMS 4 //Don't let atoms of DIFFERENT types cluster
diff --git a/code/modules/procedural_mapping/mapGenerators/lava_river.dm b/code/modules/procedural_mapping/mapGenerators/lava_river.dm
index 4aadd48a58..8bdedb4b76 100644
--- a/code/modules/procedural_mapping/mapGenerators/lava_river.dm
+++ b/code/modules/procedural_mapping/mapGenerators/lava_river.dm
@@ -1,3 +1,4 @@
+
/datum/mapGenerator/lavaland
var/start_z = 5
var/min_x = 0
diff --git a/code/modules/procedural_mapping/mapGenerators/syndicate.dm b/code/modules/procedural_mapping/mapGenerators/syndicate.dm
index d3653d7ff3..758df6e0a0 100644
--- a/code/modules/procedural_mapping/mapGenerators/syndicate.dm
+++ b/code/modules/procedural_mapping/mapGenerators/syndicate.dm
@@ -1,56 +1,57 @@
-// Modules
-
-/turf/open/floor/plasteel/shuttle/red/syndicate
- name = "floor" //Not Brig Floor
-
-/datum/mapGeneratorModule/bottomLayer/syndieFloor
- spawnableTurfs = list(/turf/open/floor/plasteel/shuttle/red/syndicate = 100)
-
-/datum/mapGeneratorModule/border/syndieWalls
- spawnableAtoms = list()
- spawnableTurfs = list(/turf/closed/wall/r_wall = 100)
-
-
-/datum/mapGeneratorModule/syndieFurniture
- clusterCheckFlags = CLUSTER_CHECK_ALL
- spawnableTurfs = list()
- spawnableAtoms = list(/obj/structure/table = 20,/obj/structure/chair = 15,/obj/structure/chair/stool = 10, \
- /obj/structure/frame/computer = 15, /obj/item/storage/toolbox/syndicate = 15 ,\
- /obj/structure/closet/syndicate = 25, /obj/machinery/suit_storage_unit/syndicate = 15)
-
-/datum/mapGeneratorModule/splatterLayer/syndieMobs
- spawnableAtoms = list(/mob/living/simple_animal/hostile/syndicate = 30, \
- /mob/living/simple_animal/hostile/syndicate/melee = 20, \
- /mob/living/simple_animal/hostile/syndicate/ranged = 20, \
- /mob/living/simple_animal/hostile/viscerator = 30)
- spawnableTurfs = list()
-
-// Generators
-
-/datum/mapGenerator/syndicate/empty //walls and floor only
- modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \
- /datum/mapGeneratorModule/border/syndieWalls,\
- /datum/mapGeneratorModule/bottomLayer/repressurize)
- buildmode_name = "Pattern: Shuttle Room: Syndicate"
-
-/datum/mapGenerator/syndicate/mobsonly
- modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \
- /datum/mapGeneratorModule/border/syndieWalls,\
- /datum/mapGeneratorModule/splatterLayer/syndieMobs, \
- /datum/mapGeneratorModule/bottomLayer/repressurize)
- buildmode_name = "Pattern: Shuttle Room: Syndicate: Mobs"
-
-/datum/mapGenerator/syndicate/furniture
- modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \
- /datum/mapGeneratorModule/border/syndieWalls,\
- /datum/mapGeneratorModule/syndieFurniture, \
- /datum/mapGeneratorModule/bottomLayer/repressurize)
- buildmode_name = "Pattern: Shuttle Room: Syndicate: Furniture"
-
-/datum/mapGenerator/syndicate/full
- modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \
- /datum/mapGeneratorModule/border/syndieWalls,\
- /datum/mapGeneratorModule/syndieFurniture, \
- /datum/mapGeneratorModule/splatterLayer/syndieMobs, \
- /datum/mapGeneratorModule/bottomLayer/repressurize)
- buildmode_name = "Pattern: Shuttle Room: Syndicate: All"
\ No newline at end of file
+
+// Modules
+
+/turf/open/floor/plasteel/shuttle/red/syndicate
+ name = "floor" //Not Brig Floor
+
+/datum/mapGeneratorModule/bottomLayer/syndieFloor
+ spawnableTurfs = list(/turf/open/floor/plasteel/shuttle/red/syndicate = 100)
+
+/datum/mapGeneratorModule/border/syndieWalls
+ spawnableAtoms = list()
+ spawnableTurfs = list(/turf/closed/wall/r_wall = 100)
+
+
+/datum/mapGeneratorModule/syndieFurniture
+ clusterCheckFlags = CLUSTER_CHECK_ALL
+ spawnableTurfs = list()
+ spawnableAtoms = list(/obj/structure/table = 20,/obj/structure/chair = 15,/obj/structure/chair/stool = 10, \
+ /obj/structure/frame/computer = 15, /obj/item/storage/toolbox/syndicate = 15 ,\
+ /obj/structure/closet/syndicate = 25, /obj/machinery/suit_storage_unit/syndicate = 15)
+
+/datum/mapGeneratorModule/splatterLayer/syndieMobs
+ spawnableAtoms = list(/mob/living/simple_animal/hostile/syndicate = 30, \
+ /mob/living/simple_animal/hostile/syndicate/melee = 20, \
+ /mob/living/simple_animal/hostile/syndicate/ranged = 20, \
+ /mob/living/simple_animal/hostile/viscerator = 30)
+ spawnableTurfs = list()
+
+// Generators
+
+/datum/mapGenerator/syndicate/empty //walls and floor only
+ modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \
+ /datum/mapGeneratorModule/border/syndieWalls,\
+ /datum/mapGeneratorModule/bottomLayer/repressurize)
+ buildmode_name = "Pattern: Shuttle Room: Syndicate"
+
+/datum/mapGenerator/syndicate/mobsonly
+ modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \
+ /datum/mapGeneratorModule/border/syndieWalls,\
+ /datum/mapGeneratorModule/splatterLayer/syndieMobs, \
+ /datum/mapGeneratorModule/bottomLayer/repressurize)
+ buildmode_name = "Pattern: Shuttle Room: Syndicate: Mobs"
+
+/datum/mapGenerator/syndicate/furniture
+ modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \
+ /datum/mapGeneratorModule/border/syndieWalls,\
+ /datum/mapGeneratorModule/syndieFurniture, \
+ /datum/mapGeneratorModule/bottomLayer/repressurize)
+ buildmode_name = "Pattern: Shuttle Room: Syndicate: Furniture"
+
+/datum/mapGenerator/syndicate/full
+ modules = list(/datum/mapGeneratorModule/bottomLayer/syndieFloor, \
+ /datum/mapGeneratorModule/border/syndieWalls,\
+ /datum/mapGeneratorModule/syndieFurniture, \
+ /datum/mapGeneratorModule/splatterLayer/syndieMobs, \
+ /datum/mapGeneratorModule/bottomLayer/repressurize)
+ buildmode_name = "Pattern: Shuttle Room: Syndicate: All"
diff --git a/code/modules/projectiles/ammunition.dm b/code/modules/projectiles/ammunition.dm
index 71befb50f1..c73dbb1b3b 100644
--- a/code/modules/projectiles/ammunition.dm
+++ b/code/modules/projectiles/ammunition.dm
@@ -19,8 +19,8 @@
var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect //the visual effect appearing when the ammo is fired.
-/obj/item/ammo_casing/New()
- ..()
+/obj/item/ammo_casing/Initialize()
+ . = ..()
if(projectile_type)
BB = new projectile_type(src)
pixel_x = rand(-10, 10)
diff --git a/code/modules/projectiles/ammunition/ammo_casings.dm b/code/modules/projectiles/ammunition/ammo_casings.dm
index d51ea36e15..9e7d21d510 100644
--- a/code/modules/projectiles/ammunition/ammo_casings.dm
+++ b/code/modules/projectiles/ammunition/ammo_casings.dm
@@ -284,8 +284,8 @@
icon_state = "cshell"
projectile_type = /obj/item/projectile/bullet/dart
-/obj/item/ammo_casing/shotgun/dart/New()
- ..()
+/obj/item/ammo_casing/shotgun/dart/Initialize()
+ . = ..()
container_type |= OPENCONTAINER_1
create_reagents(30)
reagents.set_reacting(TRUE)
@@ -296,10 +296,10 @@
/obj/item/ammo_casing/shotgun/dart/bioterror
desc = "A shotgun dart filled with deadly toxins."
-/obj/item/ammo_casing/shotgun/dart/bioterror/New()
- ..()
+/obj/item/ammo_casing/shotgun/dart/bioterror/Initialize()
+ . = ..()
reagents.add_reagent("neurotoxin", 6)
reagents.add_reagent("spore", 6)
reagents.add_reagent("mutetoxin", 6) //;HELP OPS IN MAINT
reagents.add_reagent("coniine", 6)
- reagents.add_reagent("sodium_thiopental", 6)
\ No newline at end of file
+ reagents.add_reagent("sodium_thiopental", 6)
diff --git a/code/modules/projectiles/ammunition/caseless.dm b/code/modules/projectiles/ammunition/caseless.dm
index e5b905019d..7432f9f8e7 100644
--- a/code/modules/projectiles/ammunition/caseless.dm
+++ b/code/modules/projectiles/ammunition/caseless.dm
@@ -7,7 +7,7 @@
/obj/item/ammo_casing/caseless/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread)
if (..()) //successfully firing
- loc = null
+ moveToNullspace()
return 1
else
return 0
diff --git a/code/modules/projectiles/box_magazine.dm b/code/modules/projectiles/box_magazine.dm
index 324470ede4..87a02012ce 100644
--- a/code/modules/projectiles/box_magazine.dm
+++ b/code/modules/projectiles/box_magazine.dm
@@ -22,8 +22,8 @@
var/multiload = 1
var/start_empty = 0
-/obj/item/ammo_box/New()
- ..()
+/obj/item/ammo_box/Initialize()
+ . = ..()
if(!start_empty)
for(var/i = 1, i <= max_ammo, i++)
stored_ammo += new ammo_type(src)
diff --git a/code/modules/projectiles/boxes_magazines/internal_mag.dm b/code/modules/projectiles/boxes_magazines/internal_mag.dm
index 3a8b4e6f2f..d7bfaf9ee7 100644
--- a/code/modules/projectiles/boxes_magazines/internal_mag.dm
+++ b/code/modules/projectiles/boxes_magazines/internal_mag.dm
@@ -51,10 +51,10 @@
var/obj/item/ammo_casing/bullet = stored_ammo[i]
if(!bullet || !bullet.BB) // found a spent ammo
stored_ammo[i] = R
- R.loc = src
+ R.forceMove(src)
if(bullet)
- bullet.loc = get_turf(src.loc)
+ bullet.forceMove(drop_location())
return 1
return 0
@@ -156,9 +156,9 @@
max_ammo = 6
multiload = 0
-/obj/item/ammo_box/magazine/internal/rus357/New()
+/obj/item/ammo_box/magazine/internal/rus357/Initialize()
stored_ammo += new ammo_type(src)
- ..()
+ . = ..()
/obj/item/ammo_box/magazine/internal/boltaction
name = "bolt action rifle internal magazine"
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 37e868462e..0307d17df0 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -24,7 +24,7 @@
var/can_suppress = FALSE
var/can_unsuppress = TRUE
var/recoil = 0 //boom boom shake the room
- var/clumsy_check = 1
+ var/clumsy_check = TRUE
var/obj/item/ammo_casing/chambered = null
trigger_guard = TRIGGER_GUARD_NORMAL //trigger guard on the weapon, hulks can't fire them with their big meaty fingers
var/sawn_desc = null //description change if weapon is sawn-off
@@ -77,9 +77,8 @@
..()
var/obj/item/gun/G = locate(/obj/item/gun) in contents
if(G)
- G.loc = loc
- qdel(G.pin)
- G.pin = null
+ G.forceMove(loc)
+ QDEL_NULL(G.pin)
visible_message("[G] can now fit a new pin, but the old one was destroyed in the process.", null, null, 3)
qdel(src)
@@ -92,19 +91,17 @@
/obj/item/gun/equipped(mob/living/user, slot)
. = ..()
- if(zoomable && user.get_active_held_item() != src)
- zoom(user, FALSE) //we can only stay zoomed in if it's in our hands
+ if(zoomed && user.get_active_held_item() != src)
+ zoom(user, FALSE) //we can only stay zoomed in if it's in our hands //yeah and we only unzoom if we're actually zoomed using the gun!!
//called after the gun has successfully fired its chambered ammo.
/obj/item/gun/proc/process_chamber()
- return 0
-
+ return FALSE
//check if there's enough ammo/energy/whatever to shoot one time
//i.e if clicking would make it shoot
/obj/item/gun/proc/can_shoot()
- return 1
-
+ return TRUE
/obj/item/gun/proc/shoot_with_empty_chamber(mob/living/user as mob|obj)
to_chat(user, "*click*")
@@ -195,13 +192,13 @@
/obj/item/gun/proc/handle_pins(mob/living/user)
if(pin)
if(pin.pin_auth(user) || pin.emagged)
- return 1
+ return TRUE
else
pin.auth_fail(user)
- return 0
+ return FALSE
else
to_chat(user, "[src]'s trigger is locked. This weapon doesn't have a firing pin installed!")
- return 0
+ return FALSE
/obj/item/gun/proc/recharge_newshot()
return
@@ -421,7 +418,7 @@
target.visible_message("[user] points [src] at [target]'s head, ready to pull the trigger...", \
"[user] points [src] at your head, ready to pull the trigger...")
- semicd = 1
+ semicd = TRUE
if(!do_mob(user, target, 120) || user.zone_selected != "mouth")
if(user)
@@ -429,10 +426,10 @@
user.visible_message("[user] decided not to shoot.")
else if(target && target.Adjacent(user))
target.visible_message("[user] has decided to spare [target]", "[user] has decided to spare your life!")
- semicd = 0
+ semicd = FALSE
return
- semicd = 0
+ semicd = FALSE
target.visible_message("[user] pulls the trigger!", "[user] pulls the trigger!")
diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm
index bfc9ceac64..ee7d74081c 100644
--- a/code/modules/projectiles/guns/ballistic.dm
+++ b/code/modules/projectiles/guns/ballistic.dm
@@ -107,13 +107,13 @@
/obj/item/gun/ballistic/attack_self(mob/living/user)
var/obj/item/ammo_casing/AC = chambered //Find chambered round
if(magazine)
- magazine.loc = get_turf(src.loc)
+ magazine.forceMove(drop_location())
user.put_in_hands(magazine)
magazine.update_icon()
magazine = null
to_chat(user, "You pull the magazine out of \the [src].")
else if(chambered)
- AC.loc = get_turf(src)
+ AC.forceMove(drop_location())
AC.SpinAnimation(10, 1)
chambered = null
to_chat(user, "You unload the round from \the [src]'s chamber.")
@@ -167,6 +167,8 @@
#undef BRAINS_BLOWN_THROW_SPEED
#undef BRAINS_BLOWN_THROW_RANGE
+
+
/obj/item/gun/ballistic/proc/sawoff(mob/user)
if(sawn_state == SAWN_OFF)
to_chat(user, "\The [src] is already shortened!")
@@ -216,4 +218,3 @@
desc = "A foreign knock-off suppressor, it feels flimsy, cheap, and brittle. Still fits all weapons."
icon = 'icons/obj/guns/projectile.dmi'
icon_state = "suppressor"
-
diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm
index eb36608e77..daf223aba9 100644
--- a/code/modules/projectiles/guns/ballistic/automatic.dm
+++ b/code/modules/projectiles/guns/ballistic/automatic.dm
@@ -8,7 +8,7 @@
actions_types = list(/datum/action/item_action/toggle_firemode)
/obj/item/gun/ballistic/automatic/proto
- name = "\improper NanoTrasen Saber SMG"
+ name = "\improper Nanotrasen Saber SMG"
desc = "A prototype three-round burst 9mm submachine gun, designated 'SABR'. Has a threaded barrel for suppressors."
icon_state = "saber"
mag_type = /obj/item/ammo_box/magazine/smgm9mm
@@ -19,7 +19,6 @@
/obj/item/gun/ballistic/automatic/update_icon()
..()
- cut_overlays()
if(!select)
add_overlay("[initial(icon_state)]semi")
if(select == 1)
@@ -93,6 +92,9 @@
fire_delay = 2
burst_size = 2
pin = /obj/item/device/firing_pin/implant/pindicate
+ can_bayonet = TRUE
+ knife_x_offset = 26
+ knife_y_offset = 12
/obj/item/gun/ballistic/automatic/c20r/unrestricted
pin = /obj/item/device/firing_pin
@@ -120,6 +122,9 @@
can_suppress = FALSE
burst_size = 0
actions_types = list()
+ can_bayonet = TRUE
+ knife_x_offset = 25
+ knife_y_offset = 12
/obj/item/gun/ballistic/automatic/wt550/update_icon()
..()
@@ -325,7 +330,7 @@
else if(cover_open && magazine)
//drop the mag
magazine.update_icon()
- magazine.loc = get_turf(src.loc)
+ magazine.forceMove(drop_location())
user.put_in_hands(magazine)
magazine = null
update_icon()
@@ -357,7 +362,8 @@
can_suppress = TRUE
w_class = WEIGHT_CLASS_NORMAL
zoomable = TRUE
- zoom_amt = 7 //Long range, enough to see in front of you, but no tiles behind you.
+ zoom_amt = 10 //Long range, enough to see in front of you, but no tiles behind you.
+ zoom_out_amt = 13
slot_flags = SLOT_BACK
actions_types = list()
diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm
index 42f4fb8a05..4dafbc3f3c 100644
--- a/code/modules/projectiles/guns/ballistic/revolver.dm
+++ b/code/modules/projectiles/guns/ballistic/revolver.dm
@@ -39,7 +39,7 @@
var/obj/item/ammo_casing/CB
CB = magazine.get_round(0)
if(CB)
- CB.loc = get_turf(src.loc)
+ CB.forceMove(drop_location())
CB.SpinAnimation(10, 1)
CB.update_icon()
num_unloaded++
@@ -289,7 +289,7 @@
var/obj/item/ammo_casing/CB
CB = magazine.get_round(0)
chambered = null
- CB.loc = get_turf(src.loc)
+ CB.forceMove(drop_location())
CB.update_icon()
num_unloaded++
if (num_unloaded)
diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm
index 650e5ec81f..c68917fbfd 100644
--- a/code/modules/projectiles/guns/ballistic/shotgun.dm
+++ b/code/modules/projectiles/guns/ballistic/shotgun.dm
@@ -56,7 +56,7 @@
/obj/item/gun/ballistic/shotgun/proc/pump_unload(mob/M)
if(chambered)//We have a shell in the chamber
- chambered.loc = get_turf(src)//Eject casing
+ chambered.forceMove(drop_location())//Eject casing
chambered.SpinAnimation(5, 1)
chambered = null
@@ -105,6 +105,9 @@
slot_flags = 0 //no SLOT_BACK sprite, alas
mag_type = /obj/item/ammo_box/magazine/internal/boltaction
var/bolt_open = FALSE
+ can_bayonet = TRUE
+ knife_x_offset = 27
+ knife_y_offset = 13
/obj/item/gun/ballistic/shotgun/boltaction/pump(mob/M)
playsound(M, 'sound/weapons/shotgunpump.ogg', 60, 1)
@@ -141,6 +144,7 @@
pin = /obj/item/device/firing_pin/magic
icon_state = "arcane_barrage"
item_state = "arcane_barrage"
+ can_bayonet = FALSE
flags_1 = DROPDEL_1
diff --git a/code/modules/projectiles/guns/beam_rifle.dm b/code/modules/projectiles/guns/beam_rifle.dm
index e1069a6bce..4b51951cfd 100644
--- a/code/modules/projectiles/guns/beam_rifle.dm
+++ b/code/modules/projectiles/guns/beam_rifle.dm
@@ -63,8 +63,6 @@
var/projectile_setting_pierce = TRUE
var/delay = 65
var/lastfire = 0
-
- var/lastprocess = 0
//ZOOMING
var/zoom_current_view_increase = 0
@@ -502,11 +500,11 @@
if(!do_pierce)
return FALSE
if(pierced[target]) //we already pierced them go away
- loc = get_turf(target)
+ forceMove(get_turf(target))
return TRUE
if(isclosedturf(target))
if(wall_pierce++ < wall_pierce_amount)
- loc = target
+ forceMove(target)
if(prob(wall_devastate))
if(iswallturf(target))
var/turf/closed/wall/W = target
@@ -522,7 +520,7 @@
var/obj/O = AM
O.take_damage((impact_structure_damage + aoe_structure_damage) * structure_bleed_coeff * get_damage_coeff(AM), BURN, "energy", FALSE)
pierced[AM] = TRUE
- loc = get_turf(AM)
+ forceMove(AM.drop_location())
structure_pierce++
return TRUE
return FALSE
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index 3b93a960ca..c65e518383 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -16,8 +16,8 @@
var/unique_frequency = FALSE // modified by KA modkits
var/overheat = FALSE
can_bayonet = TRUE
- knife_x_offset = 15
- knife_y_offset = 13
+ knife_x_offset = 20
+ knife_y_offset = 12
var/max_mod_capacity = 100
var/list/modkits = list()
diff --git a/code/modules/projectiles/guns/misc/blastcannon.dm b/code/modules/projectiles/guns/misc/blastcannon.dm
index dfbcc61f37..f1e8848d27 100644
--- a/code/modules/projectiles/guns/misc/blastcannon.dm
+++ b/code/modules/projectiles/guns/misc/blastcannon.dm
@@ -13,10 +13,10 @@
var/obj/item/device/transfer_valve/bomb
-/obj/item/gun/blastcannon/New()
+/obj/item/gun/blastcannon/Initialize()
+ . = ..()
if(!pin)
pin = new
- return ..()
/obj/item/gun/blastcannon/Destroy()
if(bomb)
diff --git a/code/modules/projectiles/guns/syringe_gun.dm b/code/modules/projectiles/guns/syringe_gun.dm
index b8e3c97e81..ac9f7daedf 100644
--- a/code/modules/projectiles/guns/syringe_gun.dm
+++ b/code/modules/projectiles/guns/syringe_gun.dm
@@ -42,7 +42,7 @@
if(!S)
return 0
- S.loc = user.loc
+ S.forceMove(user.loc)
syringes.Remove(S)
to_chat(user, "You unload [S] from \the [src].")
@@ -101,4 +101,4 @@
return TRUE
else
to_chat(user, "[src] cannot hold more syringes!")
- return FALSE
\ No newline at end of file
+ return FALSE
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 0e3bd98c68..66698a8939 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -73,9 +73,9 @@
var/impact_effect_type //what type of impact effect to show when hitting something
var/log_override = FALSE //is this type spammed enough to not log? (KAs)
-/obj/item/projectile/New()
+/obj/item/projectile/Initialize()
+ . = ..()
permutated = list()
- return ..()
/obj/item/projectile/proc/Range()
range--
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index 323960c7f3..235f27e9e5 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -341,8 +341,8 @@
icon_state = "banana"
range = 200
-/obj/item/projectile/bullet/honker/New()
- ..()
+/obj/item/projectile/bullet/honker/Initialize()
+ . = ..()
SpinAnimation()
// Mime
@@ -364,8 +364,8 @@
damage = 6
var/piercing = FALSE
-/obj/item/projectile/bullet/dart/New()
- ..()
+/obj/item/projectile/bullet/dart/Initialize()
+ . = ..()
create_reagents(50)
reagents.set_reacting(FALSE)
@@ -388,8 +388,8 @@
reagents.handle_reactions()
return TRUE
-/obj/item/projectile/bullet/dart/metalfoam/New()
- ..()
+/obj/item/projectile/bullet/dart/metalfoam/Initialize()
+ . = ..()
reagents.add_reagent("aluminium", 15)
reagents.add_reagent("foaming_agent", 5)
reagents.add_reagent("facid", 5)
diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm
index 5a650ff2c3..152cff6c74 100644
--- a/code/modules/projectiles/projectile/special.dm
+++ b/code/modules/projectiles/projectile/special.dm
@@ -100,7 +100,7 @@
/obj/item/projectile/meteor/Collide(atom/A)
if(A == firer)
- loc = A.loc
+ forceMove(A.loc)
return
A.ex_act(EXPLODE_HEAVY)
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1)
@@ -612,4 +612,3 @@
knockdown = 0
nodamage = TRUE
return ..()
-
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index 9c4bff72cb..2d3200c506 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -15,6 +15,7 @@
/datum/reagents/New(maximum=100)
maximum_volume = maximum
+
//I dislike having these here but map-objects are initialised before world/New() is called. >_>
if(!GLOB.chemical_reagents_list)
//Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id
@@ -228,8 +229,7 @@
var/list/cached_reagents = reagent_list
var/list/cached_addictions = addiction_list
if(C)
- chem_temp = C.bodytemperature
- handle_reactions()
+ expose_temperature(C.bodytemperature, 0.25)
var/need_mob_update = 0
for(var/reagent in cached_reagents)
var/datum/reagent/R = reagent
@@ -283,6 +283,7 @@
C.update_stamina()
update_total()
+
/datum/reagents/proc/set_reacting(react = TRUE)
if(react)
flags &= ~(REAGENT_NOREACT)
@@ -732,6 +733,15 @@
return english_list(out, "something indescribable")
+/datum/reagents/proc/expose_temperature(var/temperature, var/coeff=0.02)
+ var/temp_delta = (temperature - chem_temp) * coeff
+ if(temp_delta > 0)
+ chem_temp = min(chem_temp + max(temp_delta, 1), temperature)
+ else
+ chem_temp = max(chem_temp + min(temp_delta, -1), temperature)
+ chem_temp = round(chem_temp)
+ handle_reactions()
+
///////////////////////////////////////////////////////////////////////////////////
diff --git a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
index 77fcd50306..223259f6f3 100644
--- a/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
+++ b/code/modules/reagents/chemistry/machinery/reagentgrinder.dm
@@ -2,7 +2,7 @@
#define MILK_TO_BUTTER_COEFF 15
/obj/machinery/reagentgrinder
- name = "All-In-One Grinder"
+ name = "\improper All-In-One Grinder"
desc = "From BlenderTech. Will It Blend? Let's test it out!"
icon = 'icons/obj/kitchen.dmi'
icon_state = "juicer1"
@@ -16,97 +16,6 @@
var/operating = FALSE
var/obj/item/reagent_containers/beaker = null
var/limit = 10
-
- var/static/list/blend_items = list(
- //Sheets
- /obj/item/stack/sheet/mineral/plasma = list("plasma" = 20),
- /obj/item/stack/sheet/metal = list("iron" = 20),
- /obj/item/stack/sheet/plasteel = list("iron" = 20, "plasma" = 20),
- /obj/item/stack/sheet/mineral/wood = list("carbon" = 20),
- /obj/item/stack/sheet/glass = list("silicon" = 20),
- /obj/item/stack/sheet/rglass = list("silicon" = 20, "iron" = 20),
- /obj/item/stack/sheet/mineral/uranium = list("uranium" = 20),
- /obj/item/stack/sheet/mineral/bananium = list("banana" = 20),
- /obj/item/stack/sheet/mineral/silver = list("silver" = 20),
- /obj/item/stack/sheet/mineral/gold = list("gold" = 20),
- /obj/item/stack/sheet/bluespace_crystal = list("bluespace" = 20),
- /obj/item/stack/cable_coil = list ("copper" = 5),
- /obj/item/ore/bluespace_crystal = list("bluespace" = 20),
- /obj/item/grown/nettle/basic = list("sacid" = 0),
- /obj/item/grown/nettle/death = list("facid" = 0, "sacid" = 0),
- /obj/item/grown/novaflower = list("capsaicin" = 0, "condensedcapsaicin" = 0),
- //Blender Stuff
- /obj/item/reagent_containers/food/snacks/donkpocket/warm = list("omnizine" = 3),
- /obj/item/reagent_containers/food/snacks/grown/soybeans = list("soymilk" = 0),
- /obj/item/reagent_containers/food/snacks/grown/tomato = list("ketchup" = 0),
- /obj/item/reagent_containers/food/snacks/grown/wheat = list("flour" = -5),
- /obj/item/reagent_containers/food/snacks/grown/oat = list("flour" = -5),
- /obj/item/reagent_containers/food/snacks/grown/rice = list("rice" = -5),
- /obj/item/reagent_containers/food/snacks/donut = list("sprinkles" = -2, "sugar" = 1),
- /obj/item/reagent_containers/food/snacks/grown/cherries = list("cherryjelly" = 0),
- /obj/item/reagent_containers/food/snacks/grown/bluecherries = list("bluecherryjelly" = 0),
- /obj/item/reagent_containers/food/snacks/egg = list("eggyolk" = -5),
- /obj/item/reagent_containers/food/snacks/deadmouse = list ("blood" = 20, "gibs" = 5), // You monster
- //Grinder stuff, but only if dry
- /obj/item/reagent_containers/food/snacks/grown/coffee/robusta = list("coffeepowder" = 0, "morphine" = 0),
- /obj/item/reagent_containers/food/snacks/grown/coffee = list("coffeepowder" = 0),
- /obj/item/reagent_containers/food/snacks/grown/tea/astra = list("teapowder" = 0, "salglu_solution" = 0),
- /obj/item/reagent_containers/food/snacks/grown/tea = list("teapowder" = 0),
- //Stuff that doesn't quite fit in the other categories
- /obj/item/electronics = list ("iron" = 10, "silicon" = 10),
- /obj/item/circuitboard = list ("silicon" = 20, "sacid" = 0.5), // Retrieving acid this way is extremely inefficient
- /obj/item/match = list ("phosphorus" = 2),
- /obj/item/device/toner = list ("iodine" = 40, "iron" = 10),
- /obj/item/photo = list ("iodine" = 4),
- /obj/item/pen = list ("iodine" = 2, "iron" = 1),
- /obj/item/reagent_containers/food/drinks/soda_cans = list ("aluminium" = 10),
- /obj/item/trash/can = list ("aluminium" = 10),
- /obj/item/device/flashlight/flare = list ("sulfur" = 15),
- /obj/item/device/flashlight/glowstick = list ("phenol" = 15, "hydrodgen" = 10, "oxygen" = 5),
- /obj/item/stock_parts/cell = list ("lithium" = 15, "iron" = 5, "silicon" = 5),
- /obj/item/soap = list ("lye" = 10),
- /obj/item/device/analyzer = list ("mercury" = 5, "iron" = 5, "silicon" = 5),
- /obj/item/lighter = list ("iron" = 1, "weldingfuel" = 5, "oil" = 5),
- /obj/item/light = list ("silicon" = 5, "nitrogen" = 10), //Nitrogen is used as a cheaper alternative to argon in incandescent lighbulbs
- /obj/item/cigbutt/ = list ("carbon" = 2),
- /obj/item/trash/coal = list ("carbon" = 20),
- /obj/item/stack/medical/bruise_pack = list ("styptic_powder" = 5),
- /obj/item/stack/medical/ointment = list ("silver_sulfadiazine" = 5),
- //All types that you can put into the grinder to transfer the reagents to the beaker. !Put all recipes above this.!
- /obj/item/slime_extract = list(),
- /obj/item/reagent_containers/pill = list(),
- /obj/item/reagent_containers/food = list(),
- /obj/item/reagent_containers/honeycomb = list(),
- /obj/item/toy/crayon = list(),
- /obj/item/clothing/mask/cigarette = list())
-
- var/static/list/juice_items = list(
- //Juicer Stuff
- /obj/item/reagent_containers/food/snacks/grown/corn = list("corn_starch" = 0),
- /obj/item/reagent_containers/food/snacks/grown/tomato = list("tomatojuice" = 0),
- /obj/item/reagent_containers/food/snacks/grown/carrot = list("carrotjuice" = 0),
- /obj/item/reagent_containers/food/snacks/grown/berries = list("berryjuice" = 0),
- /obj/item/reagent_containers/food/snacks/grown/banana = list("banana" = 0),
- /obj/item/reagent_containers/food/snacks/grown/potato = list("potato" = 0),
- /obj/item/reagent_containers/food/snacks/grown/citrus/lemon = list("lemonjuice" = 0),
- /obj/item/reagent_containers/food/snacks/grown/citrus/orange = list("orangejuice" = 0),
- /obj/item/reagent_containers/food/snacks/grown/citrus/lime = list("limejuice" = 0),
- /obj/item/reagent_containers/food/snacks/grown/watermelon = list("watermelonjuice" = 0),
- /obj/item/reagent_containers/food/snacks/watermelonslice = list("watermelonjuice" = 0),
- /obj/item/reagent_containers/food/snacks/grown/berries/poison = list("poisonberryjuice" = 0),
- /obj/item/reagent_containers/food/snacks/grown/pumpkin = list("pumpkinjuice" = 0),
- /obj/item/reagent_containers/food/snacks/grown/blumpkin = list("blumpkinjuice" = 0),
- /obj/item/reagent_containers/food/snacks/grown/apple = list("applejuice" = 0),
- /obj/item/reagent_containers/food/snacks/grown/grapes = list("grapejuice" = 0),
- /obj/item/reagent_containers/food/snacks/grown/grapes/green = list("grapejuice" = 0))
-
- var/static/list/dried_items = list(
- //Grinder stuff, but only if dry,
- /obj/item/reagent_containers/food/snacks/grown/coffee/robusta = list("coffeepowder" = 0, "morphine" = 0),
- /obj/item/reagent_containers/food/snacks/grown/coffee = list("coffeepowder" = 0),
- /obj/item/reagent_containers/food/snacks/grown/tea/astra = list("teapowder" = 0, "salglu_solution" = 0),
- /obj/item/reagent_containers/food/snacks/grown/tea = list("teapowder" = 0))
-
var/list/holdingitems
/obj/machinery/reagentgrinder/Initialize()
@@ -158,6 +67,7 @@
if(!user.transferItemToLoc(I, src))
to_chat(user, "[I] is stuck to your hand!")
return TRUE
+ to_chat(user, "You slide [I] into [src].")
beaker = I
update_icon()
updateUsrDialog()
@@ -165,15 +75,8 @@
to_chat(user, "There's already a container inside [src].")
return TRUE //no afterattack
- if(is_type_in_list(I, dried_items))
- if(istype(I, /obj/item/reagent_containers/food/snacks/grown))
- var/obj/item/reagent_containers/food/snacks/grown/G = I
- if(!G.dry)
- to_chat(user, "You must dry [G] first!")
- return TRUE
-
- if(length(holdingitems) >= limit)
- to_chat(user, "The machine cannot hold anymore items.")
+ if(holdingitems.len >= limit)
+ to_chat(user, "[src] is filled to capacity!")
return TRUE
//Fill machine with a bag!
@@ -192,14 +95,18 @@
updateUsrDialog()
return TRUE
- if (!is_type_in_list(I, blend_items) && !is_type_in_list(I, juice_items))
+ if(!I.grind_results && !I.juice_results)
if(user.a_intent == INTENT_HARM)
return ..()
else
- to_chat(user, "Cannot refine into a reagent!")
+ to_chat(user, "You cannot grind [I] into reagents!")
return TRUE
+ if(!I.grind_requirements(src)) //Error messages should be in the objects' definitions
+ return
+
if(user.transferItemToLoc(I, src))
+ to_chat(user, "You add [I] to [src].")
holdingitems[I] = TRUE
updateUsrDialog()
return FALSE
@@ -214,7 +121,7 @@
user.set_machine(src)
interact(user)
-/obj/machinery/reagentgrinder/interact(mob/user) // The microwave Menu
+/obj/machinery/reagentgrinder/interact(mob/user) // The microwave Menu //I am reasonably certain that this is not a microwave
var/is_chamber_empty = FALSE
var/is_beaker_ready = FALSE
var/processing_chamber = ""
@@ -307,60 +214,10 @@
holdingitems -= O
updateUsrDialog()
-/obj/machinery/reagentgrinder/proc/get_allowed_by_obj(obj/item/O)
- for (var/i in blend_items)
- if (istype(O, i))
- return blend_items[i]
-
-/obj/machinery/reagentgrinder/proc/get_allowed_juice_by_obj(obj/item/reagent_containers/food/snacks/O)
- for(var/i in juice_items)
- if(istype(O, i))
- return juice_items[i]
-
-/obj/machinery/reagentgrinder/proc/get_grownweapon_amount(obj/item/grown/O)
- if (!istype(O) || !O.seed)
- return 5
- else if (O.seed.potency == -1)
- return 5
- else
- return round(O.seed.potency)
-
-/obj/machinery/reagentgrinder/proc/get_juice_amount(obj/item/reagent_containers/food/snacks/grown/O)
- if (!istype(O) || !O.seed)
- return 5
- else if (O.seed.potency == -1)
- return 5
- else
- return round(5*sqrt(O.seed.potency))
-
/obj/machinery/reagentgrinder/proc/remove_object(obj/item/O)
holdingitems -= O
qdel(O)
-/obj/machinery/reagentgrinder/proc/juice()
- power_change()
- if(!beaker || (beaker && (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)))
- return
- operate_for(50, juicing = TRUE)
-
- //Snacks
- for(var/obj/item/i in holdingitems)
- var/obj/item/I = i
- if(istype(I, /obj/item/reagent_containers/food/snacks))
- var/obj/item/reagent_containers/food/snacks/O = I
- if(beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
- break
- var/list/allowed = get_allowed_juice_by_obj(O)
- if(isnull(allowed))
- break
- for(var/r_id in allowed)
- var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume
- var/amount = get_juice_amount(O)
- beaker.reagents.add_reagent(r_id, min(amount, space))
- if(beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
- break
- remove_object(O)
-
/obj/machinery/reagentgrinder/proc/shake_for(duration)
var/offset = prob(50) ? -2 : 2
var/old_pixel_x = pixel_x
@@ -386,8 +243,26 @@
operating = FALSE
updateUsrDialog()
-/obj/machinery/reagentgrinder/proc/grind()
+/obj/machinery/reagentgrinder/proc/juice()
+ power_change()
+ if(!beaker || (beaker && (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)))
+ return
+ operate_for(50, juicing = TRUE)
+ for(var/obj/item/i in holdingitems)
+ if(beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
+ break
+ var/obj/item/I = i
+ if(I.juice_results)
+ juice_item(I)
+/obj/machinery/reagentgrinder/proc/juice_item(obj/item/I) //Juicing results can be found in respective object definitions
+ if(I.on_juice(src) == -1)
+ to_chat(usr, "[src] shorts out as it tries to juice up [I], and transfers it back to storage.")
+ return
+ beaker.reagents.add_reagent_list(I.juice_results)
+ remove_object(I)
+
+/obj/machinery/reagentgrinder/proc/grind()
power_change()
if(!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume))
return
@@ -396,82 +271,17 @@
if(beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
break
var/obj/item/I = i
- //Snacks
- if(istype(I, /obj/item/reagent_containers/food/snacks))
- var/obj/item/reagent_containers/food/snacks/O = I
- var/list/allowed = get_allowed_by_obj(O)
- if(isnull(allowed))
- continue
- for(var/r_id in allowed)
- var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume
- var/amount = allowed[r_id]
- if(amount <= 0)
- if(amount == 0)
- if (O.reagents != null && O.reagents.has_reagent("nutriment"))
- beaker.reagents.add_reagent(r_id, min(O.reagents.get_reagent_amount("nutriment"), space))
- O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space))
- else
- if (O.reagents != null && O.reagents.has_reagent("nutriment"))
- beaker.reagents.add_reagent(r_id, min(round(O.reagents.get_reagent_amount("nutriment")*abs(amount)), space))
- O.reagents.remove_reagent("nutriment", min(O.reagents.get_reagent_amount("nutriment"), space))
- else
- O.reagents.trans_id_to(beaker, r_id, min(amount, space))
- if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
- break
- if(O.reagents.reagent_list.len == 0)
- remove_object(O)
- //Sheets
- else if(istype(I, /obj/item/stack/sheet))
- var/obj/item/stack/sheet/O = I
- var/list/allowed = get_allowed_by_obj(O)
- for(var/t in 1 to round(O.amount, 1))
- for(var/r_id in allowed)
- var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume
- var/amount = allowed[r_id]
- beaker.reagents.add_reagent(r_id,min(amount, space))
- if (space < amount)
- break
- if(t == round(O.amount, 1))
- remove_object(O)
- break
- //Plants
- else if(istype(I, /obj/item/grown))
- var/obj/item/grown/O = I
- var/list/allowed = get_allowed_by_obj(O)
- for (var/r_id in allowed)
- var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume
- var/amount = allowed[r_id]
- if (amount == 0)
- if (O.reagents != null && O.reagents.has_reagent(r_id))
- beaker.reagents.add_reagent(r_id,min(O.reagents.get_reagent_amount(r_id), space))
- else
- beaker.reagents.add_reagent(r_id,min(amount, space))
- if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
- break
- remove_object(O)
- else if(istype(I, /obj/item/slime_extract))
- var/obj/item/slime_extract/O = I
- var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume
- if (O.reagents != null)
- var/amount = O.reagents.total_volume
- O.reagents.trans_to(beaker, min(amount, space))
- if (O.Uses > 0)
- beaker.reagents.add_reagent("slimejelly",min(20, space))
- remove_object(O)
- if(istype(I, /obj/item/reagent_containers))
- var/obj/item/reagent_containers/O = I
- var/amount = O.reagents.total_volume
- O.reagents.trans_to(beaker, amount)
- if(!O.reagents.total_volume)
- remove_object(O)
- else if(istype(I, /obj/item/toy/crayon))
- var/obj/item/toy/crayon/O = I
- for (var/r_id in O.reagent_contents)
- var/space = beaker.reagents.maximum_volume - beaker.reagents.total_volume
- if(!space)
- break
- beaker.reagents.add_reagent(r_id, min(O.reagent_contents[r_id], space))
- remove_object(O)
+ if(I.grind_results)
+ grind_item(i)
+
+/obj/machinery/reagentgrinder/proc/grind_item(obj/item/I) //Grind results can be found in respective object definitions
+ if(I.on_grind(src) == -1) //Call on_grind() to change amount as needed, and stop grinding the item if it returns -1
+ to_chat(usr, "[src] shorts out as it tries to grind up [I], and transfers it back to storage.")
+ return
+ beaker.reagents.add_reagent_list(I.grind_results)
+ if(I.reagents)
+ I.reagents.trans_to(beaker, I.reagents.total_volume)
+ remove_object(I)
/obj/machinery/reagentgrinder/proc/mix(mob/user)
//For butter and other things that would change upon shaking or mixing
diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
index ddb08db032..99ce4afe83 100644
--- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm
@@ -129,31 +129,16 @@
taste_description = "sludge"
/datum/reagent/medicine/cryoxadone/on_mob_life(mob/living/M)
- switch(M.bodytemperature) // Low temperatures are required to take effect.
- if(0 to 100) // At extreme temperatures (upgraded cryo) the effect is greatly increased.
- M.status_flags &= ~DISFIGURED
- M.adjustCloneLoss(-1, 0)
- M.adjustOxyLoss(-9, 0)
- M.adjustBruteLoss(-5, 0)
- M.adjustFireLoss(-5, 0)
- M.adjustToxLoss(-5, 0)
- . = 1
- if(100 to 225) // At lower temperatures (cryo) the full effect is boosted
- M.status_flags &= ~DISFIGURED
- M.adjustCloneLoss(-1, 0)
- M.adjustOxyLoss(-7, 0)
- M.adjustBruteLoss(-3, 0)
- M.adjustFireLoss(-3, 0)
- M.adjustToxLoss(-3, 0)
- . = 1
- if(225 to T0C)
- M.status_flags &= ~DISFIGURED
- M.adjustCloneLoss(-1, 0)
- M.adjustOxyLoss(-5, 0)
- M.adjustBruteLoss(-1, 0)
- M.adjustFireLoss(-1, 0)
- M.adjustToxLoss(-1, 0)
- . = 1
+ var/power = -0.00003 * (M.bodytemperature ** 2) + 3
+ if(M.bodytemperature < T0C)
+ M.adjustOxyLoss(-3 * power, 0)
+ M.adjustBruteLoss(-power, 0)
+ M.adjustFireLoss(-power, 0)
+ M.adjustToxLoss(-power, 0)
+ M.adjustCloneLoss(-power, 0)
+ M.status_flags &= ~DISFIGURED
+ . = 1
+ metabolization_rate = REAGENTS_METABOLISM * (0.00001 * (M.bodytemperature ** 2) + 0.5)
..()
/datum/reagent/medicine/clonexadone
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index 8698c10b05..3182080ba3 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -80,8 +80,7 @@
..()
/obj/item/reagent_containers/fire_act(exposed_temperature, exposed_volume)
- reagents.chem_temp += 30
- reagents.handle_reactions()
+ reagents.expose_temperature(exposed_temperature)
..()
/obj/item/reagent_containers/throw_impact(atom/target)
@@ -128,6 +127,8 @@
/obj/item/reagent_containers/microwave_act(obj/machinery/microwave/M)
if(is_open_container())
- reagents.chem_temp = max(reagents.chem_temp, 1000)
- reagents.handle_reactions()
+ reagents.expose_temperature(1000)
..()
+
+/obj/item/reagent_containers/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ reagents.expose_temperature(exposed_temperature)
\ No newline at end of file
diff --git a/code/modules/reagents/reagent_containers/bottle.dm b/code/modules/reagents/reagent_containers/bottle.dm
index 6fad290676..749031b367 100644
--- a/code/modules/reagents/reagent_containers/bottle.dm
+++ b/code/modules/reagents/reagent_containers/bottle.dm
@@ -311,4 +311,4 @@
/obj/item/reagent_containers/glass/bottle/tuberculosiscure
name = "BVAK bottle"
desc = "A small bottle containing Bio Virus Antidote Kit."
- list_reagents = list("atropine" = 5, "epinephrine" = 5, "salbutamol" = 10, "spaceacillin" = 10)
\ No newline at end of file
+ list_reagents = list("atropine" = 5, "epinephrine" = 5, "salbutamol" = 10, "spaceacillin" = 10)
diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm
index df2df7c171..15f22feeb4 100644
--- a/code/modules/reagents/reagent_containers/glass.dm
+++ b/code/modules/reagents/reagent_containers/glass.dm
@@ -91,15 +91,9 @@
/obj/item/reagent_containers/glass/attackby(obj/item/I, mob/user, params)
var/hotness = I.is_hot()
- if(hotness)
- var/added_heat = (hotness / 100) //ishot returns a temperature
- if(reagents)
- if(reagents.chem_temp < hotness) //can't be heated to be hotter than the source
- reagents.chem_temp += added_heat
- to_chat(user, "You heat [src] with [I].")
- reagents.handle_reactions()
- else
- to_chat(user, "[src] is already hotter than [I]!")
+ if(hotness && reagents)
+ reagents.expose_temperature(hotness)
+ to_chat(user, "You heat [name] with [I]!")
if(istype(I, /obj/item/reagent_containers/food/snacks/egg)) //breaking eggs
var/obj/item/reagent_containers/food/snacks/egg/E = I
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index 324623edbd..5836186ee1 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -8,6 +8,7 @@
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
possible_transfer_amounts = list()
volume = 50
+ grind_results = list()
var/apply_type = INGEST
var/apply_method = "swallow"
var/roundstart = 0
@@ -151,4 +152,4 @@
desc = "I wouldn't eat this if I were you."
icon_state = "pill9"
color = "#454545"
- list_reagents = list("shadowmutationtoxin" = 1)
+ list_reagents = list("shadowmutationtoxin" = 1)
\ No newline at end of file
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index 789345ca77..6edcc44a3a 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -123,6 +123,13 @@
current_range = spray_range
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()
+ if(hotness && reagents)
+ reagents.expose_temperature(hotness)
+ to_chat(user, "You heat [name] with [I]!")
+ return ..()
+
/obj/item/reagent_containers/spray/verb/empty()
set name = "Empty Spray Bottle"
set category = "Object"
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index ed14ae63c1..aa41763cfa 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -29,7 +29,7 @@
if(make_from)
setDir(make_from.dir)
- make_from.loc = null
+ make_from.moveToNullspace()
stored = make_from
pressure_charging = FALSE // newly built disposal bins start with pump off
else
@@ -471,7 +471,7 @@
if(isobj(AM))
var/obj/O = AM
- O.loc = src
+ O.forceMove(src)
else if(ismob(AM))
var/mob/M = AM
if(prob(2)) // to prevent mobs being stuck in infinite loops
diff --git a/code/modules/recycling/disposal/pipe.dm b/code/modules/recycling/disposal/pipe.dm
index 28eefde453..355d5d6b96 100644
--- a/code/modules/recycling/disposal/pipe.dm
+++ b/code/modules/recycling/disposal/pipe.dm
@@ -190,6 +190,7 @@
deconstruct()
+// Straight/bent pipe segment
/obj/structure/disposalpipe/segment
icon_state = "pipe"
initialize_dirs = DISP_DIR_FLIP
diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm
index a66fdf7e03..38259b56d6 100644
--- a/code/modules/research/circuitprinter.dm
+++ b/code/modules/research/circuitprinter.dm
@@ -12,8 +12,6 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis).
circuit = /obj/item/circuitboard/machine/circuit_imprinter
var/efficiency_coeff
- var/console_link = TRUE //can this link to a console?
- var/requires_console = TRUE
var/datum/component/material_container/materials //Store for hyper speed!
@@ -32,11 +30,11 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis).
)
/obj/machinery/rnd/circuit_imprinter/Initialize()
- var/datum/component/material_container/materials
materials = AddComponent(/datum/component/material_container, list(MAT_GLASS, MAT_GOLD, MAT_DIAMOND, MAT_METAL, MAT_BLUESPACE), 0,
FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
materials.precise_insertion = TRUE
create_reagents(0)
+ RefreshParts()
return ..()
/obj/machinery/rnd/circuit_imprinter/RefreshParts()
@@ -119,11 +117,9 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis).
return TRUE
/obj/machinery/rnd/circuit_imprinter/proc/do_print(path, list/matlist, notify_admins)
- if(notify_admins)
- if(usr)
- usr.investigate_log("built [path] at a circuit imprinter.", INVESTIGATE_RESEARCH)
- var/turf/T = get_turf(usr)
- message_admins("[key_name(usr)][ADMIN_JMP(T)] has built [path] at a circuit imprinter at [COORD(usr)]")
+ if(notify_admins && usr)
+ investigate_log("[key_name(usr)] built [path] at a circuit imprinter.", INVESTIGATE_RESEARCH)
+ message_admins("[ADMIN_LOOKUPFLW(usr)] has built [path] at a circuit imprinter.")
var/obj/item/I = new path(get_turf(src))
I.materials = matlist.Copy()
- SSblackbox.record_feedback("nested_tally", "circuit_printed", 1, list("[type]", "[path]"))
+ SSblackbox.record_feedback("nested tally", "circuit_printed", 1, list("[type]", "[path]"))
diff --git a/code/modules/research/departmental_circuit_imprinter.dm b/code/modules/research/departmental_circuit_imprinter.dm
index bd3414884f..7c67bd44b7 100644
--- a/code/modules/research/departmental_circuit_imprinter.dm
+++ b/code/modules/research/departmental_circuit_imprinter.dm
@@ -4,10 +4,8 @@
icon_state = "circuit_imprinter"
container_type = OPENCONTAINER_1
circuit = /obj/item/circuitboard/machine/circuit_imprinter/department
- console_link = FALSE
requires_console = FALSE
- var/list/allowed_department_flags = DEPARTMENTAL_FLAG_ALL
var/list/datum/design/cached_designs
var/list/datum/design/matching_designs
var/department_tag = "Unidentified" //used for material distribution among other things.
@@ -145,8 +143,7 @@
/obj/machinery/rnd/circuit_imprinter/department/proc/ui_header()
var/list/l = list()
- l += "
Nanotrasen Department Circuit Imprinter: [department_tag]
"
- l += "Eject Item"
- l += "Name: [linked_destroy.loaded_item.name]"
- l += "Select a node to boost by deconstructing this item."
- l += "This item is able to boost:"
- var/list/listin = techweb_item_boost_check(linked_destroy.loaded_item)
- for(var/node_id in listin)
- var/datum/techweb_node/N = get_techweb_node_by_id(node_id)
- var/worth = listin[N.id]
- if(!stored_research.researched_nodes[N.id] && !stored_research.boosted_nodes[N.id])
- l += "[N.display_name]: [worth] points"
- else
- l += "[RDSCREEN_NOBREAK]"
+ l += "
[RDSCREEN_NOBREAK]"
+ l += "Select a node to boost by deconstructing this item. This item can boost:"
+
+ var/anything = FALSE
+ var/list/boostable_nodes = techweb_item_boost_check(linked_destroy.loaded_item)
+ for(var/id in boostable_nodes)
+ anything = TRUE
+ var/worth = boostable_nodes[id]
+ var/datum/techweb_node/N = get_techweb_node_by_id(id)
+
+ l += "
[RDSCREEN_NOBREAK]"
+ if (stored_research.researched_nodes[N.id]) // already researched
+ l += "[N.display_name]"
+ l += "This node has already been researched."
+ else if (worth == 0) // reveal only
+ if (stored_research.hidden_nodes[N.id])
+ l += "[N.display_name]"
+ l += "This node will be revealed."
+ else
+ l += "[N.display_name]"
+ l += "This node has already been revealed."
+ else // boost by the difference
+ var/difference = min(worth, N.research_cost) - stored_research.boosted_nodes[N.id]
+ if (difference > 0)
+ l += "[N.display_name]"
+ l += "This node will be boosted by [difference] points."
+ else
+ l += "[N.display_name]"
+ l += "This node has already been boosted."
+ l += "
[RDSCREEN_NOBREAK]"
+
+ // point deconstruction and material reclamation use the same ID to prevent accidentally missing the points
var/point_value = techweb_item_point_check(linked_destroy.loaded_item)
- if(point_value && isnull(stored_research.deconstructed_items[linked_destroy.loaded_item.type]))
- l += "Generic Point Deconstruction - [point_value] points"
- l += "Material Reclaimation Deconstruction"
+ if(point_value)
+ anything = TRUE
+ l += "
[RDSCREEN_NOBREAK]"
+ if (stored_research.deconstructed_items[linked_destroy.loaded_item.type])
+ l += "Point Deconstruction"
+ l += "This item's [point_value] point\s have already been claimed."
+ else
+ l += "Point Deconstruction"
+ l += "This item is worth [point_value] point\s!"
+ l += "
[RDSCREEN_NOBREAK]"
+
+ var/list/materials = linked_destroy.loaded_item.materials
+ if (materials.len)
+ l += "
Material Reclamation"
+ for (var/M in materials)
+ l += "* [CallMaterialName(M)] x [materials[M]]"
+ l += "
[RDSCREEN_NOBREAK]"
+ anything = TRUE
+
+ if (!anything)
+ l += "Nothing!"
+
l += "
"
return l
-/obj/machinery/computer/rdconsole/proc/ui_techweb() //Legacy code.
+/obj/machinery/computer/rdconsole/proc/ui_techweb()
var/list/l = list()
- var/list/avail = list() //This could probably be optimized a bit later.
- var/list/unavail = list()
- var/list/res = list()
- for(var/v in stored_research.researched_nodes)
- res += stored_research.researched_nodes[v]
- for(var/v in stored_research.available_nodes)
- if(stored_research.researched_nodes[v])
- continue
- avail += stored_research.available_nodes[v]
- for(var/v in stored_research.visible_nodes)
- if(stored_research.available_nodes[v])
- continue
- unavail += stored_research.visible_nodes[v]
- l += "
[RDSCREEN_NOBREAK]"
- else if(stored_research.visible_nodes[selected_node.id])
- l += "
Prerequisites not met!
[RDSCREEN_NOBREAK]"
- else
- l += "
ERROR
[RDSCREEN_NOBREAK]"
- l += "
Designs:
[RDSCREEN_NOBREAK]"
- for(var/i in selected_node.designs)
- var/datum/design/D = selected_node.designs[i]
- l += "[D.name]"
- l += "
Prerequisites:
[RDSCREEN_NOBREAK]"
- for(var/i in selected_node.prerequisites)
- var/datum/techweb_node/prereq = selected_node.prerequisites[i]
- var/sc = stored_research.researched_nodes[prereq.id]
- var/begin
- var/end
- if(sc)
- begin = ""
- end = ""
- else
- begin = ""
- end = ""
- l += "[begin][prereq.display_name][end]"
- l += "
Unlocks:
[RDSCREEN_NOBREAK]"
- for(var/i in selected_node.unlocks)
- var/datum/techweb_node/unlock = selected_node.unlocks[i]
- l += "[unlock.display_name]"
+ return
- l += "
[RDSCREEN_NOBREAK]"
+ l += "
[RDSCREEN_NOBREAK]"
+ if (length(selected_node.prerequisites))
+ l += "
Requires
[RDSCREEN_NOBREAK]"
+ l += "
Current Node
[RDSCREEN_NOBREAK]"
+ if (length(selected_node.unlocks))
+ l += "
Unlocks
[RDSCREEN_NOBREAK]"
+
+ l += "
[RDSCREEN_NOBREAK]"
+ if (length(selected_node.prerequisites))
+ l += "
[RDSCREEN_NOBREAK]"
+ for (var/i in selected_node.prerequisites)
+ l += ui_techweb_single_node(selected_node.prerequisites[i])
+ l += "
[RDSCREEN_NOBREAK]"
+ l += "
[RDSCREEN_NOBREAK]"
+ l += ui_techweb_single_node(selected_node, selflink=FALSE)
+ l += "
[RDSCREEN_NOBREAK]"
+ if (length(selected_node.unlocks))
+ l += "
[RDSCREEN_NOBREAK]"
+ for (var/i in selected_node.unlocks)
+ l += ui_techweb_single_node(selected_node.unlocks[i])
+ l += "
[RDSCREEN_NOBREAK]"
+
+ l += "
[RDSCREEN_NOBREAK]"
return l
/obj/machinery/computer/rdconsole/proc/ui_techweb_designview() //Legacy code
RDSCREEN_UI_SDESIGN_CHECK
var/list/l = list()
var/datum/design/D = selected_design
- l += "
Name: [D.name]"
+ l += "
[D.icon_html(usr)]
[D.name]
[RDSCREEN_NOBREAK]"
if(D.build_type)
- l += "Lathe Types:"
- if(D.build_type & IMPRINTER) l += "Circuit Imprinter"
- if(D.build_type & PROTOLATHE) l += "Protolathe"
- if(D.build_type & AUTOLATHE) l += "Autolathe"
- if(D.build_type & MECHFAB) l += "Exosuit Fabricator"
- if(D.build_type & BIOGENERATOR) l += "Biogenerator"
- if(D.build_type & LIMBGROWER) l += "Limbgrower"
- if(D.build_type & SMELTER) l += "Smelter"
- l += "Required Materials:"
+ var/lathes = list()
+ if(D.build_type & IMPRINTER)
+ lathes += "[machine_icon(/obj/machinery/rnd/circuit_imprinter)][RDSCREEN_NOBREAK]"
+ if (linked_imprinter && D.id in stored_research.researched_designs)
+ l += "Imprint"
+ if(D.build_type & PROTOLATHE)
+ lathes += "[machine_icon(/obj/machinery/rnd/protolathe)][RDSCREEN_NOBREAK]"
+ if (linked_lathe && D.id in stored_research.researched_designs)
+ l += "Construct"
+ if(D.build_type & AUTOLATHE)
+ lathes += "[machine_icon(/obj/machinery/autolathe)][RDSCREEN_NOBREAK]"
+ if(D.build_type & MECHFAB)
+ lathes += "[machine_icon(/obj/machinery/mecha_part_fabricator)][RDSCREEN_NOBREAK]"
+ if(D.build_type & BIOGENERATOR)
+ lathes += "[machine_icon(/obj/machinery/biogenerator)][RDSCREEN_NOBREAK]"
+ if(D.build_type & LIMBGROWER)
+ lathes += "[machine_icon(/obj/machinery/limbgrower)][RDSCREEN_NOBREAK]"
+ if(D.build_type & SMELTER)
+ lathes += "[machine_icon(/obj/machinery/mineral/processing_unit)][RDSCREEN_NOBREAK]"
+ l += "Construction types:"
+ l += lathes
+ l += ""
+ l += "Required materials:"
var/all_mats = D.materials + D.reagents_list
for(var/M in all_mats)
l += "* [CallMaterialName(M)] x [all_mats[M]]"
+ l += "Unlocked by:"
+ for (var/node in D.unlocked_by)
+ l += ui_techweb_single_node(node)
l += "[RDSCREEN_NOBREAK]
"
return l
@@ -710,6 +812,8 @@ doesn't have toxins access.
if(ls["switch_screen"])
back = screen
screen = text2num(ls["switch_screen"])
+ if(ls["ui_mode"])
+ ui_mode = text2num(ls["ui_mode"])
if(ls["lock_console"])
if(allowed(usr))
lock_console(usr)
@@ -862,7 +966,8 @@ doesn't have toxins access.
/obj/machinery/computer/rdconsole/interact(mob/user)
user.set_machine(src)
- var/datum/browser/popup = new(user, "rndconsole", name, 460, 550)
+ var/datum/browser/popup = new(user, "rndconsole", name, 900, 600)
+ popup.add_stylesheet("techwebs", 'html/browser/techwebs.css')
popup.set_content(generate_ui())
popup.open()
diff --git a/code/modules/research/rdmachines.dm b/code/modules/research/rdmachines.dm
index ad75ddf07b..ce98b911d3 100644
--- a/code/modules/research/rdmachines.dm
+++ b/code/modules/research/rdmachines.dm
@@ -1,5 +1,4 @@
-
//All devices that link into the R&D console fall into thise type for easy identification and some shared procs.
@@ -11,10 +10,13 @@
use_power = IDLE_POWER_USE
var/busy = FALSE
var/hacked = FALSE
+ var/console_link = TRUE //allow console link.
+ var/requires_console = TRUE
var/disabled = FALSE
var/shocked = FALSE
var/obj/machinery/computer/rdconsole/linked_console
var/obj/item/loaded_item = null //the item loaded inside the machine (currently only used by experimentor and destructive analyzer)
+ var/allowed_department_flags = ALL
/obj/machinery/rnd/proc/reset_busy()
busy = FALSE
@@ -78,28 +80,26 @@
/obj/machinery/rnd/proc/is_insertion_ready(mob/user)
if(panel_open)
to_chat(user, "You can't load [src] while it's opened!")
- return
- if (disabled)
- return
- if (!linked_console) // Try to auto-connect to new RnD consoles nearby.
- if(!linked_console)
- to_chat(user, "[src] must be linked to an R&D console first!")
- return
- if (busy)
+ return FALSE
+ if(disabled)
+ return FALSE
+ if(requires_console && !linked_console)
+ to_chat(user, "[src] must be linked to an R&D console first!")
+ return FALSE
+ if(busy)
to_chat(user, "[src] is busy right now.")
- return
+ return FALSE
if(stat & BROKEN)
to_chat(user, "[src] is broken.")
- return
+ return FALSE
if(stat & NOPOWER)
to_chat(user, "[src] has no power.")
- return
+ return FALSE
if(loaded_item)
to_chat(user, "[src] is already loaded.")
- return
+ return FALSE
return TRUE
-
//we eject the loaded item when deconstructing the machine
/obj/machinery/rnd/on_deconstruction()
if(loaded_item)
diff --git a/code/modules/research/stock_parts.dm b/code/modules/research/stock_parts.dm
index af1dc853d8..0e2e788b8f 100644
--- a/code/modules/research/stock_parts.dm
+++ b/code/modules/research/stock_parts.dm
@@ -82,7 +82,6 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
//Rating 1
-
/obj/item/stock_parts/capacitor
name = "capacitor"
desc = "A basic capacitor used in the construction of a variety of devices."
diff --git a/code/modules/research/techweb/__techweb_helpers.dm b/code/modules/research/techweb/__techweb_helpers.dm
index adfa5c78d0..af4fe7480b 100644
--- a/code/modules/research/techweb/__techweb_helpers.dm
+++ b/code/modules/research/techweb/__techweb_helpers.dm
@@ -130,6 +130,9 @@
CHECK_TICK
/proc/calculate_techweb_nodes()
+ for(var/design_id in SSresearch.techweb_designs)
+ var/datum/design/D = SSresearch.techweb_designs[design_id]
+ D.unlocked_by.Cut()
for(var/node_id in SSresearch.techweb_nodes)
var/datum/techweb_node/node = SSresearch.techweb_nodes[node_id]
node.prerequisites = list()
@@ -138,7 +141,9 @@
for(var/i in node.prereq_ids)
node.prerequisites[i] = SSresearch.techweb_nodes[i]
for(var/i in node.design_ids)
- node.designs[i] = SSresearch.techweb_designs[i]
+ var/datum/design/D = SSresearch.techweb_designs[i]
+ node.designs[i] = D
+ D.unlocked_by += node
if(node.hidden)
SSresearch.techweb_nodes_hidden[node.id] = node
CHECK_TICK
diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm
index 74ace7e4c2..d59dea55d3 100644
--- a/code/modules/research/techweb/_techweb.dm
+++ b/code/modules/research/techweb/_techweb.dm
@@ -17,6 +17,9 @@
var/id = "generic"
var/list/research_logs = list() //IC logs.
var/max_bomb_value = 0
+ var/organization = "Third-Party" //Organization name, used for display.
+ var/last_bitcoins = 0 //Current per-second production, used for display only.
+ var/list/tiers = list() //Assoc list, datum = number, 1 is available, 2 is all reqs are 1, so on
/datum/techweb/New()
for(var/i in SSresearch.techweb_nodes_starting)
@@ -28,6 +31,7 @@
/datum/techweb/admin
research_points = INFINITY //KEKKLES.
id = "ADMIN"
+ organization = "CentCom"
/datum/techweb/admin/New() //All unlocked.
. = ..()
@@ -38,6 +42,7 @@
/datum/techweb/science //Global science techweb for RND consoles.
id = "SCIENCE"
+ organization = "Nanotrasen"
/datum/techweb/Destroy()
researched_nodes = null
@@ -148,15 +153,31 @@
recalculate_nodes(TRUE) //Fully rebuild the tree.
/datum/techweb/proc/boost_with_path(datum/techweb_node/N, itempath)
- if(!istype(N)||!ispath(itempath))
+ if(!istype(N) || !ispath(itempath))
return FALSE
- var/boost = N.boost_item_paths[itempath]
- if(!boosted_nodes[N])
- boosted_nodes[N] = boost
- if(N.autounlock_by_boost)
- hidden_nodes -= N.id
+ boosted_nodes[N] = max(boosted_nodes[N], N.boost_item_paths[itempath])
+ if(N.autounlock_by_boost)
+ hidden_nodes -= N.id
return TRUE
+/datum/techweb/proc/update_tiers(datum/techweb_node/base)
+ var/list/current = list(base)
+ while (current.len)
+ var/list/next = list()
+ for (var/node_ in current)
+ var/datum/techweb_node/node = node_
+ var/tier = 0
+ if (!researched_nodes[node.id]) // researched is tier 0
+ for (var/id in node.prereq_ids)
+ var/prereq_tier = tiers[node.prerequisites[id]]
+ tier = max(tier, prereq_tier + 1)
+
+ if (tier != tiers[node])
+ tiers[node] = tier
+ for (var/id in node.unlocks)
+ next += node.unlocks[id]
+ current = next
+
/datum/techweb/proc/update_node_status(datum/techweb_node/node, autoupdate_consoles = TRUE)
var/researched = FALSE
var/available = FALSE
@@ -185,6 +206,7 @@
else
if(visible)
visible_nodes[node.id] = node
+ update_tiers(node)
if(autoupdate_consoles)
for(var/v in consoles_accessing)
var/obj/machinery/computer/rdconsole/V = v
diff --git a/code/modules/research/techweb/_techweb_node.dm b/code/modules/research/techweb/_techweb_node.dm
index 75faf07bf1..3ec6c4cf9d 100644
--- a/code/modules/research/techweb/_techweb_node.dm
+++ b/code/modules/research/techweb/_techweb_node.dm
@@ -23,8 +23,6 @@
actual_cost = research_cost
/datum/techweb_node/proc/get_price(datum/techweb/host)
- if(!host)
- return actual_cost
- var/discount = boost_item_paths[host.boosted_nodes[src]]
- actual_cost = research_cost - discount
+ if(host)
+ actual_cost = research_cost - host.boosted_nodes[src]
return actual_cost
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index 96b252854b..ba43a1c24b 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -1,6 +1,6 @@
//Current rate: 132500 research points in 90 minutes
-//Current cargo price: 250000 points for fullmaxed R&D.
+//Current cargo price: 280000 points for fullmaxed R&D.
//Base Node
/datum/techweb_node/base
@@ -9,7 +9,7 @@
display_name = "Basic Research Technology"
description = "NT default research technologies."
design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani",
- "destructive_analyzer", "protolathe", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab",
+ "destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab",
"space_heater") //Default research tech, prevents bricking
/////////////////////////Biotech/////////////////////////
@@ -18,7 +18,7 @@
display_name = "Biological Technology"
description = "What makes us tick." //the MC, silly!
prereq_ids = list("base")
- design_ids = list("mass_spectrometer", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "pandemic")
+ design_ids = list("chem_heater", "chem_master", "chem_dispenser", "sleeper", "pandemic")
research_cost = 2500
export_price = 10000
@@ -27,7 +27,16 @@
display_name = "Advanced Biotechnology"
description = "Advanced Biotechnology"
prereq_ids = list("biotech")
- design_ids = list("piercesyringe", "adv_mass_spectrometer", "plasmarefiller", "limbgrower")
+ design_ids = list("piercesyringe", "plasmarefiller", "limbgrower")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/bio_process
+ id = "bio_process"
+ display_name = "Biological Processing"
+ description = "From slimes to kitchens."
+ prereq_ids = list("biotech")
+ design_ids = list("smartfridge", "gibber", "deepfryer", "monkey_recycler", "processor", "gibber", "microwave")
research_cost = 2500
export_price = 10000
@@ -52,8 +61,8 @@
/////////////////////////engineering tech/////////////////////////
/datum/techweb_node/engineering
id = "engineering"
- description = "Modern Engineering Technology."
display_name = "Industrial Engineering"
+ description = "A refresher course on modern engineering technology."
prereq_ids = list("base")
design_ids = list("solarcontrol", "recharger", "powermonitor", "rped", "pacman", "adv_capacitor", "adv_scanning", "emitter", "high_cell", "adv_matter_bin",
"atmosalerts", "atmos_control", "recycler", "autolathe", "high_micro_laser", "nano_mani", "weldingmask", "mesons", "thermomachine", "tesla_coil", "grounding_rod", "apc_control")
@@ -62,13 +71,31 @@
/datum/techweb_node/adv_engi
id = "adv_engi"
- description = "Advanced Engineering research"
display_name = "Advanced Engineering"
+ description = "Pushing the boundaries of physics, one chainsaw-fist at a time."
prereq_ids = list("engineering", "emp_basic")
design_ids = list("engine_goggles", "diagnostic_hud", "magboots")
research_cost = 2500
export_price = 10000
+/datum/techweb_node/high_efficiency
+ id = "high_efficiency"
+ display_name = "High Efficiency Parts"
+ description = "Finely-tooled manufacturing techniques allowing for picometer-perfect precision levels."
+ prereq_ids = list("engineering", "datatheory")
+ design_ids = list("pico_mani", "super_matter_bin")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/adv_power
+ id = "adv_power"
+ display_name = "Advanced Power Manipulation"
+ description = "How to get more zap."
+ prereq_ids = list("engineering")
+ design_ids = list("smes", "super_cell", "hyper_cell", "super_capacitor", "superpacman", "mrspacman", "power_turbine", "power_turbine_console", "power_compressor")
+ research_cost = 2500
+ export_price = 10000
+
/////////////////////////Bluespace tech/////////////////////////
/datum/techweb_node/bluespace_basic //Bluespace-memery
id = "bluespace_basic"
@@ -89,6 +116,26 @@
research_cost = 2500
export_price = 10000
+/datum/techweb_node/practical_bluespace
+ id = "practical_bluespace"
+ display_name = "Applied Bluespace Research"
+ description = "Using bluespace to make things faster and better."
+ prereq_ids = list("bluespace_basic", "engineering")
+ design_ids = list("bs_rped","minerbag_holding", "telesci_gps", "bluespacebeaker", "bluespacesyringe", "bluespacebodybag", "phasic_scanning")
+ research_cost = 2500
+ export_price = 10000
+
+
+/datum/techweb_node/bluespace_power
+ id = "bluespace_power"
+ display_name = "Bluespace Power Technology"
+ description = "Even more powerful.. power!"
+ prereq_ids = list("adv_power", "adv_bluespace")
+ design_ids = list("bluespace_cell", "quadratic_capacitor")
+ research_cost = 2500
+ export_price = 10000
+
+
/////////////////////////plasma tech/////////////////////////
/datum/techweb_node/basic_plasma
id = "basic_plasma"
@@ -127,112 +174,6 @@
research_cost = 2500
export_price = 10000
-/////////////////////////EMP tech/////////////////////////
-/datum/techweb_node/emp_basic //EMP tech for some reason
- id = "emp_basic"
- display_name = "Electromagnetic Theory"
- description = "Study into usage of frequencies in the electromagnetic spectrum."
- prereq_ids = list("base")
- design_ids = list("holosign", "inducer", "tray_goggles", "holopad")
- research_cost = 2500
- export_price = 10000
-
-/datum/techweb_node/emp_adv
- id = "emp_adv"
- display_name = "Advanced Electromagnetic Theory"
- prereq_ids = list("emp_basic")
- design_ids = list("ultra_micro_laser")
- research_cost = 2500
- export_price = 10000
-
-/datum/techweb_node/emp_super
- id = "emp_super"
- display_name = "Quantum Electromagnetic Technology" //bs
- description = "Even better electromagnetic technology"
- prereq_ids = list("emp_adv")
- design_ids = list("quadultra_micro_laser")
- research_cost = 2500
- export_price = 10000
-
-/////////////////////////Clown tech/////////////////////////
-/datum/techweb_node/clown
- id = "clown"
- display_name = "Clown Technology"
- description = "Honk?!"
- prereq_ids = list("base")
- design_ids = list("air_horn", "honker_main", "honker_peri", "honker_targ", "honk_chassis", "honk_head", "honk_torso", "honk_left_arm", "honk_right_arm",
- "honk_left_leg", "honk_right_leg", "mech_banana_mortar", "mech_mousetrap_mortar", "mech_honker", "mech_punching_face", "implant_trombone")
- research_cost = 2500
- export_price = 10000
-
-////////////////////////Computer tech////////////////////////
-/datum/techweb_node/comptech
- id = "comptech"
- display_name = "Computer Consoles"
- description = "Computers and how they work."
- prereq_ids = list("datatheory")
- design_ids = list("cargo", "cargorequest", "stockexchange", "libraryconsole", "aifixer", "mining", "crewconsole", "comconsole", "idcardconsole", "operating", "seccamera")
- research_cost = 2500
- export_price = 10000
-
-/datum/techweb_node/computer_hardware_basic //Modular computers are shitty and nearly useless so until someone makes them actually useful this can be easy to get.
- id = "computer_hardware_basic"
- display_name = "Computer Hardware"
- description = "How computer hardware are made."
- prereq_ids = list("comptech")
- research_cost = 2500
- export_price = 10000
- design_ids = list("hdd_basic", "hdd_advanced", "hdd_super", "hdd_cluster", "ssd_small", "ssd_micro", "netcard_basic", "netcard_advanced", "netcard_wired",
- "portadrive_basic", "portadrive_advanced", "portadrive_super", "cardslot", "aislot", "miniprinter", "APClink", "bat_control", "bat_normal", "bat_advanced",
- "bat_super", "bat_micro", "bat_nano", "cpu_normal", "pcpu_normal", "cpu_small", "pcpu_small")
-
-/datum/techweb_node/computer_board_gaming
- id = "computer_board_gaming"
- display_name = "Arcade Games"
- description = "For the slackers on the station."
- prereq_ids = list("comptech")
- design_ids = list("arcade_battle", "arcade_orion", "slotmachine")
- research_cost = 2500
- export_price = 10000
-
-/datum/techweb_node/comp_recordkeeping
- id = "comp_recordkeeping"
- display_name = "Computerized Recordkeeping"
- description = "Organized record databases and how they're used."
- prereq_ids = list("comptech")
- design_ids = list("secdata", "med_data", "prisonmanage", "vendor", "automated_announcement")
- research_cost = 2500
- export_price = 10000
-
-/datum/techweb_node/telecomms
- id = "telecomms"
- display_name = "Telecommunications Technology"
- description = "Subspace transmission technology for near-instant communications devices."
- prereq_ids = list("comptech", "bluespace_basic")
- research_cost = 2500
- export_price = 10000
- design_ids = list("s-receiver", "s-bus", "s-broadcaster", "s-processor", "s-hub", "s-server", "s-relay", "comm_monitor", "comm_server",
- "s-ansible", "s-filter", "s-amplifier", "ntnet_relay", "s-treatment", "s-analyzer", "s-crystal", "s-transmitter")
-
-/datum/techweb_node/integrated_HUDs
- id = "integrated_HUDs"
- display_name = "Integrated HUDs"
- description = "The usefulness of computerized records, projected straight onto your eyepiece!"
- prereq_ids = list("comp_recordkeeping", "emp_basic")
- design_ids = list("health_hud", "security_hud", "diagnostic_hud", "scigoggles")
- research_cost = 2500
- export_price = 10000
-
-/datum/techweb_node/NVGtech
- id = "NVGtech"
- display_name = "Night Vision Technology"
- description = "Allows seeing in the dark without actual light!"
- prereq_ids = list("integrated_HUDs", "adv_engi", "emp_adv")
- design_ids = list("health_hud_night", "security_hud_night", "diagnostic_hud_night", "night_visision_goggles", "nvgmesons")
- research_cost = 2500
- export_price = 10000
-
-////////////////////////AI & Cyborg tech////////////////////////
/datum/techweb_node/neural_programming
id = "neural_programming"
display_name = "Neural Programming"
@@ -281,7 +222,7 @@
/datum/techweb_node/cyborg_upg_med
id = "cyborg_upg_med"
display_name = "Cyborg Upgrades: Medical"
- description = "Medical upgrades for cyborgs"
+ description = "Medical upgrades for cyborgs."
prereq_ids = list("adv_biotech", "cyborg")
design_ids = list("borg_upgrade_defibrillator", "borg_upgrade_piercinghypospray", "borg_upgrade_highstrengthsynthesiser", "borg_upgrade_expandedsynthesiser")
research_cost = 2500
@@ -291,7 +232,7 @@
id = "cyborg_upg_combat"
display_name = "Cyborg Upgrades: Combat"
description = "Military grade upgrades for cyborgs."
- prereq_ids = list("adv_robotics", "adv_engi")
+ prereq_ids = list("adv_robotics", "adv_engi" , "weaponry")
design_ids = list("borg_upgrade_vtec", "borg_upgrade_disablercooler")
research_cost = 2500
export_price = 10000
@@ -307,6 +248,112 @@
research_cost = 2500
export_price = 10000
+/////////////////////////EMP tech/////////////////////////
+/datum/techweb_node/emp_basic //EMP tech for some reason
+ id = "emp_basic"
+ display_name = "Electromagnetic Theory"
+ description = "Study into usage of frequencies in the electromagnetic spectrum."
+ prereq_ids = list("base")
+ design_ids = list("holosign", "inducer", "tray_goggles", "holopad")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/emp_adv
+ id = "emp_adv"
+ display_name = "Advanced Electromagnetic Theory"
+ description = "Determining whether reversing the polarity will actually help in a given situation."
+ prereq_ids = list("emp_basic")
+ design_ids = list("ultra_micro_laser")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/emp_super
+ id = "emp_super"
+ display_name = "Quantum Electromagnetic Technology" //bs
+ description = "Even better electromagnetic technology."
+ prereq_ids = list("emp_adv")
+ design_ids = list("quadultra_micro_laser")
+ research_cost = 2500
+ export_price = 10000
+
+/////////////////////////Clown tech/////////////////////////
+/datum/techweb_node/clown
+ id = "clown"
+ display_name = "Clown Technology"
+ description = "Honk?!"
+ prereq_ids = list("base")
+ design_ids = list("air_horn", "honker_main", "honker_peri", "honker_targ", "honk_chassis", "honk_head", "honk_torso", "honk_left_arm", "honk_right_arm",
+ "honk_left_leg", "honk_right_leg", "mech_banana_mortar", "mech_mousetrap_mortar", "mech_honker", "mech_punching_face", "implant_trombone")
+ research_cost = 2500
+ export_price = 10000
+
+////////////////////////Computer tech////////////////////////
+/datum/techweb_node/comptech
+ id = "comptech"
+ display_name = "Computer Consoles"
+ description = "Computers and how they work."
+ prereq_ids = list("datatheory")
+ design_ids = list("cargo", "cargorequest", "stockexchange", "libraryconsole", "aifixer", "mining", "crewconsole", "comconsole", "idcardconsole", "operating", "seccamera")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/computer_hardware_basic //Modular computers are shitty and nearly useless so until someone makes them actually useful this can be easy to get.
+ id = "computer_hardware_basic"
+ display_name = "Computer Hardware"
+ description = "How computer hardware are made."
+ prereq_ids = list("comptech")
+ research_cost = 2500
+ export_price = 10000
+ design_ids = list("hdd_basic", "hdd_advanced", "hdd_super", "hdd_cluster", "ssd_small", "ssd_micro", "netcard_basic", "netcard_advanced", "netcard_wired",
+ "portadrive_basic", "portadrive_advanced", "portadrive_super", "cardslot", "aislot", "miniprinter", "APClink", "bat_control", "bat_normal", "bat_advanced",
+ "bat_super", "bat_micro", "bat_nano", "cpu_normal", "pcpu_normal", "cpu_small", "pcpu_small")
+
+/datum/techweb_node/computer_board_gaming
+ id = "computer_board_gaming"
+ display_name = "Arcade Games"
+ description = "For the slackers on the station."
+ prereq_ids = list("comptech")
+ design_ids = list("arcade_battle", "arcade_orion", "slotmachine")
+ research_cost = 1000
+ export_price = 10000
+
+/datum/techweb_node/comp_recordkeeping
+ id = "comp_recordkeeping"
+ display_name = "Computerized Recordkeeping"
+ description = "Organized record databases and how they're used."
+ prereq_ids = list("comptech")
+ design_ids = list("secdata", "med_data", "prisonmanage", "vendor", "automated_announcement")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/telecomms
+ id = "telecomms"
+ display_name = "Telecommunications Technology"
+ description = "Subspace transmission technology for near-instant communications devices."
+ prereq_ids = list("comptech", "bluespace_basic")
+ research_cost = 2500
+ export_price = 10000
+ design_ids = list("s-receiver", "s-bus", "s-broadcaster", "s-processor", "s-hub", "s-server", "s-relay", "comm_monitor", "comm_server",
+ "s-ansible", "s-filter", "s-amplifier", "ntnet_relay", "s-treatment", "s-analyzer", "s-crystal", "s-transmitter")
+
+/datum/techweb_node/integrated_HUDs
+ id = "integrated_HUDs"
+ display_name = "Integrated HUDs"
+ description = "The usefulness of computerized records, projected straight onto your eyepiece!"
+ prereq_ids = list("comp_recordkeeping", "emp_basic")
+ design_ids = list("health_hud", "security_hud", "diagnostic_hud", "scigoggles")
+ research_cost = 2500
+ export_price = 10000
+
+/datum/techweb_node/NVGtech
+ id = "NVGtech"
+ display_name = "Night Vision Technology"
+ description = "Allows seeing in the dark without actual light!"
+ prereq_ids = list("integrated_HUDs", "adv_engi", "emp_adv")
+ design_ids = list("health_hud_night", "security_hud_night", "diagnostic_hud_night", "night_visision_goggles", "nvgmesons")
+ research_cost = 2500
+ export_price = 10000
+
////////////////////////Medical////////////////////////
/datum/techweb_node/cloning
id = "cloning"
@@ -323,7 +370,7 @@
description = "Smart freezing of objects to preserve them!"
prereq_ids = list("adv_engi", "emp_basic", "biotech")
design_ids = list("splitbeaker", "noreactsyringe", "cryotube", "cryo_Grenade")
- research_cost = 2500
+ research_cost = 2000
export_price = 10000
/datum/techweb_node/subdermal_implants
@@ -357,7 +404,7 @@
id = "adv_cyber_implants"
display_name = "Advanced Cybernetic Implants"
description = "Upgraded and more powerful cybernetic implants."
- prereq_ids = list("neural_programming", "cyber_implants")
+ prereq_ids = list("neural_programming", "cyber_implants","integrated_HUDs")
design_ids = list("ci-toolset", "ci-surgery", "ci-reviver")
research_cost = 2500
export_price = 10000
@@ -366,40 +413,11 @@
id = "combat_cyber_implants"
display_name = "Combat Cybernetic Implants"
description = "Military grade combat implants to improve performance."
- prereq_ids = list("adv_cyber_implants") //Needs way more reqs.
+ prereq_ids = list("adv_cyber_implants","weaponry","NVGtech","high_efficiency")
design_ids = list("ci-xray", "ci-thermals", "ci-antidrop", "ci-antistun", "ci-thrusters")
research_cost = 2500
export_price = 10000
-////////////////////////generic biotech////////////////////////
-/datum/techweb_node/bio_process
- id = "bio_process"
- display_name = "Biological Processing"
- description = "From slimes to kitchens."
- prereq_ids = list("biotech")
- design_ids = list("smartfridge", "gibber", "deepfryer", "monkey_recycler", "processor", "gibber", "microwave")
- research_cost = 2500
- export_price = 10000
-
-////////////////////////generic engineering////////////////////////
-/datum/techweb_node/high_efficiency
- id = "high_efficiency"
- display_name = "High Efficiency Parts"
- description = "High Efficiency Parts"
- prereq_ids = list("engineering", "datatheory")
- design_ids = list("pico_mani", "super_matter_bin")
- research_cost = 2500
- export_price = 10000
-
-/datum/techweb_node/adv_power
- id = "adv_power"
- display_name = "Advanced Power Manipulation"
- description = "How to get more zap."
- prereq_ids = list("engineering")
- design_ids = list("smes", "super_cell", "hyper_cell", "super_capacitor", "superpacman", "mrspacman", "power_turbine", "power_turbine_console", "power_compressor")
- research_cost = 2500
- export_price = 10000
-
////////////////////////Tools////////////////////////
/datum/techweb_node/basic_mining
id = "basic_mining"
@@ -419,15 +437,6 @@
research_cost = 2500
export_price = 10000
-/datum/techweb_node/practical_bluespace
- id = "practical_bluespace"
- display_name = "Applied Bluespace Research"
- description = "Using bluespace to make things faster and better."
- prereq_ids = list("bluespace_basic", "engineering")
- design_ids = list("bs_rped","minerbag_holding", "telesci_gps", "bluespacebeaker", "bluespacesyringe", "bluespacebodybag", "phasic_scanning")
- research_cost = 2500
- export_price = 10000
-
/datum/techweb_node/janitor
id = "janitor"
display_name = "Advanced Sanitation Technology"
@@ -455,22 +464,13 @@
research_cost = 2500
export_price = 10000
-/datum/techweb_node/exp_equipment
- id = "exp_equipment"
+/datum/techweb_node/exp_flight
+ id = "exp_flight"
display_name = "Experimental Flight Equipment"
description = "Highly advanced construction tools."
design_ids = list("flightshoes", "flightpack", "flightsuit")
- prereq_ids = list("adv_engi")
- research_cost = 2500
- export_price = 10000
-
-/datum/techweb_node/bluespace_power
- id = "bluespace_power"
- display_name = "Bluespace Power Technology"
- description = "Even more powerful.. power!"
- prereq_ids = list("adv_power", "adv_bluespace")
- design_ids = list("bluespace_cell", "quadratic_capacitor")
- research_cost = 2500
+ prereq_ids = list("adv_engi","integrated_HUDs", "adv_power" , "high_efficiency")
+ research_cost = 5000
export_price = 10000
/////////////////////////weaponry tech/////////////////////////
@@ -496,7 +496,7 @@
id = "electronic_weapons"
display_name = "Electric Weapons"
description = "Weapons using electric technology"
- prereq_ids = list("weaponry", "adv_power")
+ prereq_ids = list("weaponry", "adv_power" , "emp_basic")
design_ids = list("stunrevolver", "stunshell", "tele_shield")
research_cost = 2500
export_price = 10000
@@ -506,7 +506,7 @@
display_name = "Radioactive Weaponry"
description = "Weapons using radioactive technology."
prereq_ids = list("adv_engi", "adv_weaponry")
- design_ids = list("nuclear_gun", "decloner")
+ design_ids = list("nuclear_gun")
research_cost = 2500
export_price = 10000
@@ -586,8 +586,8 @@
/datum/techweb_node/adv_mecha
id = "adv_mecha"
- display_name = "Mechanical Exosuits"
- description = "Mechanized exosuits that are several magnitudes stronger and more powerful than the average human."
+ display_name = "Advanced Exosuits"
+ description = "For when you just aren't Gundam enough."
prereq_ids = list("adv_robotics", "mecha")
design_ids = list("mech_repair_droid")
research_cost = 2500
@@ -627,7 +627,7 @@
id = "mecha_phazon"
display_name = "EXOSUIT: Phazon"
description = "Phazon exosuit designs"
- prereq_ids = list("adv_mecha", "weaponry")
+ prereq_ids = list("adv_mecha", "weaponry" , "adv_bluespace")
design_ids = list("phazon_chassis", "phazon_torso", "phazon_head", "phazon_left_arm", "phazon_right_arm", "phazon_left_leg", "phazon_right_leg", "phazon_main",
"phazon_peri", "phazon_targ", "phazon_armor")
research_cost = 2500
@@ -637,7 +637,7 @@
id = "mech_tools"
display_name = "Basic Exosuit Equipment"
description = "Various tools fit for basic mech units"
- prereq_ids = list("mecha", "engineering")
+ prereq_ids = list("mecha")
design_ids = list("mech_drill", "mech_mscanner", "mech_extinguisher", "mech_cable_layer")
research_cost = 2500
export_price = 10000
@@ -646,7 +646,7 @@
id = "adv_mecha_tools"
display_name = "Advanced Exosuit Equipment"
description = "Tools for high level mech suits"
- prereq_ids = list("adv_mecha", "mech_tools", "adv_engi")
+ prereq_ids = list("adv_mecha", "mech_tools")
design_ids = list("mech_rcd")
research_cost = 2500
export_price = 10000
@@ -662,9 +662,9 @@
/datum/techweb_node/mech_modules
id = "adv_mecha_modules"
- display_name = "Basic Exosuit Modules"
+ display_name = "Simple Exosuit Modules"
description = "An advanced piece of mech weaponry"
- prereq_ids = list("adv_mecha", "adv_power")
+ prereq_ids = list("adv_mecha", "bluespace_power")
design_ids = list("mech_energy_relay", "mech_ccw_armor", "mech_proj_armor", "mech_generator_nuclear")
research_cost = 2500
export_price = 10000
@@ -779,7 +779,7 @@
/datum/techweb_node/mech_lmg
id = "mech_lmg"
- display_name = "Exosuit Weapon (PBT \"Pacifier\" Mounted Taser)"
+ display_name = "Exosuit Weapon (\"Ultra AC 2\" LMG)"
description = "An advanced piece of mech weaponry"
prereq_ids = list("adv_mecha", "adv_weaponry", "ballistic_weapons")
design_ids = list("mech_lmg")
@@ -800,12 +800,12 @@
id = "alientech"
display_name = "Alien Technology"
description = "Things used by the greys."
- prereq_ids = list("base")
+ prereq_ids = list("biotech","engineering")
boost_item_paths = list(/obj/item/gun/energy/alien = 0, /obj/item/scalpel/alien = 0, /obj/item/hemostat/alien = 0, /obj/item/retractor/alien = 0, /obj/item/circular_saw/alien = 0,
/obj/item/cautery/alien = 0, /obj/item/surgicaldrill/alien = 0, /obj/item/screwdriver/abductor = 0, /obj/item/wrench/abductor = 0, /obj/item/crowbar/abductor = 0, /obj/item/device/multitool/abductor = 0,
/obj/item/weldingtool/abductor = 0, /obj/item/wirecutters/abductor = 0, /obj/item/circuitboard/machine/abductor = 0, /obj/item/abductor_baton = 0, /obj/item/device/abductor = 0)
- research_cost = 2500
- export_price = 10000
+ research_cost = 5000
+ export_price = 20000
hidden = TRUE
design_ids = list("alienalloy")
@@ -813,13 +813,13 @@
id = "alien_bio"
display_name = "Alien Biological Tools"
description = "Advanced biological tools."
- prereq_ids = list("alientech", "biotech")
+ prereq_ids = list("alientech", "adv_biotech")
design_ids = list("alien_scalpel", "alien_hemostat", "alien_retractor", "alien_saw", "alien_drill", "alien_cautery")
boost_item_paths = list(/obj/item/gun/energy/alien = 0, /obj/item/scalpel/alien = 0, /obj/item/hemostat/alien = 0, /obj/item/retractor/alien = 0, /obj/item/circular_saw/alien = 0,
/obj/item/cautery/alien = 0, /obj/item/surgicaldrill/alien = 0, /obj/item/screwdriver/abductor = 0, /obj/item/wrench/abductor = 0, /obj/item/crowbar/abductor = 0, /obj/item/device/multitool/abductor = 0,
/obj/item/weldingtool/abductor = 0, /obj/item/wirecutters/abductor = 0, /obj/item/circuitboard/machine/abductor = 0, /obj/item/abductor_baton = 0, /obj/item/device/abductor = 0)
research_cost = 2500
- export_price = 10000
+ export_price = 20000
hidden = TRUE
/datum/techweb_node/alien_engi
@@ -831,9 +831,38 @@
/obj/item/weldingtool/abductor = 0, /obj/item/wirecutters/abductor = 0, /obj/item/circuitboard/machine/abductor = 0, /obj/item/abductor_baton = 0, /obj/item/device/abductor = 0)
design_ids = list("alien_wrench", "alien_wirecutters", "alien_screwdriver", "alien_crowbar", "alien_welder", "alien_multitool")
research_cost = 2500
+ export_price = 20000
+ hidden = TRUE
+
+/datum/techweb_node/syndicate_basic
+ id = "syndicate_basic"
+ display_name = "Illegal Technology"
+ description = "Dangerous research used to create dangerous objects."
+ prereq_ids = list("adv_engi", "adv_weaponry", "explosive_weapons")
+ design_ids = list("decloner", "borg_syndicate_module", "suppressor", "largecrossbow")
+ research_cost = 10000
export_price = 10000
hidden = TRUE
+/datum/techweb_node/syndicate_basic/New() //Crappy way of making syndicate gear decon supported until there's another way.
+ . = ..()
+ boost_item_paths = list()
+ for(var/cat in GLOB.uplink_items)
+ var/list/l = cat
+ for(var/i in l)
+ var/datum/uplink_item/UI = i
+ boost_item_paths[UI.item] = 0 //allows deconning to unlock.
+
+//HELPERS
+/proc/total_techweb_exports()
+ var/list/datum/techweb_node/processing = list()
+ for(var/i in subtypesof(/datum/techweb_node))
+ processing += new i
+ . = 0
+ for(var/i in processing)
+ var/datum/techweb_node/TN = i
+ . += TN.export_price
+
/proc/total_techweb_points()
var/list/datum/techweb_node/processing = list()
for(var/i in subtypesof(/datum/techweb_node))
@@ -842,19 +871,3 @@
for(var/i in processing)
var/datum/techweb_node/TN = i
. += TN.research_cost
-
-/*
-/datum/design/borg_syndicate_module
- name = "Cyborg Upgrade (Illegal Modules)"
- id = "borg_syndicate_module"
- construction_time = 120
-
-/datum/design/suppressor
- name = "Universal Suppressor"
- id = "suppressor"
-
-/datum/design/largecrossbow
- name = "Energy Crossbow"
- id = "largecrossbow"
- build_path = /obj/item/gun/energy/kinetic_accelerator/crossbow/large
-*/
\ No newline at end of file
diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm
index cf250f50f1..09f241609e 100644
--- a/code/modules/research/xenobiology/xenobiology.dm
+++ b/code/modules/research/xenobiology/xenobiology.dm
@@ -12,6 +12,7 @@
throw_speed = 3
throw_range = 6
container_type = INJECTABLE_1
+ grind_results = list()
var/Uses = 1 // uses before it goes inert
var/qdel_timer = null // deletion timer, for delayed reactions
@@ -29,6 +30,10 @@
. = ..()
create_reagents(100)
+/obj/item/slime_extract/on_grind()
+ if(Uses)
+ grind_results["slimejelly"] = 20
+
/obj/item/slime_extract/grey
name = "grey slime extract"
icon_state = "grey slime extract"
@@ -467,7 +472,7 @@
desc = "A golem's head."
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
flags_1 = ABSTRACT_1 | NODROP_1
-
+
/obj/item/stack/tile/bluespace
name = "bluespace floor tile"
singular_name = "floor tile"
diff --git a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm
index ce467a1181..e5c36d09c4 100644
--- a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm
+++ b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm
@@ -399,7 +399,7 @@ GLOBAL_DATUM(necropolis_gate, /obj/structure/necropolis_gate/legion_gate)
name = "burnt stone surrounding tile"
icon_state = "burnt_surrounding_tile1"
tile_key = "burnt_surrounding_tile"
-
+
#undef STABLE
#undef COLLAPSE_ON_CROSS
#undef DESTROY_ON_CROSS
diff --git a/code/modules/ruins/spaceruin_code/listeningstation.dm b/code/modules/ruins/spaceruin_code/listeningstation.dm
index 0c2ec7817d..5afdc602b8 100644
--- a/code/modules/ruins/spaceruin_code/listeningstation.dm
+++ b/code/modules/ruins/spaceruin_code/listeningstation.dm
@@ -24,7 +24,7 @@
/obj/item/paper/fluff/ruins/listeningstation/reports/june
name = "june report"
- info = "Nanotrasen communications have been noticably less frequent recently. The pirate radio station I found last month has been transmitting pro-Nanotrasen propaganda. I will continue to monitor it."
+ info = "Nanotrasen communications have been noticeably less frequent recently. The pirate radio station I found last month has been transmitting pro-Nanotrasen propaganda. I will continue to monitor it."
/obj/item/paper/fluff/ruins/listeningstation/reports/may
name = "may report"
diff --git a/code/modules/ruins/spaceruin_code/oldstation.dm b/code/modules/ruins/spaceruin_code/oldstation.dm
index edea4fe0c1..d023760061 100644
--- a/code/modules/ruins/spaceruin_code/oldstation.dm
+++ b/code/modules/ruins/spaceruin_code/oldstation.dm
@@ -44,6 +44,6 @@
/obj/item/paper/fluff/ruins/oldstation/report
name = "Crew Reawakening Report"
info = "Artifical Program's report to surviving crewmembers.
Crew were placed into cryostasis on March 10th, 2445.
Crew were awoken from cryostasis around June, 2557.
\
- SIGNIFICANT EVENTS OF NOTE 1: The primary radiation detectors were taken offline after 112 years due to power failure, secondary radioation detectors showed no residual \
- radioation on station. Deduction, primariy detector was malfunctioning and was producing a radioation signal when there was none.
2: A data burst from a nearby Nanotrasen Space \
+ SIGNIFICANT EVENTS OF NOTE 1: The primary radiation detectors were taken offline after 112 years due to power failure, secondary radiation detectors showed no residual \
+ radiation on station. Deduction, primarily detector was malfunctioning and was producing a radiation signal when there was none.
2: A data burst from a nearby Nanotrasen Space \
Station was recieved, this data burst contained research data that has been uploaded to our RnD labs.
3: Unknown invasion force has occupied Delta station."
diff --git a/code/modules/ruins/spaceruin_code/spacehotel.dm b/code/modules/ruins/spaceruin_code/spacehotel.dm
index 5f20bafb68..69eebd8535 100644
--- a/code/modules/ruins/spaceruin_code/spacehotel.dm
+++ b/code/modules/ruins/spaceruin_code/spacehotel.dm
@@ -7,6 +7,6 @@
/obj/item/paper/pamphlet/ruin/spacehotel
name = "hotel pamphlet"
- info = "
The Twin Nexus Hotel
A place of Sanctuary
Welcome to The Twin-Nexus Hotel, \[insert name here]! The loyal staff stride to their best effort to cater for the best possible experience for all space(wo)men! If you have any questions or comments, please ask one of our on-board staff for more infomation.
"
+ info = "
The Twin Nexus Hotel
A place of Sanctuary
Welcome to The Twin-Nexus Hotel, \[insert name here]! The loyal staff stride to their best effort to cater for the best possible experience for all space(wo)men! If you have any questions or comments, please ask one of our on-board staff for more information.
"
diff --git a/code/modules/security_levels/security_levels.dm b/code/modules/security_levels/security_levels.dm
index 2c0ffd3a34..5f2cc3d9ea 100644
--- a/code/modules/security_levels/security_levels.dm
+++ b/code/modules/security_levels/security_levels.dm
@@ -76,7 +76,7 @@ GLOBAL_VAR_INIT(security_level, 0)
FA.update_icon()
for(var/obj/machinery/computer/shuttle/pod/pod in GLOB.machines)
pod.admin_controlled = 0
- SSblackbox.record_feedback("tally", "security_level_changes", 1, level)
+ SSblackbox.record_feedback("tally", "security_level_changes", 1, get_security_level())
else
return
diff --git a/code/modules/server_tools/st_commands.dm b/code/modules/server_tools/st_commands.dm
index 9ec87a595c..1e071550e0 100644
--- a/code/modules/server_tools/st_commands.dm
+++ b/code/modules/server_tools/st_commands.dm
@@ -51,7 +51,7 @@
/*
The MIT License
-Copyright (c) 2011 Dominic Tarr
+Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
diff --git a/code/modules/server_tools/st_interface.dm b/code/modules/server_tools/st_interface.dm
index 39bebbbb3d..b0b1b0a43c 100644
--- a/code/modules/server_tools/st_interface.dm
+++ b/code/modules/server_tools/st_interface.dm
@@ -30,7 +30,10 @@ SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(server_tools_api_compatible, FALSE)
return
if(skip_compat_check && !fexists(SERVICE_INTERFACE_DLL))
CRASH("Service parameter present but no interface DLL detected. This is symptomatic of running a service less than version 3.1! Please upgrade.")
- call(SERVICE_INTERFACE_DLL, SERVICE_INTERFACE_FUNCTION)(command) //trust no retval
+ var/instance = params[SERVICE_INSTANCE_PARAM]
+ if(!instance)
+ instance = "TG Station Server" //maybe just upgraded
+ call(SERVICE_INTERFACE_DLL, SERVICE_INTERFACE_FUNCTION)(instance, command) //trust no retval
return TRUE
/world/proc/ChatBroadcast(message)
@@ -72,7 +75,7 @@ SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(server_tools_api_compatible, FALSE)
switch(command)
if(SERVICE_CMD_API_COMPATIBLE)
SERVER_TOOLS_WRITE_GLOBAL(server_tools_api_compatible, TRUE)
- return "SUCCESS"
+ return SERVICE_RETURN_SUCCESS
if(SERVICE_CMD_HARD_REBOOT)
if(SERVER_TOOLS_READ_GLOBAL(reboot_mode) != REBOOT_MODE_HARD)
SERVER_TOOLS_WRITE_GLOBAL(reboot_mode, REBOOT_MODE_HARD)
@@ -88,7 +91,7 @@ SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(server_tools_api_compatible, FALSE)
if(!istext(msg) || !msg)
return "No message set!"
SERVER_TOOLS_WORLD_ANNOUNCE(msg)
- return "SUCCESS"
+ return SERVICE_RETURN_SUCCESS
if(SERVICE_CMD_PLAYER_COUNT)
return "[SERVER_TOOLS_CLIENT_COUNT]"
if(SERVICE_CMD_LIST_CUSTOM)
@@ -96,13 +99,13 @@ SERVER_TOOLS_DEFINE_AND_SET_GLOBAL(server_tools_api_compatible, FALSE)
else
var/custom_command_result = HandleServiceCustomCommand(lowertext(command), params[SERVICE_CMD_PARAM_SENDER], params[SERVICE_CMD_PARAM_CUSTOM])
if(custom_command_result)
- return istext(custom_command_result) ? custom_command_result : "SUCCESS"
+ return istext(custom_command_result) ? custom_command_result : SERVICE_RETURN_SUCCESS
return "Unknown command: [command]"
/*
The MIT License
-Copyright (c) 2011 Dominic Tarr
+Copyright (c) 2017 Jordan Brown
Permission is hereby granted, free of charge,
to any person obtaining a copy of this software and
diff --git a/code/modules/shuttle/arrivals.dm b/code/modules/shuttle/arrivals.dm
index dd5a60ace7..b48d38691c 100644
--- a/code/modules/shuttle/arrivals.dm
+++ b/code/modules/shuttle/arrivals.dm
@@ -200,5 +200,5 @@
/obj/docking_port/mobile/arrivals/vv_edit_var(var_name, var_value)
switch(var_name)
if("perma_docked")
- SSblackbox.record_feedback("tally", "admin_secrets_fun_used", 1, "ShA[var_value ? "s" : "g"]")
+ SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("arrivals shuttle", "[var_value ? "stopped" : "started"]"))
return ..()
diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm
index c4eb16305a..c3efc5fc55 100644
--- a/code/modules/shuttle/emergency.dm
+++ b/code/modules/shuttle/emergency.dm
@@ -301,6 +301,7 @@
var/datum/DBQuery/query_round_shuttle_name = SSdbcore.NewQuery("UPDATE [format_table_name("round")] SET shuttle_name = '[name]' WHERE id = [GLOB.round_id]")
query_round_shuttle_name.Execute()
+
if(SHUTTLE_DOCKED)
if(time_left <= ENGINES_START_TIME)
mode = SHUTTLE_IGNITING
diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm
index 65636aa528..de1b0022f6 100644
--- a/code/modules/shuttle/navigation_computer.dm
+++ b/code/modules/shuttle/navigation_computer.dm
@@ -119,7 +119,7 @@
return
if(!my_port)
- my_port = new /obj/docking_port/stationary()
+ my_port = new(locate(eyeobj.x - x_offset, eyeobj.y - y_offset, eyeobj.z))
my_port.name = shuttlePortName
my_port.id = shuttlePortId
my_port.height = shuttle_port.height
@@ -128,7 +128,6 @@
my_port.dwidth = shuttle_port.dwidth
my_port.hidden = shuttle_port.hidden
my_port.dir = the_eye.dir
- my_port.loc = locate(eyeobj.x - x_offset, eyeobj.y - y_offset, eyeobj.z)
if(current_user.client)
current_user.client.images -= the_eye.placed_images
diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm
index c7a77f9457..de2b569687 100644
--- a/code/modules/shuttle/on_move.dm
+++ b/code/modules/shuttle/on_move.dm
@@ -15,6 +15,10 @@ All ShuttleMove procs go here
// Only gets called if fromShuttleMove returns true first
// returns the new move_mode (based on the old)
/turf/proc/toShuttleMove(turf/oldT, move_mode, obj/docking_port/mobile/shuttle)
+ . = move_mode
+ if(!(. & MOVE_TURF))
+ return
+
var/shuttle_dir = shuttle.dir
for(var/i in contents)
var/atom/movable/thing = i
@@ -38,8 +42,6 @@ All ShuttleMove procs go here
else
qdel(thing)
- return move_mode
-
// Called on the old turf to move the turf data
/turf/proc/onShuttleMove(turf/newT, list/movement_force, move_dir)
if(newT == src) // In case of in place shuttle rotation shenanigans.
diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm
index a4303078a5..02bee0856e 100644
--- a/code/modules/shuttle/shuttle.dm
+++ b/code/modules/shuttle/shuttle.dm
@@ -568,7 +568,7 @@
continue
move_mode = moving_atom.beforeShuttleMove(newT, rotation, move_mode) //atoms
- move_mode = oldT.fromShuttleMove(newT, underlying_turf_type, baseturf_cache, move_mode) //turfs
+ move_mode = oldT.fromShuttleMove(newT, underlying_turf_type, baseturf_cache, move_mode) //turfs
move_mode = newT.toShuttleMove(oldT, move_mode , src) //turfs
if(move_mode & MOVE_AREA)
diff --git a/code/modules/shuttle/white_ship.dm b/code/modules/shuttle/white_ship.dm
index 46aa4b6576..b6d9bda8b2 100644
--- a/code/modules/shuttle/white_ship.dm
+++ b/code/modules/shuttle/white_ship.dm
@@ -17,3 +17,4 @@
x_offset = -6
y_offset = -10
designate_time = 100
+
diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm
index 85956b0c6d..316dde05df 100644
--- a/code/modules/spells/spell.dm
+++ b/code/modules/spells/spell.dm
@@ -189,7 +189,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
var/mob/living/carbon/human/H = user
- if((invocation_type == "whisper" || invocation_type == "shout") && H.is_muzzled())
+ if((invocation_type == "whisper" || invocation_type == "shout") && !H.can_speak_vocal())
to_chat(user, "You can't get the words out!")
return 0
diff --git a/code/modules/spells/spell_types/dumbfire.dm b/code/modules/spells/spell_types/dumbfire.dm
index bb6e4480f5..f86c29fdc2 100644
--- a/code/modules/spells/spell_types/dumbfire.dm
+++ b/code/modules/spells/spell_types/dumbfire.dm
@@ -1,41 +1,41 @@
//NEEDS MAJOR CODE CLEANUP
-/obj/effect/proc_holder/spell/dumbfire
-
- var/projectile_type = ""
- var/activate_on_collision = 1
-
- var/proj_icon = 'icons/obj/projectiles.dmi'
- var/proj_icon_state = "spell"
- var/proj_name = "a spell projectile"
-
- var/proj_trail = 0 //if it leaves a trail
- var/proj_trail_lifespan = 0 //deciseconds
- var/proj_trail_icon = 'icons/obj/wizard.dmi'
- var/proj_trail_icon_state = "trail"
-
- var/proj_type = "/obj/effect/proc_holder/spell" //IMPORTANT use only subtypes of this
-
- var/proj_insubstantial = 0 //if it can pass through dense objects or not
- var/proj_trigger_range = 1 //the range from target at which the projectile triggers cast(target)
-
- var/proj_lifespan = 100 //in deciseconds * proj_step_delay
- var/proj_step_delay = 1 //lower = faster
-
-/obj/effect/proc_holder/spell/dumbfire/choose_targets(mob/user = usr)
-
- var/turf/T = get_turf(user)
- for(var/i = 1; i < range; i++)
- var/turf/new_turf = get_step(T, user.dir)
- if(new_turf.density)
- break
- T = new_turf
- perform(list(T),user = user)
-
-/obj/effect/proc_holder/spell/dumbfire/cast(list/targets, mob/user = usr)
- playMagSound()
- for(var/turf/target in targets)
+/obj/effect/proc_holder/spell/dumbfire
+
+ var/projectile_type = ""
+ var/activate_on_collision = 1
+
+ var/proj_icon = 'icons/obj/projectiles.dmi'
+ var/proj_icon_state = "spell"
+ var/proj_name = "a spell projectile"
+
+ var/proj_trail = 0 //if it leaves a trail
+ var/proj_trail_lifespan = 0 //deciseconds
+ var/proj_trail_icon = 'icons/obj/wizard.dmi'
+ var/proj_trail_icon_state = "trail"
+
+ var/proj_type = "/obj/effect/proc_holder/spell" //IMPORTANT use only subtypes of this
+
+ var/proj_insubstantial = 0 //if it can pass through dense objects or not
+ var/proj_trigger_range = 1 //the range from target at which the projectile triggers cast(target)
+
+ var/proj_lifespan = 100 //in deciseconds * proj_step_delay
+ var/proj_step_delay = 1 //lower = faster
+
+/obj/effect/proc_holder/spell/dumbfire/choose_targets(mob/user = usr)
+
+ var/turf/T = get_turf(user)
+ for(var/i = 1; i < range; i++)
+ var/turf/new_turf = get_step(T, user.dir)
+ if(new_turf.density)
+ break
+ T = new_turf
+ perform(list(T),user = user)
+
+/obj/effect/proc_holder/spell/dumbfire/cast(list/targets, mob/user = usr)
+ playMagSound()
+ for(var/turf/target in targets)
launch_at(target, user)
/obj/effect/proc_holder/spell/dumbfire/proc/launch_at(turf/target, mob/user)
diff --git a/code/modules/spells/spell_types/genetic.dm b/code/modules/spells/spell_types/genetic.dm
index c6945dab50..48d0d7cfbe 100644
--- a/code/modules/spells/spell_types/genetic.dm
+++ b/code/modules/spells/spell_types/genetic.dm
@@ -1,28 +1,28 @@
-/obj/effect/proc_holder/spell/targeted/genetic
- name = "Genetic"
- desc = "This spell inflicts a set of mutations and disabilities upon the target."
-
- var/disabilities = 0 //bits
- var/list/mutations = list() //mutation strings
- var/duration = 100 //deciseconds
- /*
- Disabilities
- 1st bit - ?
- 2nd bit - ?
- 3rd bit - ?
- 4th bit - ?
- 5th bit - ?
- 6th bit - ?
- */
-
-/obj/effect/proc_holder/spell/targeted/genetic/cast(list/targets,mob/user = usr)
- playMagSound()
- for(var/mob/living/carbon/target in targets)
- if(!target.dna)
- continue
- for(var/A in mutations)
- target.dna.add_mutation(A)
- target.disabilities |= disabilities
+/obj/effect/proc_holder/spell/targeted/genetic
+ name = "Genetic"
+ desc = "This spell inflicts a set of mutations and disabilities upon the target."
+
+ var/disabilities = 0 //bits
+ var/list/mutations = list() //mutation strings
+ var/duration = 100 //deciseconds
+ /*
+ Disabilities
+ 1st bit - ?
+ 2nd bit - ?
+ 3rd bit - ?
+ 4th bit - ?
+ 5th bit - ?
+ 6th bit - ?
+ */
+
+/obj/effect/proc_holder/spell/targeted/genetic/cast(list/targets,mob/user = usr)
+ playMagSound()
+ for(var/mob/living/carbon/target in targets)
+ if(!target.dna)
+ continue
+ for(var/A in mutations)
+ target.dna.add_mutation(A)
+ target.disabilities |= disabilities
addtimer(CALLBACK(src, .proc/remove, target), duration)
/obj/effect/proc_holder/spell/targeted/genetic/proc/remove(mob/living/carbon/target)
diff --git a/code/modules/spells/spell_types/knock.dm b/code/modules/spells/spell_types/knock.dm
index bbb2b3877f..7179bed031 100644
--- a/code/modules/spells/spell_types/knock.dm
+++ b/code/modules/spells/spell_types/knock.dm
@@ -1,31 +1,31 @@
-/obj/effect/proc_holder/spell/aoe_turf/knock
- name = "Knock"
- desc = "This spell opens nearby doors and does not require wizard garb."
-
- school = "transmutation"
- charge_max = 100
- clothes_req = 0
- invocation = "AULIE OXIN FIERA"
- invocation_type = "whisper"
- range = 3
- cooldown_min = 20 //20 deciseconds reduction per rank
-
- action_icon_state = "knock"
-
-/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets,mob/user = usr)
+/obj/effect/proc_holder/spell/aoe_turf/knock
+ name = "Knock"
+ desc = "This spell opens nearby doors and does not require wizard garb."
+
+ school = "transmutation"
+ charge_max = 100
+ clothes_req = 0
+ invocation = "AULIE OXIN FIERA"
+ invocation_type = "whisper"
+ range = 3
+ cooldown_min = 20 //20 deciseconds reduction per rank
+
+ action_icon_state = "knock"
+
+/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets,mob/user = usr)
SEND_SOUND(user, sound('sound/magic/knock.ogg'))
- for(var/turf/T in targets)
- for(var/obj/machinery/door/door in T.contents)
- INVOKE_ASYNC(src, .proc/open_door, door)
- for(var/obj/structure/closet/C in T.contents)
- INVOKE_ASYNC(src, .proc/open_closet, C)
-
-/obj/effect/proc_holder/spell/aoe_turf/knock/proc/open_door(var/obj/machinery/door/door)
- if(istype(door, /obj/machinery/door/airlock))
- var/obj/machinery/door/airlock/A = door
- A.locked = FALSE
- door.open()
-
-/obj/effect/proc_holder/spell/aoe_turf/knock/proc/open_closet(var/obj/structure/closet/C)
- C.locked = FALSE
- C.open()
+ for(var/turf/T in targets)
+ for(var/obj/machinery/door/door in T.contents)
+ INVOKE_ASYNC(src, .proc/open_door, door)
+ for(var/obj/structure/closet/C in T.contents)
+ INVOKE_ASYNC(src, .proc/open_closet, C)
+
+/obj/effect/proc_holder/spell/aoe_turf/knock/proc/open_door(var/obj/machinery/door/door)
+ if(istype(door, /obj/machinery/door/airlock))
+ var/obj/machinery/door/airlock/A = door
+ A.locked = FALSE
+ door.open()
+
+/obj/effect/proc_holder/spell/aoe_turf/knock/proc/open_closet(var/obj/structure/closet/C)
+ C.locked = FALSE
+ C.open()
diff --git a/code/modules/spells/spell_types/mime.dm b/code/modules/spells/spell_types/mime.dm
index 4e5c0605e2..28960fce31 100644
--- a/code/modules/spells/spell_types/mime.dm
+++ b/code/modules/spells/spell_types/mime.dm
@@ -125,146 +125,6 @@
..()
-/obj/item/spellbook/oneuse/mimery_blockade
- spell = /obj/effect/proc_holder/spell/targeted/forcewall/mime
- spellname = ""
- name = "Guide to Advanced Mimery Vol 1"
- desc = "The pages don't make any sound when turned."
- icon_state ="bookmime"
-
-/obj/item/spellbook/oneuse/mimery_guns
- spell = /obj/effect/proc_holder/spell/aimed/finger_guns
- spellname = ""
- name = "Guide to Advanced Mimery Vol 2"
- desc = "There aren't any words written..."
- icon_state ="bookmime"
-/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall
- name = "Invisible Wall"
- desc = "The mime's performance transmutates into physical reality."
- school = "mime"
- panel = "Mime"
- summon_type = list(/obj/effect/forcefield/mime)
- invocation_type = "emote"
- invocation_emote_self = "You form a wall in front of yourself."
- summon_lifespan = 300
- charge_max = 300
- clothes_req = 0
- range = 0
- cast_sound = null
- human_req = 1
-
- action_icon_state = "mime"
- action_background_icon_state = "bg_mime"
-
-/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall/Click()
- if(usr && usr.mind)
- if(!usr.mind.miming)
- to_chat(usr, "You must dedicate yourself to silence first.")
- return
- invocation = "[usr.real_name] looks as if a wall is in front of [usr.p_them()]."
- else
- invocation_type ="none"
- ..()
-
-
-/obj/effect/proc_holder/spell/targeted/mime/speak
- name = "Speech"
- desc = "Make or break a vow of silence."
- school = "mime"
- panel = "Mime"
- clothes_req = 0
- human_req = 1
- charge_max = 3000
- range = -1
- include_user = 1
-
- action_icon_state = "mime"
- action_background_icon_state = "bg_mime"
-
-/obj/effect/proc_holder/spell/targeted/mime/speak/Click()
- if(!usr)
- return
- if(!ishuman(usr))
- return
- var/mob/living/carbon/human/H = usr
- if(H.mind.miming)
- still_recharging_msg = "You can't break your vow of silence that fast!"
- else
- still_recharging_msg = "You'll have to wait before you can give your vow of silence again!"
- ..()
-
-/obj/effect/proc_holder/spell/targeted/mime/speak/cast(list/targets,mob/user = usr)
- for(var/mob/living/carbon/human/H in targets)
- H.mind.miming=!H.mind.miming
- if(H.mind.miming)
- to_chat(H, "You make a vow of silence.")
- else
- to_chat(H, "You break your vow of silence.")
-
-// These spells can only be gotten from the "Guide for Advanced Mimery series" for Mime Traitors.
-
-/obj/effect/proc_holder/spell/targeted/forcewall/mime
- name = "Invisible Blockade"
- desc = "Form an invisible three tile wide blockade."
- wall_type = /obj/effect/forcefield/mime/advanced
- invocation_type = "emote"
- invocation_emote_self = "You form a blockade in front of yourself."
- charge_max = 600
- sound = null
- clothes_req = 0
- range = -1
- include_user = 1
-
- action_icon_state = "mime"
- action_background_icon_state = "bg_mime"
-
-/obj/effect/proc_holder/spell/targeted/forcewall/mime/Click()
- if(usr && usr.mind)
- if(!usr.mind.miming)
- to_chat(usr, "You must dedicate yourself to silence first.")
- return
- invocation = "[usr.real_name] looks as if a blockade is in front of [usr.p_them()]."
- else
- invocation_type ="none"
- ..()
-
-/obj/effect/proc_holder/spell/aimed/finger_guns
- name = "Finger Guns"
- desc = "Shoot a mimed bullet from your fingers that stuns and does some damage."
- school = "mime"
- panel = "Mime"
- charge_max = 300
- clothes_req = 0
- invocation_type = "emote"
- invocation_emote_self = "You fire your finger gun!"
- range = 20
- projectile_type = /obj/item/projectile/bullet/mime
- projectile_amount = 3
- sound = null
- active_msg = "You draw your fingers!"
- deactive_msg = "You put your fingers at ease. Another time."
- active = FALSE
-
- action_icon_state = "mime"
- action_background_icon_state = "bg_mime"
- base_icon_state = "mime"
-
-
-/obj/effect/proc_holder/spell/aimed/finger_guns/Click()
- var/mob/living/carbon/human/owner = usr
- if(owner.incapacitated())
- to_chat(owner, "You can't properly point your fingers while incapacitated.")
- return
- if(usr && usr.mind)
- if(!usr.mind.miming)
- to_chat(usr, "You must dedicate yourself to silence first.")
- return
- invocation = "[usr.real_name] fires [usr.p_their()] finger gun!"
- else
- invocation_type ="none"
- ..()
-
-
/obj/item/spellbook/oneuse/mimery_blockade
spell = /obj/effect/proc_holder/spell/targeted/forcewall/mime
spellname = ""
diff --git a/code/modules/spells/spell_types/mind_transfer.dm b/code/modules/spells/spell_types/mind_transfer.dm
index 023af548d0..8a646d792f 100644
--- a/code/modules/spells/spell_types/mind_transfer.dm
+++ b/code/modules/spells/spell_types/mind_transfer.dm
@@ -1,79 +1,79 @@
-/obj/effect/proc_holder/spell/targeted/mind_transfer
- name = "Mind Transfer"
- desc = "This spell allows the user to switch bodies with a target."
-
- school = "transmutation"
- charge_max = 600
- clothes_req = 0
- invocation = "GIN'YU CAPAN"
- invocation_type = "whisper"
- range = 1
- cooldown_min = 200 //100 deciseconds reduction per rank
- var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell
- var/unconscious_amount_caster = 400 //how much the caster is stunned for after the spell
- var/unconscious_amount_victim = 400 //how much the victim is stunned for after the spell
-
- action_icon_state = "mindswap"
-
-/*
-Urist: I don't feel like figuring out how you store object spells so I'm leaving this for you to do.
+/obj/effect/proc_holder/spell/targeted/mind_transfer
+ name = "Mind Transfer"
+ desc = "This spell allows the user to switch bodies with a target."
+
+ school = "transmutation"
+ charge_max = 600
+ clothes_req = 0
+ invocation = "GIN'YU CAPAN"
+ invocation_type = "whisper"
+ range = 1
+ cooldown_min = 200 //100 deciseconds reduction per rank
+ var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell
+ var/unconscious_amount_caster = 400 //how much the caster is stunned for after the spell
+ var/unconscious_amount_victim = 400 //how much the victim is stunned for after the spell
+
+ action_icon_state = "mindswap"
+
+/*
+Urist: I don't feel like figuring out how you store object spells so I'm leaving this for you to do.
Make sure spells that are removed from spell_list are actually removed and deleted when mind transferring.
-Also, you never added distance checking after target is selected. I've went ahead and did that.
-*/
-/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets, mob/living/user = usr, distanceoverride)
- if(!targets.len)
- to_chat(user, "No mind found!")
- return
-
- if(targets.len > 1)
- to_chat(user, "Too many minds! You're not a hive damnit!")
- return
-
- var/mob/living/target = targets[1]
-
- var/t_He = target.p_they(TRUE)
- var/t_is = target.p_are()
-
- if(!(target in oview(range)) && !distanceoverride)//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it.
- to_chat(user, "[t_He] [t_is] too far away!")
- return
-
- if(ismegafauna(target))
- to_chat(user, "This creature is too powerful to control!")
- return
-
- if(target.stat == DEAD)
- to_chat(user, "You don't particularly want to be dead!")
- return
-
- if(!target.key || !target.mind)
- to_chat(user, "[t_He] appear[target.p_s()] to be catatonic! Not even magic can affect [target.p_their()] vacant mind.")
- return
-
- if(user.suiciding)
- to_chat(user, "You're killing yourself! You can't concentrate enough to do this!")
- return
-
- if((target.mind.special_role in protected_roles) || cmptext(copytext(target.key,1,2),"@"))
- to_chat(user, "[target.p_their(TRUE)] mind is resisting your spell!")
- return
-
- var/mob/living/victim = target//The target of the spell whos body will be transferred to.
- var/mob/living/caster = user//The wizard/whomever doing the body transferring.
-
- //MIND TRANSFER BEGIN
- var/mob/dead/observer/ghost = victim.ghostize(0)
- caster.mind.transfer_to(victim)
-
- ghost.mind.transfer_to(caster)
- if(ghost.key)
- caster.key = ghost.key //have to transfer the key since the mind was not active
- qdel(ghost)
-
- //MIND TRANSFER END
-
- //Here we knock both mobs out for a time.
- caster.Unconscious(unconscious_amount_caster)
- victim.Unconscious(unconscious_amount_victim)
+Also, you never added distance checking after target is selected. I've went ahead and did that.
+*/
+/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets, mob/living/user = usr, distanceoverride)
+ if(!targets.len)
+ to_chat(user, "No mind found!")
+ return
+
+ if(targets.len > 1)
+ to_chat(user, "Too many minds! You're not a hive damnit!")
+ return
+
+ var/mob/living/target = targets[1]
+
+ var/t_He = target.p_they(TRUE)
+ var/t_is = target.p_are()
+
+ if(!(target in oview(range)) && !distanceoverride)//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it.
+ to_chat(user, "[t_He] [t_is] too far away!")
+ return
+
+ if(ismegafauna(target))
+ to_chat(user, "This creature is too powerful to control!")
+ return
+
+ if(target.stat == DEAD)
+ to_chat(user, "You don't particularly want to be dead!")
+ return
+
+ if(!target.key || !target.mind)
+ to_chat(user, "[t_He] appear[target.p_s()] to be catatonic! Not even magic can affect [target.p_their()] vacant mind.")
+ return
+
+ if(user.suiciding)
+ to_chat(user, "You're killing yourself! You can't concentrate enough to do this!")
+ return
+
+ if((target.mind.special_role in protected_roles) || cmptext(copytext(target.key,1,2),"@"))
+ to_chat(user, "[target.p_their(TRUE)] mind is resisting your spell!")
+ return
+
+ var/mob/living/victim = target//The target of the spell whos body will be transferred to.
+ var/mob/living/caster = user//The wizard/whomever doing the body transferring.
+
+ //MIND TRANSFER BEGIN
+ var/mob/dead/observer/ghost = victim.ghostize(0)
+ caster.mind.transfer_to(victim)
+
+ ghost.mind.transfer_to(caster)
+ if(ghost.key)
+ caster.key = ghost.key //have to transfer the key since the mind was not active
+ qdel(ghost)
+
+ //MIND TRANSFER END
+
+ //Here we knock both mobs out for a time.
+ caster.Unconscious(unconscious_amount_caster)
+ victim.Unconscious(unconscious_amount_victim)
SEND_SOUND(caster, sound('sound/magic/mandswap.ogg'))
SEND_SOUND(victim, sound('sound/magic/mandswap.ogg'))// only the caster and victim hear the sounds, that way no one knows for sure if the swap happened
diff --git a/code/modules/spells/spell_types/projectile.dm b/code/modules/spells/spell_types/projectile.dm
index 19e44ffa83..4bbd9ac4a6 100644
--- a/code/modules/spells/spell_types/projectile.dm
+++ b/code/modules/spells/spell_types/projectile.dm
@@ -1,33 +1,33 @@
//NEEDS MAJOR CODE CLEANUP.
-/obj/effect/proc_holder/spell/targeted/projectile
- name = "Projectile"
- desc = "This spell summons projectiles which try to hit the targets."
-
- var/proj_icon = 'icons/obj/projectiles.dmi'
- var/proj_icon_state = "spell"
- var/proj_name = "a spell projectile"
-
- var/proj_trail = 0 //if it leaves a trail
- var/proj_trail_lifespan = 0 //deciseconds
- var/proj_trail_icon = 'icons/obj/wizard.dmi'
- var/proj_trail_icon_state = "trail"
-
-
- var/proj_type = "/obj/effect/proc_holder/spell/targeted" //IMPORTANT use only subtypes of this
-
- var/proj_lingering = 0 //if it lingers or disappears upon hitting an obstacle
- var/proj_homing = 1 //if it follows the target
- var/proj_insubstantial = 0 //if it can pass through dense objects or not
- var/proj_trigger_range = 0 //the range from target at which the projectile triggers cast(target)
-
- var/proj_lifespan = 15 //in deciseconds * proj_step_delay
- var/proj_step_delay = 1 //lower = faster
-
-/obj/effect/proc_holder/spell/targeted/projectile/cast(list/targets, mob/user = usr)
- playMagSound()
- for(var/mob/living/target in targets)
+/obj/effect/proc_holder/spell/targeted/projectile
+ name = "Projectile"
+ desc = "This spell summons projectiles which try to hit the targets."
+
+ var/proj_icon = 'icons/obj/projectiles.dmi'
+ var/proj_icon_state = "spell"
+ var/proj_name = "a spell projectile"
+
+ var/proj_trail = 0 //if it leaves a trail
+ var/proj_trail_lifespan = 0 //deciseconds
+ var/proj_trail_icon = 'icons/obj/wizard.dmi'
+ var/proj_trail_icon_state = "trail"
+
+
+ var/proj_type = "/obj/effect/proc_holder/spell/targeted" //IMPORTANT use only subtypes of this
+
+ var/proj_lingering = 0 //if it lingers or disappears upon hitting an obstacle
+ var/proj_homing = 1 //if it follows the target
+ var/proj_insubstantial = 0 //if it can pass through dense objects or not
+ var/proj_trigger_range = 0 //the range from target at which the projectile triggers cast(target)
+
+ var/proj_lifespan = 15 //in deciseconds * proj_step_delay
+ var/proj_step_delay = 1 //lower = faster
+
+/obj/effect/proc_holder/spell/targeted/projectile/cast(list/targets, mob/user = usr)
+ playMagSound()
+ for(var/mob/living/target in targets)
launch(target, user)
/obj/effect/proc_holder/spell/targeted/projectile/proc/launch(mob/living/target, mob/user)
diff --git a/code/modules/spells/spell_types/rightandwrong.dm b/code/modules/spells/spell_types/rightandwrong.dm
index b992871004..bb454a3b19 100644
--- a/code/modules/spells/spell_types/rightandwrong.dm
+++ b/code/modules/spells/spell_types/rightandwrong.dm
@@ -13,7 +13,7 @@
if(H.stat == DEAD || !(H.client))
continue
if(H.mind)
- if(H.mind.special_role == "Wizard" || H.mind.special_role == "apprentice" || H.mind.special_role == "survivalist")
+ if(iswizard(H) || H.mind.special_role == "survivalist")
continue
if(prob(survivor_probability) && !(H.mind in SSticker.mode.traitors))
SSticker.mode.traitors += H.mind
@@ -22,12 +22,14 @@
guns.owner = H.mind
H.mind.objectives += guns
H.mind.special_role = "survivalist"
+ H.mind.add_antag_datum(/datum/antagonist/auto_custom)
to_chat(H, "You are the survivalist! Your own safety matters above all else, and the only way to ensure your safety is to stockpile weapons! Grab as many guns as possible, by any means necessary. Kill anyone who gets in your way.")
else
var/datum/objective/steal_five_of_type/summon_magic/magic = new
magic.owner = H.mind
H.mind.objectives += magic
H.mind.special_role = "amateur magician"
+ H.mind.add_antag_datum(/datum/antagonist/auto_custom)
to_chat(H, "You are the amateur magician! Grow your newfound talent! Grab as many magical artefacts as possible, by any means necessary. Kill anyone who gets in your way.")
var/datum/objective/survive/survive = new
survive.owner = H.mind
@@ -218,4 +220,4 @@
SSevents.reschedule()
message_admins("Summon Events intensifies, events will now occur every [SSevents.frequency_lower / 600] to [SSevents.frequency_upper / 600] minutes.")
- log_game("Summon Events was increased!")
\ No newline at end of file
+ log_game("Summon Events was increased!")
diff --git a/code/modules/spells/spell_types/shapeshift.dm b/code/modules/spells/spell_types/shapeshift.dm
index 4ee1b678f0..8a377c6c3a 100644
--- a/code/modules/spells/spell_types/shapeshift.dm
+++ b/code/modules/spells/spell_types/shapeshift.dm
@@ -57,13 +57,15 @@
var/mob/living/shape = new shapeshift_type(caster.loc)
H = new(shape,src,caster)
+
clothes_req = 0
human_req = 0
/obj/effect/proc_holder/spell/targeted/shapeshift/proc/Restore(mob/living/shape)
var/obj/shapeshift_holder/H = locate() in shape
if(!H)
- return
+ return
+
H.restore()
clothes_req = initial(clothes_req)
@@ -156,4 +158,4 @@
/datum/soullink/shapeshift/sharerDies(gibbed, mob/living/sharer)
if(source)
- source.shapeDeath(gibbed)
+ source.shapeDeath(gibbed)
\ No newline at end of file
diff --git a/code/modules/station_goals/station_goal.dm b/code/modules/station_goals/station_goal.dm
index 98ec01f641..88377455c6 100644
--- a/code/modules/station_goals/station_goal.dm
+++ b/code/modules/station_goals/station_goal.dm
@@ -26,11 +26,11 @@
/datum/station_goal/proc/check_completion()
return completed
-/datum/station_goal/proc/print_result()
+/datum/station_goal/proc/get_result()
if(check_completion())
- to_chat(world, "Station Goal : [name] : Completed!")
+ return "