= penalty_threshold)
+ C.maxHealth -= 10 //reduce the maxhealth
+ var/slowdown = (1 - round(features["body_size"] / penalty_threshold, 0.1)) * CONFIG_GET(number/body_size_slowdown_multiplier)
+ holder.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/small_stride, TRUE, slowdown)
+ else
+ if(old_size < penalty_threshold && features["body_size"] >= penalty_threshold)
+ C.maxHealth += 10 //give the maxhealth back
+ holder.remove_movespeed_modifier(/datum/movespeed_modifier/small_stride) //remove the slowdown
+
+
diff --git a/code/datums/elements/update_icon_blocker.dm b/code/datums/elements/update_icon_blocker.dm
index c30dc9efad..f52a712ebb 100644
--- a/code/datums/elements/update_icon_blocker.dm
+++ b/code/datums/elements/update_icon_blocker.dm
@@ -7,4 +7,4 @@
RegisterSignal(target, COMSIG_ATOM_UPDATE_ICON, .proc/block_update_icon)
/datum/element/update_icon_blocker/proc/block_update_icon()
- return COMSIG_ATOM_NO_UPDATE_ICON_STATE | COMSIG_ATOM_NO_UPDATE_OVERLAYS
\ No newline at end of file
+ return COMSIG_ATOM_NO_UPDATE_ICON_STATE | COMSIG_ATOM_NO_UPDATE_OVERLAYS
diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm
index e1147df225..14f3eae689 100644
--- a/code/datums/emotes.dm
+++ b/code/datums/emotes.dm
@@ -66,8 +66,12 @@
if(emote_type == EMOTE_AUDIBLE)
user.audible_message(msg)
- else
+ else if(emote_type == EMOTE_VISIBLE)
user.visible_message(msg)
+ else if(emote_type == EMOTE_BOTH)
+ user.visible_message(msg, blind_message = msg)
+ else if(emote_type == EMOTE_OMNI)
+ user.visible_message(msg, omni = TRUE)
/datum/emote/proc/replace_pronoun(mob/user, message)
if(findtext(message, "their"))
diff --git a/code/datums/looping_sounds/machinery_sounds.dm b/code/datums/looping_sounds/machinery_sounds.dm
index f9a9e07aed..4f6996bfdd 100644
--- a/code/datums/looping_sounds/machinery_sounds.dm
+++ b/code/datums/looping_sounds/machinery_sounds.dm
@@ -51,4 +51,4 @@
mid_sounds = list('sound/machines/fryer/deep_fryer_1.ogg' = 1, 'sound/machines/fryer/deep_fryer_2.ogg' = 1)
volume = 10
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
\ No newline at end of file
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/code/datums/martial/psychotic_brawl.dm b/code/datums/martial/psychotic_brawl.dm
index 06d07260ed..28ca852a43 100644
--- a/code/datums/martial/psychotic_brawl.dm
+++ b/code/datums/martial/psychotic_brawl.dm
@@ -66,4 +66,4 @@
if(atk_verb)
log_combat(A, D, "[atk_verb] (Psychotic Brawling)")
- return TRUE
\ No newline at end of file
+ return TRUE
diff --git a/code/datums/mutations/_mutations.dm b/code/datums/mutations/_mutations.dm
index 3bddfdaa63..b72874c329 100644
--- a/code/datums/mutations/_mutations.dm
+++ b/code/datums/mutations/_mutations.dm
@@ -150,7 +150,6 @@
overlays_standing[CM.layer_used] = mut_overlay
apply_overlay(CM.layer_used)
-
/datum/mutation/human/proc/modify() //called when a genome is applied so we can properly update some stats without having to remove and reapply the mutation from someone
if(modified || !power || !owner)
return
diff --git a/code/datums/mutations/radioactive.dm b/code/datums/mutations/radioactive.dm
index df30aaa9d2..2e6aa50d46 100644
--- a/code/datums/mutations/radioactive.dm
+++ b/code/datums/mutations/radioactive.dm
@@ -16,4 +16,4 @@
visual_indicators[type] = list(mutable_appearance('icons/effects/genetics.dmi', "radiation", -MUTATIONS_LAYER))
/datum/mutation/human/radioactive/get_visual_indicator()
- return visual_indicators[type][1]
\ No newline at end of file
+ return visual_indicators[type][1]
diff --git a/code/datums/progressbar.dm b/code/datums/progressbar.dm
index fbc194cc6f..c2e0d3c9d2 100644
--- a/code/datums/progressbar.dm
+++ b/code/datums/progressbar.dm
@@ -64,4 +64,4 @@
qdel(bar)
. = ..()
-#undef PROGRESSBAR_HEIGHT
\ No newline at end of file
+#undef PROGRESSBAR_HEIGHT
diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm
index e92564a3b4..73813fd253 100644
--- a/code/datums/traits/neutral.dm
+++ b/code/datums/traits/neutral.dm
@@ -109,7 +109,7 @@
name = "Alcohol Intolerance"
desc = "You take toxin damage from alcohol rather than getting drunk."
value = 0
- mob_trait = TRAIT_NO_ALCOHOL
+ mob_trait = TRAIT_TOXIC_ALCOHOL
medical_record_text = "Patient's body does not react properly to ethyl alcohol."
/datum/quirk/alcohol_intolerance/add()
diff --git a/code/datums/wires/airalarm.dm b/code/datums/wires/airalarm.dm
index dae92d3c42..376512a375 100644
--- a/code/datums/wires/airalarm.dm
+++ b/code/datums/wires/airalarm.dm
@@ -72,4 +72,4 @@
var/area/AA = get_base_area(A)
if(AA.atmosalert(2, holder))
A.post_alert(2)
- A.update_icon()
\ No newline at end of file
+ A.update_icon()
diff --git a/code/datums/wires/apc.dm b/code/datums/wires/apc.dm
index 19b2b8dda8..d167a11fd3 100644
--- a/code/datums/wires/apc.dm
+++ b/code/datums/wires/apc.dm
@@ -55,4 +55,4 @@
if(mend)
A.aidisabled = FALSE
else
- A.aidisabled = TRUE
\ No newline at end of file
+ A.aidisabled = TRUE
diff --git a/code/datums/wires/explosive.dm b/code/datums/wires/explosive.dm
index 25493f2e30..6e3c5318bf 100644
--- a/code/datums/wires/explosive.dm
+++ b/code/datums/wires/explosive.dm
@@ -79,4 +79,4 @@
/datum/wires/explosive/gibtonite/explode()
var/obj/item/gibtonite/P = holder
- P.GibtoniteReaction(null, 2)
\ No newline at end of file
+ P.GibtoniteReaction(null, 2)
diff --git a/code/datums/wires/mulebot.dm b/code/datums/wires/mulebot.dm
index 988487727b..90f229fc2c 100644
--- a/code/datums/wires/mulebot.dm
+++ b/code/datums/wires/mulebot.dm
@@ -29,4 +29,4 @@
if(WIRE_MOTOR1, WIRE_MOTOR2)
holder.visible_message("[icon2html(M, viewers(holder))] The drive motor whines briefly.")
else
- holder.visible_message("[icon2html(M, viewers(holder))] You hear a radio crackle.")
\ No newline at end of file
+ holder.visible_message("[icon2html(M, viewers(holder))] You hear a radio crackle.")
diff --git a/code/datums/wires/particle_accelerator.dm b/code/datums/wires/particle_accelerator.dm
index b782e589dd..97f518e434 100644
--- a/code/datums/wires/particle_accelerator.dm
+++ b/code/datums/wires/particle_accelerator.dm
@@ -47,4 +47,4 @@
C.remove_strength()
/datum/wires/particle_accelerator/control_box/emp_pulse() // to prevent singulo from pulsing wires
- return
\ No newline at end of file
+ return
diff --git a/code/datums/wires/vending.dm b/code/datums/wires/vending.dm
index 6c7e59c24c..e8fb883ecd 100644
--- a/code/datums/wires/vending.dm
+++ b/code/datums/wires/vending.dm
@@ -57,4 +57,4 @@
if(WIRE_IDSCAN)
V.scan_id = mend
if(WIRE_SPEAKER)
- V.shut_up = mend
\ No newline at end of file
+ V.shut_up = mend
diff --git a/code/datums/wounds/_scars.dm b/code/datums/wounds/_scars.dm
index 8cd0d8a047..3365fc359d 100644
--- a/code/datums/wounds/_scars.dm
+++ b/code/datums/wounds/_scars.dm
@@ -149,4 +149,4 @@
/// Used to format a scar to safe in preferences for persistent scars
/datum/scar/proc/format_amputated(body_zone)
description = pick(list("is several skintone shades paler than the rest of the body", "is a gruesome patchwork of artificial flesh", "has a large series of attachment scars at the articulation points"))
- return "[SCAR_CURRENT_VERSION]|[body_zone]|[description]|amputated|[WOUND_SEVERITY_LOSS]"
\ No newline at end of file
+ return "[SCAR_CURRENT_VERSION]|[body_zone]|[description]|amputated|[WOUND_SEVERITY_LOSS]"
diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm
index 29c87b32d4..02421b1e52 100644
--- a/code/datums/wounds/_wounds.dm
+++ b/code/datums/wounds/_wounds.dm
@@ -91,8 +91,6 @@
var/wound_flags = (FLESH_WOUND | BONE_WOUND | ACCEPTS_GAUZE)
/datum/wound/Destroy()
- if(attached_surgery)
- QDEL_NULL(attached_surgery)
if(limb?.wounds && (src in limb.wounds)) // destroy can call remove_wound() and remove_wound() calls qdel, so we check to make sure there's anything to remove first
remove_wound()
limb = null
diff --git a/code/game/area/ai_monitored.dm b/code/game/area/ai_monitored.dm
index 87b44291f5..558a4b1026 100644
--- a/code/game/area/ai_monitored.dm
+++ b/code/game/area/ai_monitored.dm
@@ -28,4 +28,4 @@
for(var/X in motioncameras)
var/obj/machinery/camera/cam = X
cam.lostTargetRef(WEAKREF(O))
- return
\ No newline at end of file
+ return
diff --git a/code/game/area/areas/away_content.dm b/code/game/area/areas/away_content.dm
index b724c92607..27a73ae5f1 100644
--- a/code/game/area/areas/away_content.dm
+++ b/code/game/area/areas/away_content.dm
@@ -25,4 +25,4 @@ Unused icons for new areas are "awaycontent1" ~ "awaycontent30"
/area/awaymission/vr
name = "Virtual Reality"
- icon_state = "awaycontent1"
\ No newline at end of file
+ icon_state = "awaycontent1"
diff --git a/code/game/area/areas/ruins/lavaland.dm b/code/game/area/areas/ruins/lavaland.dm
index 19a1fd503d..66c4f8542b 100644
--- a/code/game/area/areas/ruins/lavaland.dm
+++ b/code/game/area/areas/ruins/lavaland.dm
@@ -94,4 +94,4 @@
//ash walker nest
/area/ruin/unpowered/ash_walkers
- icon_state = "red"
\ No newline at end of file
+ icon_state = "red"
diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm
index fbc433a8a0..836b00250f 100644
--- a/code/game/gamemodes/dynamic/dynamic.dm
+++ b/code/game/gamemodes/dynamic/dynamic.dm
@@ -72,6 +72,8 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
var/list/threat_log_verbose = list()
/// List of roundstart rules used for selecting the rules.
var/list/roundstart_rules = list()
+ /// List of minor roundstart rules used for selecting the rules.
+ var/list/minor_rules = list()
/// List of latejoin rules used for selecting the rules.
var/list/latejoin_rules = list()
/// List of midround rules used for selecting the rules.
@@ -121,10 +123,12 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
var/pop_last_updated = 0
/// How many percent of the rounds are more peaceful.
var/peaceful_percentage = 50
- /// If a highlander executed.
+ /// If a highlander executed. No other highlander rulesets will be run.
var/highlander_executed = FALSE
- /// If a only ruleset has been executed.
+ /// If a only ruleset has been executed. No other rulesets will be run.
var/only_ruleset_executed = FALSE
+ /// If the first picked ruleset was a minor ruleset. Minor antagonists will be weighted higher.
+ var/minor_ruleset_start = FALSE
/// Antags rolled by rules so far, to keep track of and discourage scaling past a certain ratio of crew/antags especially on lowpop.
var/antags_rolled = 0
// Arbitrary threat addition, for fudging purposes.
@@ -372,6 +376,8 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
if(ruleset.name == "")
continue
switch(ruleset.ruletype)
+ if("Minor")
+ minor_rules += ruleset
if("Roundstart")
roundstart_rules += ruleset
if ("Latejoin")
@@ -396,21 +402,47 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
rigged_roundstart()
else
roundstart()
-
- var/starting_rulesets = ""
- for (var/datum/dynamic_ruleset/roundstart/DR in executed_rules)
- starting_rulesets += "[DR.name], "
- log_game("DYNAMIC: Picked the following roundstart rules: [starting_rulesets]")
+ if(minor_ruleset_start)
+ log_game("DYNAMIC: Starting a minor ruleset round.")
+ else
+ var/starting_rulesets = ""
+ for (var/datum/dynamic_ruleset/roundstart/DR in executed_rules)
+ starting_rulesets += "[DR.name], "
+ log_game("DYNAMIC: Picked the following roundstart rules: [starting_rulesets]")
candidates.Cut()
return TRUE
/datum/game_mode/dynamic/post_setup(report)
update_playercounts()
-
- for(var/datum/dynamic_ruleset/roundstart/rule in executed_rules)
- addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_roundstart_rule, rule), rule.delay)
+ if(minor_ruleset_start)
+ addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/minor_roundstart),rand(1 MINUTES,5 MINUTES))
+ else
+ for(var/datum/dynamic_ruleset/roundstart/rule in executed_rules)
+ addtimer(CALLBACK(src, /datum/game_mode/dynamic/.proc/execute_roundstart_rule, rule), rule.delay)
..()
+/datum/game_mode/dynamic/proc/minor_roundstart()
+ message_admins("Dynamic beginning minor antag roundstart rolls.")
+ var/list/potential_minor_rulesets = storyteller.minor_rule_draft()
+ var/iterations = 0
+ var/num_rulesets_executed = 0
+ while(threat < threat_level && potential_minor_rulesets.len && (!CHECK_TICK || iterations < 100))
+ var/datum/dynamic_ruleset/minor/rule = pickweight(potential_minor_rulesets)
+ rule.candidates = current_players[CURRENT_LIVING_PLAYERS].Copy()
+ rule.trim_candidates()
+ if(!check_blocking(rule.blocking_rules, executed_rules) && rule.ready())
+ rule.execute()
+ executed_rules |= rule
+ log_threat("[rule.ruletype] - [rule.name] [rule.cost] threat", verbose = TRUE)
+ num_rulesets_executed++
+ else
+ potential_minor_rulesets -= rule
+ update_playercounts()
+ iterations++
+ message_admins("Minor antag roundstart rolls completed, with [num_rulesets_executed] antags or antag teams made.")
+ log_game("DYNAMIC: Minor antag roundstart made [num_rulesets_executed] antags or antag teams.")
+
+
/// A simple roundstart proc used when dynamic_forced_roundstart_ruleset has rules in it.
/datum/game_mode/dynamic/proc/rigged_roundstart()
message_admins("[GLOB.dynamic_forced_roundstart_ruleset.len] rulesets being forced. Will now attempt to draft players for them.")
@@ -429,12 +461,17 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
if (GLOB.dynamic_forced_extended)
log_game("DYNAMIC: Starting a round of forced extended.")
return TRUE
+ if(prob(storyteller.minor_start_chance()))
+ minor_ruleset_start = TRUE
+ message_admins("Dynamic has initialized a minor antag start. Antags will be assigned in 1-5 minutes.")
+ log_game("DYNAMIC: Minor start initialized.")
+ return TRUE
var/list/drafted_rules = storyteller.roundstart_draft()
if(!drafted_rules.len)
- message_admins("Not enough threat level for roundstart antags!")
- log_game("DYNAMIC: Not enough threat level for roundstart antags!")
- midround_injection_cooldown = round((midround_injection_cooldown + world.time) / 2, 1)
- latejoin_injection_cooldown = round((latejoin_injection_cooldown + world.time) / 2, 1)
+ message_admins("No roundstart antags drafted! Falling back to minor ruleset start.")
+ log_game("DYNAMIC: No roundstart antags drafted! Falling back to minor ruleset start.")
+ minor_ruleset_start = TRUE
+ return FALSE
var/indice_pop = min(10,round(roundstart_pop_ready/pop_per_requirement)+1)
extra_rulesets_amount = 0
if (GLOB.dynamic_classic_secret)
@@ -468,8 +505,9 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
else
if(threat_level >= 50)
- message_admins("DYNAMIC: Picking first roundstart ruleset failed. You should report this.")
+ message_admins("DYNAMIC: Picking first roundstart ruleset failed. You should report this. Falling back to minor antag start.")
log_game("DYNAMIC: Picking first roundstart ruleset failed. drafted_rules.len = [drafted_rules.len] and threat = [threat]/[threat_level]")
+ minor_ruleset_start = TRUE
return FALSE
return TRUE
@@ -513,7 +551,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
drafted_rules -= starting_rule
starting_rule.trim_candidates()
- starting_rule.scale_up(extra_rulesets_amount, threat_level-added_threat)
if (starting_rule.pre_execute())
log_threat("[starting_rule.ruletype] - [starting_rule.name] [starting_rule.cost + starting_rule.scaled_times * starting_rule.scaling_cost] threat", verbose = TRUE)
if(starting_rule.flags & HIGHLANDER_RULESET)
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets.dm b/code/game/gamemodes/dynamic/dynamic_rulesets.dm
index eb7da2144f..3e7e504130 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets.dm
@@ -50,8 +50,12 @@
/// Used for the roundend report
var/total_cost = 0
/// A flag that determines how the ruleset is handled
+ /// ONLY_RULESET are rulesets that prevent ALL other rulesets from rolling.
/// HIGHLANDER_RULESET are rulesets can end the round.
- /// TRAITOR_RULESET and MINOR_RULESET can't end the round and have no difference right now.
+ /// TRAITOR_RULESET are the "default" ruleset--they should always be addable to a round, if the round type allows antags and dynamic thinks there should be another.
+ /// MINOR_RULESET is for rulesets whose antags can have multiple instances without causing too much issue. As roundstarts, they have their weights reduced based on the storyteller's minor-antag-round chance.
+ /// FAKE_ANTAG_RULESET is for rulesets whose antags aren't actually antagonistic--essentially just flavor meant to spice the round up.
+ /// ALWAYS_MAX_WEIGHT_RULESET means that the ruleset doesn't have its weight reduced based on recency.
var/flags = 0
/// Pop range per requirement. If zero defaults to mode's pop_per_requirement.
var/pop_per_requirement = 0
@@ -82,9 +86,6 @@
var/delay = 0
/// List of tags for use in storytellers.
var/list/property_weights = list()
- /// Whether or not recent-round weight values are taken into account for this ruleset.
- /// Weight reduction uses the same values as secret's recent-round mode weight reduction.
- var/always_max_weight = FALSE
/// Weight reduction by recent-rounds. Saved on new.
var/weight_mult = 1
@@ -100,7 +101,7 @@
var/high_population_requirements = CONFIG_GET(keyed_list/dynamic_high_population_requirement)
var/list/repeated_mode_adjust = CONFIG_GET(number_list/repeated_mode_adjust)
if(config_tag in weights)
- if(!always_max_weight && SSpersistence.saved_dynamic_rules.len == 3 && repeated_mode_adjust.len == 3)
+ if(!(flags & ALWAYS_MAX_WEIGHT_RULESET) && SSpersistence.saved_dynamic_rules.len == 3 && repeated_mode_adjust.len == 3)
var/saved_dynamic_rules = SSpersistence.saved_dynamic_rules
for(var/i in 1 to 3)
if(config_tag in saved_dynamic_rules[i])
@@ -119,6 +120,9 @@
/datum/dynamic_ruleset/roundstart // One or more of those drafted at roundstart
ruletype = "Roundstart"
+/datum/dynamic_ruleset/minor // drafted at roundstart in minor rounds, one antag at a time, for a "mixed" round
+ ruletype = "Minor"
+
// Can be drafted when a player joins the server
/datum/dynamic_ruleset/latejoin
ruletype = "Latejoin"
@@ -175,7 +179,7 @@
/// This is called if persistent variable is true everytime SSTicker ticks.
/datum/dynamic_ruleset/proc/rule_process()
return TRUE
-
+
/// Called on game mode pre_setup for roundstart rulesets.
/// Do everything you need to do before job is assigned here.
/// IMPORTANT: ASSIGN special_role HERE
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
index d2fa8bcc70..7842c6e0f7 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm
@@ -70,9 +70,8 @@
requirements = list(40,30,20,15,15,15,15,15,15,15)
high_population_requirement = 15
repeatable = TRUE
- flags = TRAITOR_RULESET
+ flags = TRAITOR_RULESET | MINOR_RULESET | ALWAYS_MAX_WEIGHT_RULESET
property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1)
- always_max_weight = TRUE
//////////////////////////////////////////////
// //
@@ -207,6 +206,7 @@
weight = 4
cost = 25
requirements = list(60,60,60,55,50,50,50,50,50,50)
+ flags = MINOR_RULESET
high_population_requirement = 50
property_weights = list("story_potential" = 1, "trust" = -1, "chaos" = 2, "extended" = -1, "valid" = 2)
repeatable = TRUE
@@ -229,6 +229,7 @@
cost = 10
property_weights = list("story_potential" = 2, "extended" = 2, "trust" = -2, "valid" = 1)
requirements = list(70,65,60,55,50,45,40,35,30,30)
+ flags = MINOR_RULESET
high_population_requirement = 30
repeatable = TRUE
@@ -258,6 +259,7 @@
required_candidates = 1
weight = 3
cost = 15
+ flags = MINOR_RULESET
requirements = list(101,101,101,101,101,101,101,101,101,101)
property_weights = list("trust" = -2, "valid" = 2)
high_population_requirement = 101
@@ -281,5 +283,5 @@
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
repeatable = TRUE
- flags = TRAITOR_RULESET | MINOR_RULESET
- property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 2)
+ flags = TRAITOR_RULESET | MINOR_RULESET | FAKE_ANTAG_RULESET
+ property_weights = list("story_potential" = 1, "trust" = -1, "extended" = 2)
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
index b29584aa58..416721702b 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
@@ -207,9 +207,8 @@
requirements = list(30,25,20,15,15,15,15,15,15,15)
repeatable = TRUE
high_population_requirement = 15
- flags = TRAITOR_RULESET
+ flags = TRAITOR_RULESET | MINOR_RULESET | ALWAYS_MAX_WEIGHT_RULESET
property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1)
- always_max_weight = TRUE
/datum/dynamic_ruleset/midround/autotraitor/acceptable(population = 0, threat = 0)
var/player_count = mode.current_players[CURRENT_LIVING_PLAYERS].len
@@ -494,6 +493,7 @@
required_candidates = 1
weight = 3
cost = 10
+ flags = MINOR_RULESET
requirements = list(101,101,101,70,50,40,20,15,15,15)
high_population_requirement = 50
repeatable_weight_decrease = 2
@@ -630,6 +630,7 @@
required_candidates = 1
weight = 4
cost = 15
+ flags = MINOR_RULESET
requirements = list(101,101,101,90,80,70,60,50,40,30)
high_population_requirement = 30
property_weights = list("story_potential" = 1, "extended" = -2, "valid" = 2)
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_minor.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_minor.dm
new file mode 100644
index 0000000000..618befbaa7
--- /dev/null
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_minor.dm
@@ -0,0 +1,212 @@
+
+//////////////////////////////////////////////
+// //
+// SYNDICATE TRAITORS //
+// //
+//////////////////////////////////////////////
+
+/datum/dynamic_ruleset/minor/traitor
+ name = "Traitors"
+ config_tag = "traitor" // these having identical config tags to the roundstart modes is 100% intentional, so that config edits are simpler
+ persistent = TRUE
+ antag_flag = ROLE_TRAITOR
+ antag_datum = /datum/antagonist/traitor/
+ minimum_required_age = 0
+ protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster", "Cyborg")
+ restricted_roles = list("Cyborg", "AI")
+ required_candidates = 1
+ weight = 5
+ flags = TRAITOR_RULESET | ALWAYS_MAX_WEIGHT_RULESET
+ cost = 10 // Avoid raising traitor threat above 10, as it is the default low cost ruleset.
+ requirements = list(50,50,50,50,50,50,50,50,50,50)
+ high_population_requirement = 40
+ property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1, "valid" = 1)
+
+/datum/dynamic_ruleset/minor/traitor/execute()
+ var/mob/M = pick_n_take(candidates)
+ assigned += M
+ var/datum/antagonist/traitor/newTraitor = new
+ M.mind.add_antag_datum(newTraitor)
+ log_admin("[M] was made into a traitor by dynamic.")
+ message_admins("[M] was made into a traitor by dynamic.")
+ return TRUE
+
+//////////////////////////////////////////
+// //
+// BLOOD BROTHERS //
+// //
+//////////////////////////////////////////
+
+/datum/dynamic_ruleset/minor/traitorbro
+ name = "Blood Brothers"
+ config_tag = "traitorbro"
+ antag_flag = ROLE_BROTHER
+ antag_datum = /datum/antagonist/brother
+ restricted_roles = list("AI", "Cyborg")
+ protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
+ required_candidates = 2
+ weight = 4
+ cost = 10
+ requirements = list(101,101,101,101,101,101,101,101,101,101)
+ high_population_requirement = 101
+ antag_cap = list(2,2,2,2,2,2,2,2,2,2) // Can pick 3 per team, but rare enough it doesn't matter.
+ property_weights = list("story_potential" = 1, "trust" = -1, "extended" = 1, "valid" = 1)
+ var/list/datum/team/brother_team/pre_brother_teams = list()
+ var/const/min_team_size = 2
+
+/datum/dynamic_ruleset/minor/traitorbro/execute()
+ if(candidates.len < min_team_size || candidates.len < required_candidates)
+ return FALSE
+ var/datum/team/brother_team/team = new
+ var/team_size = prob(10) ? min(3, candidates.len) : 2
+ for(var/k = 1 to team_size)
+ var/mob/bro = pick_n_take(candidates)
+ assigned += bro.mind
+ team.add_member(bro.mind)
+ bro.mind.special_role = "brother"
+ bro.mind.restricted_roles = restricted_roles
+ team.pick_meeting_area()
+ team.forge_brother_objectives()
+ for(var/datum/mind/M in team.members)
+ M.add_antag_datum(/datum/antagonist/brother, team)
+ team.update_name()
+ mode.brother_teams += team
+
+//////////////////////////////////////////////
+// //
+// CHANGELINGS //
+// //
+//////////////////////////////////////////////
+
+/datum/dynamic_ruleset/minor/changeling
+ name = "Changelings"
+ config_tag = "changeling"
+ antag_flag = ROLE_CHANGELING
+ antag_datum = /datum/antagonist/changeling
+ restricted_roles = list("AI", "Cyborg")
+ protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
+ required_candidates = 1
+ weight = 3
+ cost = 15
+ scaling_cost = 15
+ requirements = list(101,101,101,101,101,101,101,101,101,101)
+ property_weights = list("trust" = -2, "valid" = 2)
+ high_population_requirement = 10
+ antag_cap = list(1,1,1,1,1,2,2,2,2,3)
+ var/team_mode_probability = 30
+
+/datum/dynamic_ruleset/minor/changeling/execute()
+ var/mob/M = pick_n_take(candidates)
+ assigned += M.mind
+ M.mind.restricted_roles = restricted_roles
+ M.mind.special_role = ROLE_CHANGELING
+ var/datum/antagonist/changeling/new_antag = new antag_datum()
+ M.mind.add_antag_datum(new_antag)
+ return TRUE
+
+//////////////////////////////////////////////
+// //
+// ELDRITCH CULT //
+// //
+//////////////////////////////////////////////
+
+/datum/dynamic_ruleset/minor/heretics
+ name = "Heretic"
+ antag_flag = "heretic"
+ antag_datum = /datum/antagonist/heretic
+ protected_roles = list("Prisoner","Security Officer", "Warden", "Detective", "Head of Security", "Captain")
+ restricted_roles = list("AI", "Cyborg")
+ required_candidates = 1
+ weight = 3
+ cost = 25
+ scaling_cost = 15
+ requirements = list(60,60,60,55,50,50,50,50,50,50)
+ property_weights = list("story_potential" = 1, "trust" = -1, "chaos" = 2, "extended" = -1, "valid" = 2)
+ antag_cap = list(1,1,1,1,2,2,2,2,3,3)
+ high_population_requirement = 50
+
+
+/datum/dynamic_ruleset/minor/heretics/pre_execute()
+ var/mob/picked_candidate = pick_n_take(candidates)
+ assigned += picked_candidate.mind
+ picked_candidate.mind.restricted_roles = restricted_roles
+ picked_candidate.mind.special_role = ROLE_HERETIC
+ var/datum/antagonist/heretic/new_antag = new antag_datum()
+ picked_candidate.mind.add_antag_datum(new_antag)
+ return TRUE
+
+//////////////////////////////////////////////
+// //
+// DEVIL //
+// //
+//////////////////////////////////////////////
+
+/datum/dynamic_ruleset/minor/devil
+ name = "Devil"
+ config_tag = "devil"
+ antag_flag = ROLE_DEVIL
+ antag_datum = /datum/antagonist/devil
+ restricted_roles = list("Lawyer", "Curator", "Chaplain", "Head of Security", "Captain", "AI")
+ required_candidates = 1
+ weight = 3
+ cost = 0
+ requirements = list(101,101,101,101,101,101,101,101,101,101)
+ high_population_requirement = 101
+ antag_cap = list(1,1,1,2,2,2,3,3,3,4)
+ property_weights = list("extended" = 1)
+
+/datum/dynamic_ruleset/minor/devil/pre_execute()
+ var/mob/devil = pick_n_take(candidates)
+ assigned += devil.mind
+ devil.mind.special_role = ROLE_DEVIL
+ devil.mind.restricted_roles = restricted_roles
+
+ log_game("[key_name(devil)] has been selected as a devil")
+ add_devil(devil, ascendable = TRUE)
+ add_devil_objectives(devil.mind,2)
+ return TRUE
+
+/datum/dynamic_ruleset/minor/devil/proc/add_devil_objectives(datum/mind/devil_mind, quantity)
+ var/list/validtypes = list(/datum/objective/devil/soulquantity, /datum/objective/devil/soulquality, /datum/objective/devil/sintouch, /datum/objective/devil/buy_target)
+ var/datum/antagonist/devil/D = devil_mind.has_antag_datum(/datum/antagonist/devil)
+ for(var/i = 1 to quantity)
+ var/type = pick(validtypes)
+ var/datum/objective/devil/objective = new type(null)
+ objective.owner = devil_mind
+ D.objectives += objective
+ if(!istype(objective, /datum/objective/devil/buy_target))
+ validtypes -= type
+ else
+ objective.find_target()
+
+//////////////////////////////////////////////
+// //
+// BLOODSUCKERS //
+// //
+//////////////////////////////////////////////
+
+/datum/dynamic_ruleset/minor/bloodsucker
+ name = "Bloodsuckers"
+ config_tag = "bloodsucker"
+ antag_flag = ROLE_BLOODSUCKER
+ antag_datum = ANTAG_DATUM_BLOODSUCKER
+ minimum_required_age = 0
+ protected_roles = list("Chaplain", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
+ restricted_roles = list("Cyborg", "AI")
+ required_candidates = 1
+ weight = 2
+ cost = 15
+ scaling_cost = 10
+ property_weights = list("story_potential" = 1, "extended" = 1, "trust" = -2, "valid" = 1)
+ requirements = list(70,65,60,55,50,50,50,50,50,50)
+ high_population_requirement = 50
+
+/datum/dynamic_ruleset/minor/bloodsucker/execute()
+ var/mob/M = pick_n_take(candidates)
+ assigned += M.mind
+ M.mind.special_role = ROLE_BLOODSUCKER
+ M.mind.restricted_roles = restricted_roles
+ mode.check_start_sunlight()
+ if(mode.make_bloodsucker(M.mind))
+ mode.bloodsuckers += M.mind
+ return TRUE
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
index db4ec99558..c5e0857461 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm
@@ -15,6 +15,7 @@
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster", "Cyborg")
restricted_roles = list("Cyborg", "AI")
required_candidates = 1
+ flags = TRAITOR_RULESET | MINOR_RULESET | ALWAYS_MAX_WEIGHT_RULESET
weight = 5
cost = 10 // Avoid raising traitor threat above 10, as it is the default low cost ruleset.
scaling_cost = 10
@@ -22,7 +23,6 @@
high_population_requirement = 40
antag_cap = list(1,1,1,1,2,2,2,2,3,3)
property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 1, "valid" = 1)
- always_max_weight = TRUE
var/autotraitor_cooldown = 450 // 15 minutes (ticks once per 2 sec)
/datum/dynamic_ruleset/roundstart/traitor/pre_execute()
@@ -57,6 +57,7 @@
restricted_roles = list("AI", "Cyborg")
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_candidates = 2
+ flags = MINOR_RULESET
weight = 4
cost = 10
requirements = list(101,101,101,101,101,101,101,101,101,101)
@@ -106,6 +107,7 @@
restricted_roles = list("AI", "Cyborg")
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_candidates = 1
+ flags = MINOR_RULESET
weight = 3
cost = 15
scaling_cost = 15
@@ -156,6 +158,7 @@
protected_roles = list("Prisoner","Security Officer", "Warden", "Detective", "Head of Security", "Captain")
restricted_roles = list("AI", "Cyborg")
required_candidates = 1
+ flags = MINOR_RULESET
weight = 3
cost = 25
scaling_cost = 15
@@ -694,6 +697,7 @@
antag_datum = /datum/antagonist/devil
restricted_roles = list("Lawyer", "Curator", "Chaplain", "Head of Security", "Captain", "AI")
required_candidates = 1
+ flags = MINOR_RULESET
weight = 3
cost = 0
requirements = list(101,101,101,101,101,101,101,101,101,101)
@@ -850,6 +854,7 @@
protected_roles = list("Chaplain", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
restricted_roles = list("Cyborg", "AI")
required_candidates = 1
+ flags = MINOR_RULESET
weight = 2
cost = 15
scaling_cost = 10
diff --git a/code/game/gamemodes/dynamic/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm
index 04e295356a..d5766b287e 100644
--- a/code/game/gamemodes/dynamic/dynamic_storytellers.dm
+++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm
@@ -32,6 +32,9 @@ Property weights are added to the config weight of the ruleset. They are:
"conversion" -- Basically a bool. Conversion antags, well, convert. It's in its own class 'cause people kinda hate conversion.
*/
+/datum/dynamic_storyteller/proc/minor_start_chance()
+ return clamp(60 - mode.threat_level,0,100) // by default higher threat = lower chance of minor round
+
/datum/dynamic_storyteller/proc/start_injection_cooldowns()
var/latejoin_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_latejoin_delay_max + GLOB.dynamic_first_latejoin_delay_min)
mode.latejoin_injection_cooldown = round(clamp(EXP_DISTRIBUTION(latejoin_injection_cooldown_middle), GLOB.dynamic_first_latejoin_delay_min, GLOB.dynamic_first_latejoin_delay_max)) + world.time
@@ -104,8 +107,27 @@ Property weights are added to the config weight of the ruleset. They are:
/datum/dynamic_storyteller/proc/roundstart_draft()
var/list/drafted_rules = list()
+ var/minor_round_weight_mult = (100-minor_start_chance()) / 100
for (var/datum/dynamic_ruleset/roundstart/rule in mode.roundstart_rules)
if (rule.acceptable(mode.roundstart_pop_ready, mode.threat_level)) // If we got the population and threat required
+ rule.candidates = mode.candidates.Copy()
+ rule.trim_candidates()
+ if (rule.ready() && rule.candidates.len > 0)
+ var/property_weight = 0
+ for(var/property in property_weights)
+ if(property in rule.property_weights) // just treat it as 0 if it's not in there
+ property_weight += rule.property_weights[property] * property_weights[property]
+ var/calced_weight = (rule.get_weight() + property_weight) * rule.weight_mult
+ if(CHECK_BITFIELD(rule.flags, MINOR_RULESET))
+ calced_weight *= minor_round_weight_mult
+ if(calced_weight > 0) // negatives in the list might cause problems
+ drafted_rules[rule] = calced_weight
+ return drafted_rules
+
+/datum/dynamic_storyteller/proc/minor_rule_draft()
+ var/list/drafted_rules = list()
+ for (var/datum/dynamic_ruleset/minor/rule in mode.minor_rules)
+ if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
rule.candidates = mode.candidates.Copy()
rule.trim_candidates()
if (rule.ready() && rule.candidates.len > 0)
@@ -124,7 +146,7 @@ Property weights are added to the config weight of the ruleset. They are:
// if there are antags OR the rule is an antag rule, antag_acceptable will be true.
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
// Classic secret : only autotraitor/minor roles
- if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
+ if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET)))
continue
rule.trim_candidates()
if (rule.ready())
@@ -133,7 +155,7 @@ Property weights are added to the config weight of the ruleset. They are:
if(property in rule.property_weights) // just treat it as 0 if it's not in there
property_weight += rule.property_weights[property] * property_weights[property]
var/threat_weight = 1
- if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway
+ if(!(rule.flags & TRAITOR_RULESET)) // makes the traitor rulesets always possible anyway
var/cost_difference = rule.cost-(mode.threat_level-mode.threat)
/* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to
pick this particular ruleset.
@@ -157,7 +179,7 @@ Property weights are added to the config weight of the ruleset. They are:
for (var/datum/dynamic_ruleset/latejoin/rule in mode.latejoin_rules)
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level - mode.threat))
// Classic secret : only autotraitor/minor roles
- if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
+ if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET)))
continue
// No stacking : only one round-ender, unless threat level > stacking_limit.
if (mode.threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
@@ -172,7 +194,7 @@ Property weights are added to the config weight of the ruleset. They are:
if(property in rule.property_weights)
property_weight += rule.property_weights[property] * property_weights[property]
var/threat_weight = 1
- if(!(rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))
+ if(!(rule.flags & TRAITOR_RULESET))
var/cost_difference = rule.cost-(mode.threat_level-mode.threat)
threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,abs(cost_difference),0)))
if(cost_difference > 0)
@@ -195,6 +217,9 @@ Property weights are added to the config weight of the ruleset. They are:
min_players = 30
var/refund_cooldown = 0
+/datum/dynamic_storyteller/chaotic/minor_start_chance()
+ return 0
+
/datum/dynamic_storyteller/chaotic/do_process()
if(refund_cooldown < world.time)
mode.create_threat(20)
@@ -215,6 +240,9 @@ Property weights are added to the config weight of the ruleset. They are:
flags = WAROPS_ALWAYS_ALLOWED | USE_PREV_ROUND_WEIGHTS
property_weights = list("valid" = 3, "trust" = 5)
+/datum/dynamic_storyteller/chaotic/minor_start_chance()
+ return 0
+
/datum/dynamic_storyteller/team/should_inject_antag(dry_run = FALSE)
return (mode.current_players[CURRENT_LIVING_ANTAGS].len ? FALSE : ..())
@@ -228,6 +256,9 @@ Property weights are added to the config weight of the ruleset. They are:
flags = WAROPS_ALWAYS_ALLOWED
property_weights = list("valid" = 1, "conversion" = 20)
+/datum/dynamic_storyteller/chaotic/minor_start_chance()
+ return 0
+
/datum/dynamic_storyteller/random
name = "Random"
config_tag = "random"
@@ -244,6 +275,9 @@ Property weights are added to the config weight of the ruleset. They are:
/datum/dynamic_storyteller/random/should_inject_antag()
return prob(50)
+/datum/dynamic_storyteller/chaotic/minor_start_chance()
+ return 20
+
/datum/dynamic_storyteller/random/roundstart_draft()
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/roundstart/rule in mode.roundstart_rules)
@@ -254,12 +288,22 @@ Property weights are added to the config weight of the ruleset. They are:
drafted_rules[rule] = 1
return drafted_rules
+/datum/dynamic_storyteller/random/minor_rule_draft()
+ var/list/drafted_rules = list()
+ for (var/datum/dynamic_ruleset/minor/rule in mode.minor_rules)
+ if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
+ rule.candidates = mode.candidates.Copy()
+ rule.trim_candidates()
+ if (rule.ready() && rule.candidates.len > 0)
+ drafted_rules[rule] = 1
+ return drafted_rules
+
/datum/dynamic_storyteller/random/midround_draft()
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/midround/rule in mode.midround_rules)
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
// Classic secret : only autotraitor/minor roles
- if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
+ if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET)))
continue
rule.trim_candidates()
if (rule.ready())
@@ -271,7 +315,7 @@ Property weights are added to the config weight of the ruleset. They are:
for (var/datum/dynamic_ruleset/latejoin/rule in mode.latejoin_rules)
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
// Classic secret : only autotraitor/minor roles
- if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
+ if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET)))
continue
// No stacking : only one round-ender, unless threat level > stacking_limit.
if (mode.threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
@@ -286,7 +330,7 @@ Property weights are added to the config weight of the ruleset. They are:
/datum/dynamic_storyteller/story
name = "Story"
config_tag = "story"
- desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies. Has a buildup-climax-falling action threat curve."
+ desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies."
weight = 2
curve_width = 2
flags = USE_PREV_ROUND_WEIGHTS
@@ -308,6 +352,19 @@ Property weights are added to the config weight of the ruleset. They are:
flags = USE_PREV_ROUND_WEIGHTS
property_weights = list("trust" = -2)
+/datum/dynamic_storyteller/intrigue/minor_start_chance()
+ return 100 - mode.threat_level
+
+/datum/dynamic_storyteller/grabbag
+ name = "Grab Bag"
+ config_tag = "grabbag"
+ desc = "Crew antags (e.g. traitor, changeling, bloodsucker, heretic) only, all mixed together."
+ weight = 2
+ flags = USE_PREF_WEIGHTS | USE_PREV_ROUND_WEIGHTS
+
+/datum/dynamic_storyteller/grabbag/minor_start_chance()
+ return 100
+
/datum/dynamic_storyteller/liteextended
name = "Calm"
config_tag = "calm"
@@ -319,6 +376,9 @@ Property weights are added to the config weight of the ruleset. They are:
dead_player_weight = 5
property_weights = list("extended" = 2, "chaos" = -1, "valid" = -1, "conversion" = -10)
+/datum/dynamic_storyteller/liteextended/minor_start_chance()
+ return 100
+
/datum/dynamic_storyteller/no_antag
name = "Extended"
config_tag = "semiextended"
diff --git a/code/game/gamemodes/gangs/dominator_countdown.dm b/code/game/gamemodes/gangs/dominator_countdown.dm
index c6ae610e37..3b61a07829 100644
--- a/code/game/gamemodes/gangs/dominator_countdown.dm
+++ b/code/game/gamemodes/gangs/dominator_countdown.dm
@@ -10,4 +10,4 @@
else if(D.gang && D.gang.domination_time != NOT_DOMINATING)
return D.gang.domination_time_remaining()
else
- return "OFFLINE"
\ No newline at end of file
+ return "OFFLINE"
diff --git a/code/game/gamemodes/gangs/gang.dm b/code/game/gamemodes/gangs/gang.dm
index a766dda57c..a4483ca3b8 100644
--- a/code/game/gamemodes/gangs/gang.dm
+++ b/code/game/gamemodes/gangs/gang.dm
@@ -197,7 +197,7 @@
if(gangtool)//Here is where all of the text occurs when a gang boss first spawns in.
var/obj/item/device/gangtool/G = new()
- var/where = H.equip_in_one_of_slots(G, slots)
+ var/where = H.equip_in_one_of_slots(G, slots, critical = TRUE)
if (!where)
to_chat(H, "Your Syndicate benefactors were unfortunately unable to get you a Gangtool.")
else
@@ -207,7 +207,7 @@
if(pen)
var/obj/item/pen/gang/T = new()
- var/where2 = H.equip_in_one_of_slots(T, slots)
+ var/where2 = H.equip_in_one_of_slots(T, slots, critical = TRUE)
if (!where2)
to_chat(H, "Your Syndicate benefactors were unfortunately unable to get you a recruitment pen to start.")
else
@@ -215,7 +215,7 @@
if(spraycan)
var/obj/item/toy/crayon/spraycan/gang/SC = new(null,gang)
- var/where3 = H.equip_in_one_of_slots(SC, slots)
+ var/where3 = H.equip_in_one_of_slots(SC, slots, critical = TRUE)
if (!where3)
to_chat(H, "Your Syndicate benefactors were unfortunately unable to get you a territory spraycan to start.")
else
@@ -223,7 +223,7 @@
if(hud)
var/obj/item/clothing/glasses/hud/security/chameleon/C = new(null,gang)
- var/where4 = H.equip_in_one_of_slots(C, slots)
+ var/where4 = H.equip_in_one_of_slots(C, slots, critical = TRUE)
if (!where4)
to_chat(H, "Your Syndicate benefactors were unfortunately unable to get you a chameleon security HUD.")
else
diff --git a/code/game/gamemodes/gangs/gang_decals.dm b/code/game/gamemodes/gangs/gang_decals.dm
index a37b4cb63b..75d8d459ef 100644
--- a/code/game/gamemodes/gangs/gang_decals.dm
+++ b/code/game/gamemodes/gangs/gang_decals.dm
@@ -35,4 +35,4 @@
return ..()
/obj/effect/decal/cleanable/crayon/NeverShouldHaveComeHere(turf/T)
- return isspaceturf(T) || islava(T) || istype(T, /turf/open/water) || ischasm(T)
\ No newline at end of file
+ return isspaceturf(T) || islava(T) || istype(T, /turf/open/water) || ischasm(T)
diff --git a/code/game/gamemodes/gangs/gang_hud.dm b/code/game/gamemodes/gangs/gang_hud.dm
index 3fde6d4123..825d361ab0 100644
--- a/code/game/gamemodes/gangs/gang_hud.dm
+++ b/code/game/gamemodes/gangs/gang_hud.dm
@@ -31,4 +31,4 @@
var/image/holder = M.hud_list[ANTAG_HUD]
if(holder)
holder.color = null
- ..()
\ No newline at end of file
+ ..()
diff --git a/code/game/gamemodes/gangs/gang_pen.dm b/code/game/gamemodes/gangs/gang_pen.dm
index b7bd6cca5e..09cea5cecb 100644
--- a/code/game/gamemodes/gangs/gang_pen.dm
+++ b/code/game/gamemodes/gangs/gang_pen.dm
@@ -56,4 +56,4 @@
H.silent = max(H.silent, 5)
H.DefaultCombatKnockdown(100)
gangster_mind.add_antag_datum(/datum/antagonist/gang, gang)
- return TRUE
\ No newline at end of file
+ return TRUE
diff --git a/code/game/gamemodes/gangs/gangtool.dm b/code/game/gamemodes/gangs/gangtool.dm
index e99455bcd5..32272ae51a 100644
--- a/code/game/gamemodes/gangs/gangtool.dm
+++ b/code/game/gamemodes/gangs/gangtool.dm
@@ -256,4 +256,4 @@
outfits = TRUE
/obj/item/device/gangtool/spare/lt
- promotable = TRUE
\ No newline at end of file
+ promotable = TRUE
diff --git a/code/game/gamemodes/gangs/implant_gang.dm b/code/game/gamemodes/gangs/implant_gang.dm
index ee91928845..cad54d4fc1 100644
--- a/code/game/gamemodes/gangs/implant_gang.dm
+++ b/code/game/gamemodes/gangs/implant_gang.dm
@@ -58,4 +58,4 @@
qdel(src)
return
imp = new /obj/item/implant/gang(src,gang)
- .=..()
\ No newline at end of file
+ .=..()
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index a8ed4611eb..d8617e0b48 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -166,7 +166,7 @@ If not set, defaults to check_completion instead. Set it. It's used by cryo.
var/list/slots = list("backpack" = SLOT_IN_BACKPACK)
for(var/eq_path in special_equipment)
var/obj/O = new eq_path
- H.equip_in_one_of_slots(O, slots)
+ H.equip_in_one_of_slots(O, slots, critical = TRUE)
/datum/objective/assassinate
name = "assasinate"
@@ -1152,7 +1152,7 @@ GLOBAL_LIST_EMPTY(cult_contraband)
I.forceMove(get_turf(owner))
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
- H.equip_in_one_of_slots(I, list("backpack" = SLOT_IN_BACKPACK))
+ H.equip_in_one_of_slots(I, list("backpack" = SLOT_IN_BACKPACK), critical = TRUE)
hoarded_item = I
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index bced9db61f..06e1635656 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -145,8 +145,8 @@
/obj/machinery/sleeper/ui_state(mob/user)
if(controls_inside)
- return GLOB.contained_state
- return GLOB.default_state
+ return GLOB.default_state
+ return GLOB.notcontained_state
/obj/machinery/sleeper/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
@@ -209,6 +209,7 @@
data["occupant"]["fireLoss"] = mob_occupant.getFireLoss()
data["occupant"]["cloneLoss"] = mob_occupant.getCloneLoss()
data["occupant"]["brainLoss"] = mob_occupant.getOrganLoss(ORGAN_SLOT_BRAIN)
+ data["occupant"]["is_robotic_organism"] = HAS_TRAIT(mob_occupant, TRAIT_ROBOTIC_ORGANISM)
data["occupant"]["reagents"] = list()
if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len)
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
diff --git a/code/game/machinery/announcement_system.dm b/code/game/machinery/announcement_system.dm
index da82b0afc7..f46169f72e 100644
--- a/code/game/machinery/announcement_system.dm
+++ b/code/game/machinery/announcement_system.dm
@@ -114,7 +114,7 @@ GLOBAL_LIST_EMPTY(announcement_systems)
. = ..()
if(.)
return
- if(!usr.canUseTopic(src, !issilicon(usr)))
+ if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
return
if(stat & BROKEN)
visible_message("[src] buzzes.", "You hear a faint buzz.")
@@ -147,7 +147,7 @@ GLOBAL_LIST_EMPTY(announcement_systems)
. = attack_ai(user)
/obj/machinery/announcement_system/attack_ai(mob/user)
- if(!user.canUseTopic(src, !issilicon(user)))
+ if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return
if(stat & BROKEN)
to_chat(user, "[src]'s firmware appears to be malfunctioning!")
@@ -167,7 +167,9 @@ GLOBAL_LIST_EMPTY(announcement_systems)
act_up()
/obj/machinery/announcement_system/emag_act()
+ . = ..()
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
act_up()
+ return TRUE
diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm
index a2fdc2336f..b837553b38 100644
--- a/code/game/machinery/computer/Operating.dm
+++ b/code/game/machinery/computer/Operating.dm
@@ -88,6 +88,7 @@
data["patient"]["fireLoss"] = patient.getFireLoss()
data["patient"]["toxLoss"] = patient.getToxLoss()
data["patient"]["oxyLoss"] = patient.getOxyLoss()
+ data["patient"]["is_robotic_organism"] = HAS_TRAIT(patient, TRAIT_ROBOTIC_ORGANISM)
if(patient.surgeries.len)
data["procedures"] = list()
for(var/datum/surgery/procedure in patient.surgeries)
diff --git a/code/game/machinery/computer/arcade/battle.dm b/code/game/machinery/computer/arcade/battle.dm
index a6c98c6c9c..5a0f0e9acf 100644
--- a/code/game/machinery/computer/arcade/battle.dm
+++ b/code/game/machinery/computer/arcade/battle.dm
@@ -212,4 +212,4 @@
name = "Outbomb Cuban Pete"
updateUsrDialog()
- return TRUE
\ No newline at end of file
+ return TRUE
diff --git a/code/game/machinery/computer/law.dm b/code/game/machinery/computer/law.dm
index fa6d4327a4..fc7bec7134 100644
--- a/code/game/machinery/computer/law.dm
+++ b/code/game/machinery/computer/law.dm
@@ -69,4 +69,4 @@
return 0
if(B.scrambledcodes || B.emagged)
return 0
- return ..()
\ No newline at end of file
+ return ..()
diff --git a/code/game/machinery/computer/robot.dm b/code/game/machinery/computer/robot.dm
index 401d05da12..9b911e9c15 100644
--- a/code/game/machinery/computer/robot.dm
+++ b/code/game/machinery/computer/robot.dm
@@ -21,6 +21,9 @@
return
if(R.scrambledcodes)
return
+ if(hasSiliconAccessInArea(user) && !issilicon(user))
+ if(!Adjacent(user))
+ return
return TRUE
/obj/machinery/computer/robotics/ui_interact(mob/user, datum/tgui/ui)
@@ -40,6 +43,10 @@
else if(IsAdminGhost(user))
data["can_hack"] = TRUE
+ data["can_convert"] = FALSE
+ if(isAI(user) && is_servant_of_ratvar(user))
+ data["can_convert"] = TRUE
+
data["cyborgs"] = list()
for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs)
if(!can_control(user, R))
@@ -54,6 +61,7 @@
module = R.module ? "[R.module.name] Module" : "No Module Detected",
synchronization = R.connected_ai,
emagged = R.emagged,
+ servant = is_servant_of_ratvar(R),
ref = REF(R)
)
data["cyborgs"] += list(cyborg_data)
@@ -110,6 +118,13 @@
log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!")
message_admins("[ADMIN_LOOKUPFLW(usr)] emagged cyborg [key_name_admin(R)] using robotic console!")
R.SetEmagged(TRUE)
+ if("convert")
+ if(isAI(usr) && is_servant_of_ratvar(usr))
+ var/mob/living/silicon/robot/R = locate(params["ref"]) in GLOB.silicon_mobs
+ if(istype(R) && !is_servant_of_ratvar(R) && R.connected_ai == usr)
+ log_game("[key_name(usr)] converted [key_name(R)] using robotic console!")
+ message_admins("[ADMIN_LOOKUPFLW(usr)] converted cyborg [key_name_admin(R)] using robotic console!")
+ add_servant_of_ratvar(R)
if("killdrone")
if(allowed(usr))
var/mob/living/simple_animal/drone/D = locate(params["ref"]) in GLOB.mob_list
diff --git a/code/game/machinery/dna_scanner.dm b/code/game/machinery/dna_scanner.dm
index e721e986d2..0dcb0e7235 100644
--- a/code/game/machinery/dna_scanner.dm
+++ b/code/game/machinery/dna_scanner.dm
@@ -32,6 +32,8 @@
. = ..()
if(in_range(user, src) || isobserver(user))
. += "The status display reads: Radiation pulse accuracy increased by factor [precision_coeff**2].
Radiation pulse damage decreased by factor [damage_coeff**2]."
+ if(scan_level >= 3)
+ . += "Scanner has been upgraded to support autoprocessing."
/obj/machinery/dna_scannernew/update_icon_state()
//no power or maintenance
@@ -94,6 +96,13 @@
..(user)
+// search for ghosts, if the corpse is empty and the scanner is connected to a cloner
+ var/mob/living/mob_occupant = get_mob_or_brainmob(occupant)
+ if(istype(mob_occupant))
+ if(locate_computer(/obj/machinery/computer/cloning))
+ if(!mob_occupant.suiciding && !(HAS_TRAIT(mob_occupant, TRAIT_NOCLONE)) && !mob_occupant.hellbound)
+ mob_occupant.notify_ghost_cloning("Your corpse has been placed into a cloning scanner. Re-enter your corpse if you want to be cloned!", source = src)
+
// DNA manipulators cannot operate on severed heads or brains
if(iscarbon(occupant))
if(linked_console)
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 515a4672a5..9ef34390f6 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -1457,6 +1457,16 @@
ui.open()
return TRUE
+/obj/machinery/door/airlock/ui_status(mob/user)
+ . = ..()
+ if (!issilicon(user) && hasSiliconAccessInArea(user))
+ . = UI_INTERACTIVE
+
+/obj/machinery/door/airlock/can_interact(mob/user)
+ . = ..()
+ if (!issilicon(user) && hasSiliconAccessInArea(user))
+ return TRUE
+
/obj/machinery/door/airlock/ui_data()
var/list/data = list()
diff --git a/code/game/machinery/doors/airlock_types.dm b/code/game/machinery/doors/airlock_types.dm
index fe2bdf90b1..8941c540ae 100644
--- a/code/game/machinery/doors/airlock_types.dm
+++ b/code/game/machinery/doors/airlock_types.dm
@@ -508,7 +508,7 @@
/obj/machinery/door/airlock/cult/allowed(mob/living/L)
if(!density)
return 1
- if(friendly || iscultist(L) || istype(L, /mob/living/simple_animal/shade) || isconstruct(L))
+ if(friendly || iscultist(L) || isshade(L) || isconstruct(L))
if(!stealthy)
new openingoverlaytype(loc)
return 1
diff --git a/code/game/machinery/doors/alarmlock.dm b/code/game/machinery/doors/alarmlock.dm
index 42649a9ff2..a563200575 100644
--- a/code/game/machinery/doors/alarmlock.dm
+++ b/code/game/machinery/doors/alarmlock.dm
@@ -40,4 +40,4 @@
close()
if("minor", "clear")
autoclose = FALSE
- open()
\ No newline at end of file
+ open()
diff --git a/code/game/machinery/doors/checkForMultipleDoors.dm b/code/game/machinery/doors/checkForMultipleDoors.dm
index 35a944c965..73a9edde6f 100644
--- a/code/game/machinery/doors/checkForMultipleDoors.dm
+++ b/code/game/machinery/doors/checkForMultipleDoors.dm
@@ -13,4 +13,4 @@
if(!istype(D, /obj/machinery/door/window) && D.density)
return 0
//There are no false wall checks because that would be fucking
- return 1
\ No newline at end of file
+ return 1
diff --git a/code/game/machinery/doors/passworddoor.dm b/code/game/machinery/doors/passworddoor.dm
index 60652981cf..1ec5b3c373 100644
--- a/code/game/machinery/doors/passworddoor.dm
+++ b/code/game/machinery/doors/passworddoor.dm
@@ -70,4 +70,4 @@
return
/obj/machinery/door/password/ex_act(severity, target)
- return
\ No newline at end of file
+ return
diff --git a/code/game/machinery/doors/unpowered.dm b/code/game/machinery/doors/unpowered.dm
index 828624adb4..6e9d7f9561 100644
--- a/code/game/machinery/doors/unpowered.dm
+++ b/code/game/machinery/doors/unpowered.dm
@@ -19,4 +19,4 @@
icon_state = "door1"
opacity = 1
density = TRUE
- explosion_block = 1
\ No newline at end of file
+ explosion_block = 1
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 3cd2011334..bed006d0b5 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -55,6 +55,7 @@
icon_state = "[src.base_state]open"
/obj/machinery/door/window/update_atom_colour()
+ . = ..()
if((color && (color_hex2num(color) < 255)))
visible = TRUE
if(density)
diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm
index a9c411c634..4f27e38a14 100644
--- a/code/game/machinery/doppler_array.dm
+++ b/code/game/machinery/doppler_array.dm
@@ -187,4 +187,4 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
/obj/machinery/doppler_array/research/science/Initialize()
. = ..()
- linked_techweb = SSresearch.science_tech
\ No newline at end of file
+ linked_techweb = SSresearch.science_tech
diff --git a/code/game/machinery/embedded_controller/airlock_controller.dm b/code/game/machinery/embedded_controller/airlock_controller.dm
index ea39133112..125c6692f3 100644
--- a/code/game/machinery/embedded_controller/airlock_controller.dm
+++ b/code/game/machinery/embedded_controller/airlock_controller.dm
@@ -312,4 +312,4 @@
[state_options]"}
- return output
\ No newline at end of file
+ return output
diff --git a/code/game/machinery/mass_driver.dm b/code/game/machinery/mass_driver.dm
index 0b89b117c4..b39c6d350f 100644
--- a/code/game/machinery/mass_driver.dm
+++ b/code/game/machinery/mass_driver.dm
@@ -48,4 +48,4 @@
if(isliving(O))
var/mob/living/L = O
to_chat(L, "You feel something click beneath you!")
- addtimer(CALLBACK(src, .proc/drive), drive_delay)
\ No newline at end of file
+ addtimer(CALLBACK(src, .proc/drive), drive_delay)
diff --git a/code/game/machinery/telecomms/machines/message_server.dm b/code/game/machinery/telecomms/machines/message_server.dm
index 04fd5f6af5..a0440001c3 100644
--- a/code/game/machinery/telecomms/machines/message_server.dm
+++ b/code/game/machinery/telecomms/machines/message_server.dm
@@ -28,10 +28,10 @@
if(!do_after(user, 30 SECONDS, TRUE, src))
to_chat(user, "Your fingers slip as you fail to pry the [stored] from the [src], clicking it right back into the slot!")
return
- if(user.put_in_hands(stored))
- stored.forceMove(user.drop_location())
+ user.put_in_hands(stored)
+ to_chat(user, "You successfully pry the [stored] from the [src]\
+ [user.is_holding(stored) ? "" : ", and send its overwhelming weight tumbling onto the ground"]! The tapes on the [src] stop spinning...")
stored = null
- to_chat(user, "You successfully pry the [stored] from the [src], and send its overwhelming weight tumbling onto the ground! The tapes on the [src] stop spinning...")
update_icon()
return
else
@@ -41,7 +41,7 @@
/obj/machinery/blackbox_recorder/attackby(obj/item/I, mob/living/user, params)
. = ..()
if(istype(I, /obj/item/blackbox))
- if(HAS_TRAIT(I, TRAIT_NODROP) || !user.transferItemToLoc(I, src))
+ if(!user.transferItemToLoc(I, src))
to_chat(user, "[I] is stuck to your hand!")
return
user.visible_message("[user] clicks the [I] into the [src]!", \
diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm
index 8a4a2fdd9b..f9a86066ff 100644
--- a/code/game/mecha/combat/combat.dm
+++ b/code/game/mecha/combat/combat.dm
@@ -8,4 +8,4 @@
for(var/obj/item/I in equipment)
if(istype(I, /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/))
var/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/gun = I
- gun.projectiles_cache = gun.projectiles_cache_max
\ No newline at end of file
+ gun.projectiles_cache = gun.projectiles_cache_max
diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm
index 7c7c6be2bc..06e4208d71 100644
--- a/code/game/mecha/equipment/tools/mining_tools.dm
+++ b/code/game/mecha/equipment/tools/mining_tools.dm
@@ -172,4 +172,4 @@
mineral_scan_pulse(get_turf(src))
#undef DRILL_BASIC
-#undef DRILL_HARDENED
\ No newline at end of file
+#undef DRILL_HARDENED
diff --git a/code/game/objects/effects/blessing.dm b/code/game/objects/effects/blessing.dm
index 5df90d65c7..6db28b3700 100644
--- a/code/game/objects/effects/blessing.dm
+++ b/code/game/objects/effects/blessing.dm
@@ -24,4 +24,4 @@
/obj/effect/blessing/proc/block_cult_teleport(datum/source, channel, turf/origin, turf/destination)
if(channel == TELEPORT_CHANNEL_CULT)
- return COMPONENT_BLOCK_TELEPORT
\ No newline at end of file
+ return COMPONENT_BLOCK_TELEPORT
diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm
index fa4bfe7e67..875f23434b 100644
--- a/code/game/objects/effects/decals/cleanable/aliens.dm
+++ b/code/game/objects/effects/decals/cleanable/aliens.dm
@@ -74,4 +74,4 @@
/obj/effect/decal/cleanable/blood/xtracks/Initialize()
add_blood_DNA(list("UNKNOWN DNA" = "X*"))
- . = ..()
\ No newline at end of file
+ . = ..()
diff --git a/code/game/objects/effects/decals/turfdecal/tilecoloring.dm b/code/game/objects/effects/decals/turfdecal/tilecoloring.dm
index 85c2c78abb..7b5b4d9b4e 100644
--- a/code/game/objects/effects/decals/turfdecal/tilecoloring.dm
+++ b/code/game/objects/effects/decals/turfdecal/tilecoloring.dm
@@ -235,4 +235,4 @@
icon_state = "trimline_corner_fill"
/obj/effect/turf_decal/trimline/neutral/filled/end
- icon_state = "trimline_end_fill"
\ No newline at end of file
+ icon_state = "trimline_end_fill"
diff --git a/code/game/objects/effects/spawners/bundle.dm b/code/game/objects/effects/spawners/bundle.dm
index b75df644eb..4304fc3c9c 100644
--- a/code/game/objects/effects/spawners/bundle.dm
+++ b/code/game/objects/effects/spawners/bundle.dm
@@ -160,13 +160,13 @@
/obj/effect/spawner/bundle/costume/sexyclown
name = "sexy clown costume spawner"
items = list(
- /obj/item/clothing/mask/gas/sexyclown,
+ /obj/item/clothing/mask/gas/clown_hat/sexy,
/obj/item/clothing/under/rank/civilian/clown/sexy)
/obj/effect/spawner/bundle/costume/sexymime
name = "sexy mime costume spawner"
items = list(
- /obj/item/clothing/mask/gas/sexymime,
+ /obj/item/clothing/mask/gas/mime/sexy,
/obj/item/clothing/under/rank/civilian/mime/sexy)
/obj/effect/spawner/bundle/crate/Initialize(mapload)
diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm
index 6564a83729..bacbf3c388 100644
--- a/code/game/objects/effects/spawners/lootdrop.dm
+++ b/code/game/objects/effects/spawners/lootdrop.dm
@@ -464,7 +464,7 @@
/obj/effect/spawner/lootdrop/cigars_cases/no_turf = 2,
/obj/effect/spawner/lootdrop/space_cash/no_turf = 5,
/obj/item/reagent_containers/food/snacks/grown/cannabis = 5,
- /obj/item/storage/box/dice = 5,
+ /obj/item/storage/dice = 5,
/obj/item/toy/cards/deck = 5,
/obj/effect/spawner/lootdrop/druggie_pill/no_turf = 5
)
@@ -483,7 +483,7 @@
/obj/effect/spawner/lootdrop/cig_packs/no_turf = 10,
/obj/effect/spawner/lootdrop/cigars_cases/no_turf = 5,
/obj/item/reagent_containers/food/snacks/grown/cannabis = 5,
- /obj/item/storage/box/dice = 5,
+ /obj/item/storage/dice = 5,
/obj/item/toy/cards/deck = 5,
/obj/effect/spawner/lootdrop/druggie_pill/no_turf = 5,
/obj/item/kitchen/knife = 5,
diff --git a/code/game/objects/effects/spawners/traps.dm b/code/game/objects/effects/spawners/traps.dm
index 82cfe89662..731b4efc1d 100644
--- a/code/game/objects/effects/spawners/traps.dm
+++ b/code/game/objects/effects/spawners/traps.dm
@@ -7,4 +7,4 @@
..()
var/new_type = pick(subtypesof(/obj/structure/trap) - typesof(/obj/structure/trap/ctf))
new new_type(get_turf(src))
- return INITIALIZE_HINT_QDEL
\ No newline at end of file
+ return INITIALIZE_HINT_QDEL
diff --git a/code/game/objects/items/RSF.dm b/code/game/objects/items/RSF.dm
index 8fd2ed2377..da5ab1a5a5 100644
--- a/code/game/objects/items/RSF.dm
+++ b/code/game/objects/items/RSF.dm
@@ -93,7 +93,7 @@ RSF
use_matter(50, user)
if(4)
to_chat(user, "Dispensing Dice Pack...")
- new /obj/item/storage/box/dice(T)
+ new /obj/item/storage/dice(T)
use_matter(200, user)
if(5)
to_chat(user, "Dispensing Cigarette...")
diff --git a/code/game/objects/items/chromosome.dm b/code/game/objects/items/chromosome.dm
index 8330a8e202..3acf3cfe5c 100644
--- a/code/game/objects/items/chromosome.dm
+++ b/code/game/objects/items/chromosome.dm
@@ -89,4 +89,4 @@
/obj/item/chromosome/reinforcer/apply(datum/mutation/human/HM)
HM.mutadone_proof = TRUE
- ..()
\ No newline at end of file
+ ..()
diff --git a/code/game/objects/items/circuitboards/computer_circuitboards.dm b/code/game/objects/items/circuitboards/computer_circuitboards.dm
index 2fa48582f7..9a1c770417 100644
--- a/code/game/objects/items/circuitboards/computer_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/computer_circuitboards.dm
@@ -297,6 +297,10 @@
name = "Mining Shuttle (Computer Board)"
build_path = /obj/machinery/computer/shuttle/mining
+/obj/item/circuitboard/computer/mining_shuttle/common
+ name = "Lavaland Shuttle (Computer Board)"
+ build_path = /obj/machinery/computer/shuttle/mining/common
+
/obj/item/circuitboard/computer/snow_taxi
name = "Snow Taxi (Computer Board)"
build_path = /obj/machinery/computer/shuttle/snow_taxi
diff --git a/code/game/objects/items/control_wand.dm b/code/game/objects/items/control_wand.dm
index c98484b81e..be39bb6973 100644
--- a/code/game/objects/items/control_wand.dm
+++ b/code/game/objects/items/control_wand.dm
@@ -100,4 +100,4 @@
#undef WAND_OPEN
#undef WAND_BOLT
-#undef WAND_EMERGENCY
\ No newline at end of file
+#undef WAND_EMERGENCY
diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm
index 4777796331..ecc8f9187a 100644
--- a/code/game/objects/items/defib.dm
+++ b/code/game/objects/items/defib.dm
@@ -616,7 +616,7 @@
if(defib.healdisk)
H.heal_overall_damage(25, 25)
var/list/policies = CONFIG_GET(keyed_list/policyconfig)
- var/timelimit = CONFIG_GET(number/defib_cmd_time_limit)
+ var/timelimit = CONFIG_GET(number/defib_cmd_time_limit) * 10 //the config is in seconds, not deciseconds
var/late = timelimit && (tplus > timelimit)
var/policy = late? policies[POLICYCONFIG_ON_DEFIB_LATE] : policies[POLICYCONFIG_ON_DEFIB_INTACT]
if(policy)
diff --git a/code/game/objects/items/devices/desynchronizer.dm b/code/game/objects/items/devices/desynchronizer.dm
index e3385dc13f..2cb4922f36 100644
--- a/code/game/objects/items/devices/desynchronizer.dm
+++ b/code/game/objects/items/devices/desynchronizer.dm
@@ -91,4 +91,4 @@
return ..()
/obj/effect/abstract/sync_holder/AllowDrop()
- return TRUE //no dropping spaghetti out of your spacetime pocket
\ No newline at end of file
+ return TRUE //no dropping spaghetti out of your spacetime pocket
diff --git a/code/game/objects/items/devices/glue.dm b/code/game/objects/items/devices/glue.dm
index 2c57ede706..42fbecc780 100644
--- a/code/game/objects/items/devices/glue.dm
+++ b/code/game/objects/items/devices/glue.dm
@@ -29,4 +29,4 @@
if(uses == 0)
icon_state = "glue_used"
name = "empty bottle of super glue"
- return
\ No newline at end of file
+ return
diff --git a/code/game/objects/items/devices/megaphone.dm b/code/game/objects/items/devices/megaphone.dm
index 915fcac504..365446bad9 100644
--- a/code/game/objects/items/devices/megaphone.dm
+++ b/code/game/objects/items/devices/megaphone.dm
@@ -62,4 +62,4 @@
name = "clown's megaphone"
desc = "Something that should not exist."
icon_state = "megaphone-clown"
- voicespan = list(SPAN_CLOWN)
\ No newline at end of file
+ voicespan = list(SPAN_CLOWN)
diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm
index 7a8a523a18..c02eb4a051 100644
--- a/code/game/objects/items/devices/multitool.dm
+++ b/code/game/objects/items/devices/multitool.dm
@@ -21,13 +21,13 @@
force = 5
w_class = WEIGHT_CLASS_SMALL
tool_behaviour = TOOL_MULTITOOL
+ item_flags = SURGICAL_TOOL
throwforce = 0
throw_range = 7
throw_speed = 3
custom_materials = list(/datum/material/iron=50, /datum/material/glass=20)
var/obj/machinery/buffer // simple machine buffer for device linkage
toolspeed = 1
- tool_behaviour = TOOL_MULTITOOL
usesound = 'sound/weapons/empty.ogg'
var/datum/integrated_io/selected_io = null //functional for integrated circuits.
var/mode = 0
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index db29614f20..d9bfa4b00e 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -155,7 +155,7 @@ GENETICS SCANNER
if(oxy_loss > 10)
msg += "\n\t[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected."
if(tox_loss > 10)
- msg += "\n\t[tox_loss > 50 ? "Severe" : "Minor"] amount of toxin damage detected."
+ msg += "\n\t[tox_loss > 50 ? "Severe" : "Minor"] amount of [HAS_TRAIT(M, TRAIT_ROBOTIC_ORGANISM) ? "system corruption" : "toxin damage"] detected."
if(M.getStaminaLoss())
msg += "\n\tSubject appears to be suffering from fatigue."
if(advanced)
@@ -182,7 +182,7 @@ GENETICS SCANNER
Damage: | \
Brute | \
Burn | \
- Toxin | \
+ [HAS_TRAIT(C, TRAIT_ROBOTIC_ORGANISM) ? "Corruption" :"Toxin"] | \
Suffocation | \
| Overall: | \
[brute_loss] | \
@@ -628,9 +628,9 @@ GENETICS SCANNER
var/turf/location = get_turf(user)
if(!istype(location))
return
-
+
scan_turf(user, location)
-
+
/obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens
. = ..()
diff --git a/code/game/objects/items/dice.dm b/code/game/objects/items/dice.dm
index 2fe4c67362..bbc493672f 100644
--- a/code/game/objects/items/dice.dm
+++ b/code/game/objects/items/dice.dm
@@ -1,39 +1,38 @@
-/obj/item/storage/box/dice
+/*****************************Dice Bags********************************/
+
+/obj/item/storage/dice
name = "bag of dice"
desc = "Contains all the luck you'll ever need."
icon = 'icons/obj/dice.dmi'
icon_state = "dicebag"
+ w_class = WEIGHT_CLASS_SMALL
+ var/list/special_die = list(
+ /obj/item/dice/d1,
+ /obj/item/dice/d2,
+ /obj/item/dice/fudge,
+ /obj/item/dice/d6/space,
+ /obj/item/dice/d00,
+ /obj/item/dice/eightbd20,
+ /obj/item/dice/fourdd6,
+ /obj/item/dice/d100
+ )
-/obj/item/storage/box/dice/Initialize()
- . = ..()
- var/special_die = pick("1","2","fudge","space","00","8bd20","4dd6","100")
- if(special_die == "1")
- new /obj/item/dice/d1(src)
- if(special_die == "2")
- new /obj/item/dice/d2(src)
+/obj/item/storage/dice/PopulateContents()
new /obj/item/dice/d4(src)
new /obj/item/dice/d6(src)
- if(special_die == "fudge")
- new /obj/item/dice/fudge(src)
- if(special_die == "space")
- new /obj/item/dice/d6/space(src)
new /obj/item/dice/d8(src)
new /obj/item/dice/d10(src)
- if(special_die == "00")
- new /obj/item/dice/d00(src)
new /obj/item/dice/d12(src)
new /obj/item/dice/d20(src)
- if(special_die == "8bd20")
- new /obj/item/dice/eightbd20(src)
- if(special_die == "4dd6")
- new /obj/item/dice/fourdd6(src)
- if(special_die == "100")
- new /obj/item/dice/d100(src)
+ var/picked = pick(special_die)
+ new picked(src)
-/obj/item/storage/box/dice/suicide_act(mob/user)
+/obj/item/storage/dice/suicide_act(mob/user)
user.visible_message("[user] is gambling with death! It looks like [user.p_theyre()] trying to commit suicide!")
return (OXYLOSS)
+/*****************************Dice********************************/
+
/obj/item/dice //depreciated d6, use /obj/item/dice/d6 if you actually want a d6
name = "die"
desc = "A die with six sides. Basic and serviceable."
diff --git a/code/game/objects/items/gift.dm b/code/game/objects/items/gift.dm
index 8054d8c6a4..a9ed94aae9 100644
--- a/code/game/objects/items/gift.dm
+++ b/code/game/objects/items/gift.dm
@@ -8,6 +8,15 @@
* Gifts
*/
+GLOBAL_LIST_INIT(gift_item_blacklist, typecacheof(list(
+ /obj/effect,
+ /obj/belly,
+ /obj/mafia_game_board,
+ /obj/docking_port,
+ /obj/shapeshift_holder,
+ /obj/screen
+ )))
+
GLOBAL_LIST_EMPTY(possible_gifts)
/obj/item/a_gift
@@ -95,7 +104,7 @@ GLOBAL_LIST_EMPTY(possible_gifts)
var/list/gift_types_list = subtypesof(/obj/item)
for(var/V in gift_types_list)
var/obj/item/I = V
- if((!initial(I.icon_state)) || (!initial(I.item_state)) || (initial(I.item_flags) & ABSTRACT))
+ if((!initial(I.icon_state)) || (!initial(I.item_state)) || (initial(I.item_flags) & ABSTRACT) || (is_type_in_typecache(I, GLOB.gift_item_blacklist)))
gift_types_list -= V
GLOB.possible_gifts = gift_types_list
var/gift_type = pick(GLOB.possible_gifts)
diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm
index 58146be20f..a15e1368d8 100644
--- a/code/game/objects/items/holy_weapons.dm
+++ b/code/game/objects/items/holy_weapons.dm
@@ -492,7 +492,7 @@
var/possessed = FALSE
/obj/item/nullrod/scythe/talking/process()
- for(var/mob/living/simple_animal/shade/S in contents)
+ for(var/mob/living/simple_animal/hostile/construct/shade/S in contents)
if(S.mind)
return
else
@@ -516,7 +516,7 @@
if(LAZYLEN(candidates))
var/mob/C = pick(candidates)
- var/mob/living/simple_animal/shade/S = new(src)
+ var/mob/living/simple_animal/hostile/construct/shade/S = new(src)
S.real_name = name
S.name = name
S.ckey = C.ckey
@@ -537,7 +537,7 @@
possessed = FALSE
/obj/item/nullrod/scythe/talking/Destroy()
- for(var/mob/living/simple_animal/shade/S in contents)
+ for(var/mob/living/simple_animal/hostile/construct/shade/S in contents)
to_chat(S, "You were destroyed!")
qdel(S)
return ..()
diff --git a/code/game/objects/items/implants/implant_chem.dm b/code/game/objects/items/implants/implant_chem.dm
index 8da1d1e472..d148cbbb3c 100644
--- a/code/game/objects/items/implants/implant_chem.dm
+++ b/code/game/objects/items/implants/implant_chem.dm
@@ -96,4 +96,4 @@
if(implant?.imp_in)
qdel(implant)
else
- return ..()
\ No newline at end of file
+ return ..()
diff --git a/code/game/objects/items/implants/implant_hijack.dm b/code/game/objects/items/implants/implant_hijack.dm
index 36e58d8887..06d2df9272 100644
--- a/code/game/objects/items/implants/implant_hijack.dm
+++ b/code/game/objects/items/implants/implant_hijack.dm
@@ -92,10 +92,17 @@
/obj/item/implant/hijack/proc/hijack_remotely(obj/machinery/power/apc/apc)
if (apc.hijacker || hijacking)
return FALSE //can't remotely hijack an already hijacked APC
+
+ if(apc.being_hijacked)
+ to_chat(imp_in, "This APC is already being hijacked!")
+ return FALSE
+
+ apc.being_hijacked = TRUE
hijacking = TRUE
to_chat(imp_in, "Establishing remote connection with APC.")
if (!do_after(imp_in, 4 SECONDS,target=apc))
to_chat(imp_in, "Aborting.")
+ apc.being_hijacked = FALSE
hijacking = FALSE
return TRUE
if (LAZYLEN(imp_in.siliconaccessareas) >= HIJACK_APC_MAX_AMOUNT)
@@ -118,6 +125,7 @@
toggle_eyes()
else
to_chat(imp_in, "Aborting.")
+ apc.being_hijacked = FALSE
hijacking = FALSE
imp_in.light_power = 0
imp_in.light_range = 0
diff --git a/code/game/objects/items/implants/implant_radio.dm b/code/game/objects/items/implants/implant_radio.dm
index 6f42547004..f3e7027c37 100644
--- a/code/game/objects/items/implants/implant_radio.dm
+++ b/code/game/objects/items/implants/implant_radio.dm
@@ -66,4 +66,4 @@
/obj/item/implanter/radio/syndicate
name = "implanter (internal syndicate radio)"
- imp_type = /obj/item/implant/radio/syndicate
\ No newline at end of file
+ imp_type = /obj/item/implant/radio/syndicate
diff --git a/code/game/objects/items/implants/implant_track.dm b/code/game/objects/items/implants/implant_track.dm
index 4f81432a39..2fa0244831 100644
--- a/code/game/objects/items/implants/implant_track.dm
+++ b/code/game/objects/items/implants/implant_track.dm
@@ -73,4 +73,4 @@
/obj/item/implantcase/track
name = "implant case - 'Tracking'"
desc = "A glass case containing a tracking implant."
- imp_type = /obj/item/implant/tracking
\ No newline at end of file
+ imp_type = /obj/item/implant/tracking
diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm
index b57ffa27c0..578d8595dd 100644
--- a/code/game/objects/items/implants/implanter.dm
+++ b/code/game/objects/items/implants/implanter.dm
@@ -77,4 +77,4 @@
/obj/item/implanter/hijack
name = "implanter (hijack)"
- imp_type = /obj/item/implant/hijack
\ No newline at end of file
+ imp_type = /obj/item/implant/hijack
diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm
index e2e0779b53..f15a4d00e1 100644
--- a/code/game/objects/items/kitchen.dm
+++ b/code/game/objects/items/kitchen.dm
@@ -150,8 +150,8 @@
item_state = "knife"
desc = "A military combat utility survival knife."
embedding = list("pain_mult" = 4, "embed_chance" = 65, "fall_chance" = 10, "ignore_throwspeed_threshold" = TRUE)
- force = 20
- throwforce = 20
+ force = 16
+ throwforce = 16
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "cut")
bayonet = TRUE
diff --git a/code/game/objects/items/miscellaneous.dm b/code/game/objects/items/miscellaneous.dm
index 2d2c0f31b6..913d73bdad 100644
--- a/code/game/objects/items/miscellaneous.dm
+++ b/code/game/objects/items/miscellaneous.dm
@@ -52,7 +52,8 @@
/obj/item/choice_beacon/proc/spawn_option(atom/choice,mob/living/M)
var/obj/new_item = create_choice_atom(choice, M)
- var/obj/structure/closet/supplypod/bluespacepod/pod = new()
+ var/area/pod_storage_area = locate(/area/centcom/supplypod/podStorage) in GLOB.sortedAreas
+ var/obj/structure/closet/supplypod/bluespacepod/pod = new(pick(get_area_turfs(pod_storage_area))) //Lets just have it in the pod storage zone for a really short time because we don't want it in nullspace
pod.explosionSize = list(0,0,0,0)
new_item.forceMove(pod)
var/msg = "After making your selection, you notice a strange target on the ground. It might be best to step back!"
diff --git a/code/game/objects/items/religion.dm b/code/game/objects/items/religion.dm
index 61a05aacd8..b8f0d161dc 100644
--- a/code/game/objects/items/religion.dm
+++ b/code/game/objects/items/religion.dm
@@ -321,4 +321,4 @@
desc = "A rusted claymore, once at the heart of a powerful scottish clan struck down and oppressed by tyrants, it has been passed down the ages as a symbol of defiance."
force = 15
block_chance = 30
- armour_penetration = 5
\ No newline at end of file
+ armour_penetration = 5
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index 9f098bc16c..291fc30aa2 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -80,6 +80,7 @@ as performing this in action() will cause the upgrade to end up in the borg inst
desc = "Used to kick in a cyborg's VTEC systems, increasing their speed."
icon_state = "cyborg_upgrade2"
require_module = 1
+ var/obj/effect/proc_holder/silicon/cyborg/vtecControl/VC
/obj/item/borg/upgrade/vtec/action(mob/living/silicon/robot/R, user = usr)
. = ..()
@@ -91,12 +92,14 @@ as performing this in action() will cause the upgrade to end up in the borg inst
//R.speed = -2 // Gotta go fast.
//Citadel change - makes vtecs give an ability rather than reducing the borg's speed instantly
- R.AddAbility(new/obj/effect/proc_holder/silicon/cyborg/vtecControl)
+ VC = new /obj/effect/proc_holder/silicon/cyborg/vtecControl
+ R.AddAbility(VC)
R.cansprint = 0
/obj/item/borg/upgrade/vtec/deactivate(mob/living/silicon/robot/R, user = usr)
. = ..()
if (.)
+ R.RemoveAbility(VC)
R.speed = initial(R.speed)
R.cansprint = 1
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index 29b4dea6d8..de2e3b89fe 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -388,4 +388,4 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
/obj/item/shard/plasma/alien
name = "alien shard"
- desc = "A nasty looking shard of advanced alloy glass."
\ No newline at end of file
+ desc = "A nasty looking shard of advanced alloy glass."
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 32d65041bc..8526727464 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -388,6 +388,8 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
new/datum/stack_recipe("mining satchel", /obj/item/storage/bag/ore, 4), \
new/datum/stack_recipe("chemistry bag", /obj/item/storage/bag/chemistry, 4), \
new/datum/stack_recipe("bio bag", /obj/item/storage/bag/bio, 4), \
+ new/datum/stack_recipe("material bag", /obj/item/storage/bag/material, 4), \
+ new/datum/stack_recipe("construction bag", /obj/item/storage/bag/construction, 4), \
null, \
new/datum/stack_recipe("string", /obj/item/weaponcrafting/string, 1, time = 10), \
new/datum/stack_recipe("improvised gauze", /obj/item/stack/medical/gauze/improvised, 1, 2, 6), \
diff --git a/code/game/objects/items/storage/bags.dm b/code/game/objects/items/storage/bags.dm
index ab1aab32a0..3dd48237d6 100644
--- a/code/game/objects/items/storage/bags.dm
+++ b/code/game/objects/items/storage/bags.dm
@@ -457,6 +457,9 @@
STR.display_numerical_stacking = FALSE
STR.can_hold = typecacheof(list(/obj/item/ammo_box/magazine, /obj/item/ammo_casing))
+/*
+Bag for holding materials
+*/
/obj/item/storage/bag/material
name = "material pouch"
desc = "A pouch for sheets and RCD ammunition that manages to hang where you would normally put things in your pocket."
@@ -474,3 +477,24 @@
STR.max_items = 2
STR.display_numerical_stacking = TRUE
STR.can_hold = typecacheof(list(/obj/item/rcd_ammo, /obj/item/stack/sheet))
+
+/*
+ * Construction bag (for engineering, holds stock parts and electronics)
+ */
+
+/obj/item/storage/bag/construction
+ name = "construction bag"
+ icon = 'icons/obj/tools.dmi'
+ icon_state = "construction_bag"
+ desc = "A bag for storing small construction components."
+ w_class = WEIGHT_CLASS_TINY
+ resistance_flags = FLAMMABLE
+
+/obj/item/storage/bag/construction/ComponentInitialize()
+ . = ..()
+ var/datum/component/storage/STR = GetComponent(/datum/component/storage)
+ STR.max_combined_w_class = 100
+ STR.max_items = 50
+ STR.max_w_class = WEIGHT_CLASS_SMALL
+ STR.insert_preposition = "in"
+ STR.can_hold = typecacheof(list(/obj/item/stack/ore/bluespace_crystal, /obj/item/assembly, /obj/item/stock_parts, /obj/item/reagent_containers/glass/beaker, /obj/item/stack/cable_coil, /obj/item/circuitboard, /obj/item/electronics,/obj/item/wallframe/camera))
diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm
index 244b8c804b..476f35fe4c 100644
--- a/code/game/objects/items/storage/book.dm
+++ b/code/game/objects/items/storage/book.dm
@@ -198,7 +198,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
if(istype(A, /obj/item/cult_bastard))
for(var/obj/item/soulstone/SS in A.contents)
SS.usability = TRUE
- for(var/mob/living/simple_animal/shade/EX in SS)
+ for(var/mob/living/simple_animal/hostile/construct/shade/EX in SS)
SSticker.mode.remove_cultist(EX.mind, 1, 0)
EX.icon_state = "ghost1"
EX.name = "Purified [EX.name]"
@@ -217,7 +217,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible",
if(do_after(user, 40, target = SS))
playsound(src,'sound/effects/pray_chaplain.ogg',60,1)
SS.usability = TRUE
- for(var/mob/living/simple_animal/shade/EX in SS)
+ for(var/mob/living/simple_animal/hostile/construct/shade/EX in SS)
SSticker.mode.remove_cultist(EX.mind, 1, 0)
EX.icon_state = "ghost1"
EX.name = "Purified [EX.name]"
diff --git a/code/game/objects/items/tanks/tank_types.dm b/code/game/objects/items/tanks/tank_types.dm
index d16d1b29f1..325e49dd7a 100644
--- a/code/game/objects/items/tanks/tank_types.dm
+++ b/code/game/objects/items/tanks/tank_types.dm
@@ -198,4 +198,4 @@
/obj/item/tank/internals/methyl_bromide/populate_gas()
air_contents.set_moles(/datum/gas/methyl_bromide, (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C))
- return
\ No newline at end of file
+ return
diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm
index 0dd9885c29..36f89e57f2 100644
--- a/code/game/objects/items/tools/crowbar.dm
+++ b/code/game/objects/items/tools/crowbar.dm
@@ -8,6 +8,7 @@
usesound = 'sound/items/crowbar.ogg'
flags_1 = CONDUCT_1
slot_flags = ITEM_SLOT_BELT
+ item_flags = SURGICAL_TOOL
force = 5
throwforce = 7
w_class = WEIGHT_CLASS_SMALL
@@ -107,4 +108,4 @@
icon = 'icons/obj/advancedtools.dmi'
usesound = 'sound/weapons/sonic_jackhammer.ogg'
icon_state = "crowbar"
- toolspeed = 0.2
\ No newline at end of file
+ toolspeed = 0.2
diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm
index bf767af2ed..920afb8d14 100644
--- a/code/game/objects/items/tools/screwdriver.dm
+++ b/code/game/objects/items/tools/screwdriver.dm
@@ -8,6 +8,7 @@
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
flags_1 = CONDUCT_1
slot_flags = ITEM_SLOT_BELT
+ item_flags = SURGICAL_TOOL
force = 5
w_class = WEIGHT_CLASS_TINY
throwforce = 5
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm
index d35dad9f08..c8eb96005c 100644
--- a/code/game/objects/items/tools/weldingtool.dm
+++ b/code/game/objects/items/tools/weldingtool.dm
@@ -9,6 +9,7 @@
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
flags_1 = CONDUCT_1
slot_flags = ITEM_SLOT_BELT
+ item_flags = SURGICAL_TOOL
force = 3
throwforce = 5
hitsound = "swing_hit"
@@ -21,6 +22,9 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30)
resistance_flags = FIRE_PROOF
+ var/self_fueling = FALSE //Do we refill ourselves or not
+ var/nextrefueltick = 0 // How long it takes before we get a new fuel unit
+
custom_materials = list(/datum/material/iron=70, /datum/material/glass=30)
var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2)
var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower)
@@ -82,12 +86,18 @@
//This is to start fires. process() is only called if the welder is on.
open_flame()
+ //This handles refueling. Its looking at how much fuel the tool has and comparing that to how much it holds
+ //This then looks if the refuel tick has come based on world time.
+ //Then looks if we refuel ourselves or not.
+
+ if(get_fuel() < max_fuel && nextrefueltick < world.time && self_fueling)
+ nextrefueltick = world.time + 10
+ reagents.add_reagent(/datum/reagent/fuel, 1)
/obj/item/weldingtool/suicide_act(mob/user)
user.visible_message("[user] welds [user.p_their()] every orifice closed! It looks like [user.p_theyre()] trying to commit suicide!")
return (FIRELOSS)
-
/obj/item/weldingtool/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/screwdriver))
flamethrower_screwdriver(I, user)
@@ -318,7 +328,6 @@
/obj/item/weldingtool/largetank/flamethrower_screwdriver()
return
-
/obj/item/weldingtool/mini
name = "emergency welding tool"
desc = "A miniature welder used during emergencies."
@@ -331,20 +340,6 @@
/obj/item/weldingtool/mini/flamethrower_screwdriver()
return
-/obj/item/weldingtool/abductor
- name = "alien welding tool"
- desc = "An alien welding tool. Whatever fuel it uses, it never runs out."
- icon = 'icons/obj/abductor.dmi'
- icon_state = "welder"
- toolspeed = 0.1
- light_intensity = 0
- change_icons = 0
-
-/obj/item/weldingtool/abductor/process()
- if(get_fuel() <= max_fuel)
- reagents.add_reagent(/datum/reagent/fuel, 1)
- ..()
-
/obj/item/weldingtool/hugetank
name = "upgraded industrial welding tool"
desc = "An upgraded welder based of the industrial welder."
@@ -353,27 +348,6 @@
max_fuel = 80
custom_materials = list(/datum/material/iron=70, /datum/material/glass=120)
-/obj/item/weldingtool/experimental
- name = "experimental welding tool"
- desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes."
- icon_state = "exwelder"
- item_state = "exwelder"
- max_fuel = 40
- custom_materials = list(/datum/material/iron=70, /datum/material/glass=120)
- var/last_gen = 0
- change_icons = 0
- can_off_process = 1
- light_intensity = 1
- toolspeed = 0.5
- var/nextrefueltick = 0
-
-/obj/item/weldingtool/experimental/brass
- name = "brass welding tool"
- desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch."
- resistance_flags = FIRE_PROOF | ACID_PROOF
- icon_state = "clockwelder"
- item_state = "brasswelder"
-
/obj/item/weldingtool/bronze
name = "bronze plated welding tool"
desc = "A bronze plated welder."
@@ -382,24 +356,46 @@
icon_state = "brasswelder"
item_state = "brasswelder"
-/obj/item/weldingtool/experimental/process()
- ..()
- if(get_fuel() < max_fuel && nextrefueltick < world.time)
- nextrefueltick = world.time + 10
- reagents.add_reagent(/datum/reagent/fuel, 1)
+//Self filling welders below
+
+/obj/item/weldingtool/experimental
+ name = "experimental welding tool"
+ desc = "An experimental welder capable of self-fuel generation and less harmful to the eyes."
+ icon_state = "exwelder"
+ item_state = "exwelder"
+ max_fuel = 40
+ custom_materials = list(/datum/material/iron=70, /datum/material/glass=120)
+ change_icons = 0
+ self_fueling = TRUE
+ can_off_process = 1
+ light_intensity = 1
+ toolspeed = 0.5
+
+/obj/item/weldingtool/experimental/brass
+ name = "brass welding tool"
+ desc = "A brass welder that seems to constantly refuel itself. It is faintly warm to the touch."
+ resistance_flags = FIRE_PROOF | ACID_PROOF
+ icon_state = "clockwelder"
+ item_state = "brasswelder"
+
+/obj/item/weldingtool/abductor
+ name = "alien welding tool"
+ desc = "An alien welding tool. Whatever fuel it uses, it never runs out."
+ icon = 'icons/obj/abductor.dmi'
+ icon_state = "welder"
+ self_fueling = TRUE
+ toolspeed = 0.1
+ light_intensity = 0
+ change_icons = 0
/obj/item/weldingtool/advanced
name = "advanced welding tool"
desc = "A modern welding tool combined with an alien welding tool, it never runs out of fuel and works almost as fast."
icon = 'icons/obj/advancedtools.dmi'
icon_state = "welder"
+ self_fueling = TRUE
toolspeed = 0.2
light_intensity = 0
change_icons = 0
-/obj/item/weldingtool/advanced/process()
- if(get_fuel() <= max_fuel)
- reagents.add_reagent(/datum/reagent/fuel, 1)
- ..()
-
#undef WELDER_FUEL_BURN_INTERVAL
diff --git a/code/game/objects/items/tools/wirecutters.dm b/code/game/objects/items/tools/wirecutters.dm
index 000b816d70..ee72c7fed2 100644
--- a/code/game/objects/items/tools/wirecutters.dm
+++ b/code/game/objects/items/tools/wirecutters.dm
@@ -8,6 +8,7 @@
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
flags_1 = CONDUCT_1
slot_flags = ITEM_SLOT_BELT
+ item_flags = SURGICAL_TOOL
force = 6
throw_speed = 3
throw_range = 7
@@ -148,4 +149,4 @@
icon = 'icons/obj/advancedtools.dmi'
icon_state = "cutters"
toolspeed = 0.2
- random_color = FALSE
\ No newline at end of file
+ random_color = FALSE
diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/wrench.dm
index e8b77199d7..6199e7fc76 100644
--- a/code/game/objects/items/tools/wrench.dm
+++ b/code/game/objects/items/tools/wrench.dm
@@ -7,6 +7,7 @@
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
flags_1 = CONDUCT_1
slot_flags = ITEM_SLOT_BELT
+ item_flags = SURGICAL_TOOL
force = 5
throwforce = 7
w_class = WEIGHT_CLASS_SMALL
@@ -128,4 +129,4 @@
icon = 'icons/obj/advancedtools.dmi'
icon_state = "wrench"
usesound = 'sound/effects/empulse.ogg'
- toolspeed = 0.2
\ No newline at end of file
+ toolspeed = 0.2
diff --git a/code/game/objects/structures/chess.dm b/code/game/objects/structures/chess.dm
index 8254405fee..ec882f34f8 100644
--- a/code/game/objects/structures/chess.dm
+++ b/code/game/objects/structures/chess.dm
@@ -73,4 +73,4 @@
/obj/structure/chess/blackking
name = "\improper Black King"
desc = "A black king chess piece. It can move one tile in any direction."
- icon_state = "black_king"
\ No newline at end of file
+ icon_state = "black_king"
diff --git a/code/game/objects/structures/crates_lockers/closets/bodybag.dm b/code/game/objects/structures/crates_lockers/closets/bodybag.dm
index e51aeafdc1..2df57e1d68 100644
--- a/code/game/objects/structures/crates_lockers/closets/bodybag.dm
+++ b/code/game/objects/structures/crates_lockers/closets/bodybag.dm
@@ -108,4 +108,4 @@
icon_state = "radbodybag"
mob_storage_capacity = 1
foldedbag_path = /obj/item/bodybag/containment
- rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
\ No newline at end of file
+ rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
index 05798df953..3cbeae1ce8 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm
@@ -30,6 +30,8 @@
new /obj/item/construction/rcd/loaded/upgraded(src)
new /obj/item/clothing/suit/hooded/wintercoat/ce(src)
new /obj/item/clothing/head/beret/ce/white(src)
+ new /obj/item/storage/bag/construction(src)
+ new /obj/item/storage/bag/material(src)
/obj/structure/closet/secure_closet/engineering_electrical
name = "electrical supplies locker"
@@ -78,6 +80,8 @@
new /obj/item/clothing/glasses/meson/engine(src)
new /obj/item/storage/box/emptysandbags(src)
new /obj/item/cartridge/engineering(src)
+ new /obj/item/storage/bag/construction(src)
+ new /obj/item/storage/bag/material(src)
/obj/structure/closet/secure_closet/atmospherics
name = "\proper atmospheric technician's locker"
@@ -99,6 +103,8 @@
new /obj/item/clothing/glasses/meson/engine/tray(src)
new /obj/item/extinguisher/advanced(src)
new /obj/item/cartridge/atmos(src)
+ new /obj/item/storage/bag/construction(src)
+ new /obj/item/storage/bag/material(src)
/*
* Empty lockers
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/hydroponics.dm b/code/game/objects/structures/crates_lockers/closets/secure/hydroponics.dm
index a9e6243060..c554cad034 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/hydroponics.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/hydroponics.dm
@@ -10,4 +10,4 @@
new /obj/item/radio/headset/headset_srv(src)
new /obj/item/cultivator(src)
new /obj/item/hatchet(src)
- new /obj/item/storage/box/disks_plantgene(src)
\ No newline at end of file
+ new /obj/item/storage/box/disks_plantgene(src)
diff --git a/code/game/objects/structures/crates_lockers/crates/wooden.dm b/code/game/objects/structures/crates_lockers/crates/wooden.dm
index 09d176783a..6c8d3066ee 100644
--- a/code/game/objects/structures/crates_lockers/crates/wooden.dm
+++ b/code/game/objects/structures/crates_lockers/crates/wooden.dm
@@ -15,4 +15,4 @@
new /obj/item/reagent_containers/food/drinks/soda_cans/canned_laughter(src)
new /obj/item/pneumatic_cannon/pie(src)
new /obj/item/reagent_containers/food/snacks/pie/cream(src)
- new /obj/item/storage/crayons(src)
\ No newline at end of file
+ new /obj/item/storage/crayons(src)
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index 19c0f0aed1..2eda9f126a 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -553,4 +553,4 @@
/obj/structure/displaycase/forsale/kitchen
desc = "A display case with an ID-card swiper. Use your ID to purchase the contents. Meant for the bartender and chef."
req_one_access = list(ACCESS_KITCHEN, ACCESS_BAR)
-*/
\ No newline at end of file
+*/
diff --git a/code/game/objects/structures/loom.dm b/code/game/objects/structures/loom.dm
index 164e597117..28ff5a8de7 100644
--- a/code/game/objects/structures/loom.dm
+++ b/code/game/objects/structures/loom.dm
@@ -38,4 +38,4 @@
user.show_message("You weave \the [W.name] into a workable fabric.", MSG_VISUAL)
return TRUE
-#undef FABRIC_PER_SHEET
\ No newline at end of file
+#undef FABRIC_PER_SHEET
diff --git a/code/game/objects/structures/memorial.dm b/code/game/objects/structures/memorial.dm
index 243a7e3cba..d359cfc54a 100644
--- a/code/game/objects/structures/memorial.dm
+++ b/code/game/objects/structures/memorial.dm
@@ -18,4 +18,4 @@ This memorial has been designed for him and any future coders to perish.
icon = 'icons/obj/tomb.dmi'
icon_state = "memorial"
density = TRUE
- anchored = TRUE
\ No newline at end of file
+ anchored = TRUE
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index fa6bab0fcc..32040b8573 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -94,7 +94,7 @@
name = "magic mirror"
desc = "Turn and face the strange... face."
icon_state = "magic_mirror"
- var/list/races_blacklist = list("skeleton", "agent", "angel", "military_synth", "memezombies", "clockwork golem servant", "android", "synth", "mush", "zombie", "memezombie")
+ var/list/races_blacklist = list("skeleton", "agent", "military_synth", "memezombies", "clockwork golem servant", "android", "synth", "mush", "zombie", "memezombie")
var/list/choosable_races = list()
/obj/structure/mirror/magic/New()
diff --git a/code/game/objects/structures/mop_bucket.dm b/code/game/objects/structures/mop_bucket.dm
index e1bb143fef..3eb88ad12d 100644
--- a/code/game/objects/structures/mop_bucket.dm
+++ b/code/game/objects/structures/mop_bucket.dm
@@ -26,4 +26,4 @@
/obj/structure/mopbucket/update_overlays()
. = ..()
if(reagents.total_volume > 0)
- . += "mopbucket_water"
\ No newline at end of file
+ . += "mopbucket_water"
diff --git a/code/game/objects/structures/spawner.dm b/code/game/objects/structures/spawner.dm
index e67ef7af60..9032a80d91 100644
--- a/code/game/objects/structures/spawner.dm
+++ b/code/game/objects/structures/spawner.dm
@@ -72,4 +72,4 @@
/obj/structure/spawner/mining/wumborian
name = "wumborian fugu den"
desc = "A den housing a nest of wumborian fugus, how do they all even fit in there?"
- mob_types = list(/mob/living/simple_animal/hostile/asteroid/fugu)
\ No newline at end of file
+ mob_types = list(/mob/living/simple_animal/hostile/asteroid/fugu)
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 10c79bb658..d4b2d03428 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -783,7 +783,8 @@
if(ispath(chosen, /turf))
T.ChangeTurf(chosen)
else
- var/obj/structure/closet/supplypod/centcompod/pod = new()
+ var/area/pod_storage_area = locate(/area/centcom/supplypod/podStorage) in GLOB.sortedAreas
+ var/obj/structure/closet/supplypod/centcompod/pod = new(pick(get_area_turfs(pod_storage_area))) //Lets just have it in the pod bay for a moment instead of runtiming
var/atom/A = new chosen(pod)
A.flags_1 |= ADMIN_SPAWNED_1
new /obj/effect/pod_landingzone(T, pod)
diff --git a/code/modules/admin/check_antagonists.dm b/code/modules/admin/check_antagonists.dm
index c5861b95e1..532a11a532 100644
--- a/code/modules/admin/check_antagonists.dm
+++ b/code/modules/admin/check_antagonists.dm
@@ -212,4 +212,4 @@
dat += build_antag_listing()
dat += "