diff --git a/code/__DEFINES/gamemode.dm b/code/__DEFINES/gamemode.dm
index 2f2f64db4f5..33958d237c2 100644
--- a/code/__DEFINES/gamemode.dm
+++ b/code/__DEFINES/gamemode.dm
@@ -70,3 +70,4 @@
#define SPECIAL_ROLE_THIEF "Thief"
#define SPECIAL_ROLE_SPACE_DRAGON "Space Dragon"
#define SPECIAL_ROLE_EVENTMISC "Event Role"
+#define SPECIAL_ROLE_MALFAI "Malfunctioning AI"
diff --git a/code/__DEFINES/vampire_defines.dm b/code/__DEFINES/vampire_defines.dm
index a0663014e6f..90123400739 100644
--- a/code/__DEFINES/vampire_defines.dm
+++ b/code/__DEFINES/vampire_defines.dm
@@ -16,3 +16,5 @@
#define NEW_NULLIFICATION 1 //nulifiaction like the new vampires
#define OLD_NULLIFICATION 2 //nulifiaction like the goon vampires
+
+#define REQ_BLOOD_FOR_SUBCLASS_ACT 400 // total blood required for a special subclass action
diff --git a/code/controllers/configuration/entries/config.dm b/code/controllers/configuration/entries/config.dm
index 5da930d43d3..f6570a41142 100644
--- a/code/controllers/configuration/entries/config.dm
+++ b/code/controllers/configuration/entries/config.dm
@@ -397,8 +397,6 @@
/datum/config_entry/number/simultaneous_pm_warning_timeout
default = 100
-///Do assistants get maint access?
-/datum/config_entry/flag/assistant_maint
///How long the gateway takes before it activates. Default is 10 minutes. Only matters if roundstart_away is enabled.
/datum/config_entry/number/gateway_delay
diff --git a/code/controllers/configuration/entries/testing.dm b/code/controllers/configuration/entries/testing.dm
index ade389fb95c..009cc38beed 100644
--- a/code/controllers/configuration/entries/testing.dm
+++ b/code/controllers/configuration/entries/testing.dm
@@ -4,3 +4,9 @@
///Enables bombarda crafting on server.
/datum/config_entry/flag/enable_bombarda_craft
+
+///Enables loading titlescreen only after master has been loaded.
+/datum/config_entry/flag/enable_titlescreen_lateload
+
+///Do not load station
+/datum/config_entry/flag/load_no_station
diff --git a/code/controllers/subsystem/icon_smooth.dm b/code/controllers/subsystem/icon_smooth.dm
index 07aa1838d88..7648dc8b4bb 100644
--- a/code/controllers/subsystem/icon_smooth.dm
+++ b/code/controllers/subsystem/icon_smooth.dm
@@ -7,11 +7,18 @@ SUBSYSTEM_DEF(icon_smooth)
offline_implications = "Objects will no longer smooth together properly. No immediate action is needed."
cpu_display = SS_CPUDISPLAY_LOW
ss_id = "icon_smooth"
-
+ /**
+ * Used to track instances of icon smooth halters. Does not apply to roundstart loading, however.
+ * Always make sure to remove halt source from this list on the end of operation.
+ */
+ var/halt_sources = list()
var/list/smooth_queue = list()
/datum/controller/subsystem/icon_smooth/fire()
+ if(length(halt_sources))
+ return
+
while(smooth_queue.len)
var/atom/A = smooth_queue[smooth_queue.len]
smooth_queue.len--
@@ -44,3 +51,9 @@ SUBSYSTEM_DEF(icon_smooth)
CHECK_TICK
return SS_INIT_SUCCESS
+
+/datum/controller/subsystem/icon_smooth/proc/add_halt_source(datum/source)
+ halt_sources += source
+
+/datum/controller/subsystem/icon_smooth/proc/remove_halt_source(datum/source)
+ halt_sources -= source
diff --git a/code/controllers/subsystem/non-firing/atoms.dm b/code/controllers/subsystem/non-firing/atoms.dm
index 2a2a0caef1f..ff843736a49 100644
--- a/code/controllers/subsystem/non-firing/atoms.dm
+++ b/code/controllers/subsystem/non-firing/atoms.dm
@@ -27,6 +27,7 @@ SUBSYSTEM_DEF(atoms)
if(initialized == INITIALIZATION_INSSATOMS)
return
+ SSicon_smooth.add_halt_source(src)
initialized = INITIALIZATION_INNEW_MAPLOAD
LAZYINITLIST(late_loaders)
@@ -79,6 +80,7 @@ SUBSYSTEM_DEF(atoms)
log_debug(" Late initialized [length(late_loaders)] atoms in [stop_watch(watch)]s")
late_loaders.Cut()
+ SSicon_smooth.remove_halt_source(src)
/datum/controller/subsystem/atoms/proc/InitAtom(atom/A, list/arguments)
var/the_type = A.type
@@ -127,11 +129,12 @@ SUBSYSTEM_DEF(atoms)
/datum/controller/subsystem/atoms/proc/map_loader_begin()
old_initialized = initialized
initialized = INITIALIZATION_INSSATOMS
+ SSicon_smooth.add_halt_source(src)
/datum/controller/subsystem/atoms/proc/map_loader_stop()
initialized = old_initialized
-
+ SSicon_smooth.remove_halt_source(src)
/datum/controller/subsystem/atoms/Recover()
initialized = SSatoms.initialized
diff --git a/code/controllers/subsystem/non-firing/mapping.dm b/code/controllers/subsystem/non-firing/mapping.dm
index c0c6a4cd231..1680d0cc703 100644
--- a/code/controllers/subsystem/non-firing/mapping.dm
+++ b/code/controllers/subsystem/non-firing/mapping.dm
@@ -240,8 +240,27 @@ SUBSYSTEM_DEF(mapping)
seedRuins(levels_by_trait(SPAWN_RUINS), rand(20, 30), /area/space, GLOB.space_ruins_templates)
log_startup_progress("Successfully seeded ruins in [stop_watch(seed_ruins_timer)]s.")
+/datum/controller/subsystem/mapping/proc/create_landmarks(turf/place)
+ var/landmarks = list(
+ /obj/effect/landmark/join_late,
+ /obj/effect/landmark/join_late_cryo,
+ /obj/effect/landmark/join_late_cyborg,
+ /obj/effect/landmark/join_late_gateway,
+ /obj/effect/landmark/observer_start
+ )
+
+ landmarks += subtypesof(/obj/effect/landmark/start)
+ for(var/mark in landmarks)
+ new mark(place)
/datum/controller/subsystem/mapping/proc/loadStation()
+ if(CONFIG_GET(flag/load_no_station))
+ log_startup_progress("Loading empty space...")
+ var/empty_z_level = GLOB.space_manager.add_new_zlevel(MAIN_STATION, linkage = CROSSLINKED, traits = DEFAULT_STATION_TRATS)
+ var/turf/centre = locate(world.maxx / 2, world.maxy / 2, empty_z_level)
+ create_landmarks(centre)
+ return
+
if(CONFIG_GET(string/default_map) && !CONFIG_GET(string/override_map) && map_datum == fallback_map)
var/map_datum_path = text2path(CONFIG_GET(string/default_map))
if(map_datum_path)
@@ -263,7 +282,6 @@ SUBSYSTEM_DEF(mapping)
var/watch = start_watch()
log_startup_progress("Loading [map_datum.station_name]...")
-
var/map_z_level
if(map_datum.traits && map_datum.traits?.len && islist(map_datum.traits[1])) // we work with list of lists
map_z_level = GLOB.space_manager.add_new_zlevel(MAIN_STATION, linkage = map_datum.linkage, traits = map_datum.traits[1])
diff --git a/code/controllers/subsystem/non-firing/titlescreen.dm b/code/controllers/subsystem/non-firing/titlescreen.dm
index 1de3e185f67..ddcf80acf80 100644
--- a/code/controllers/subsystem/non-firing/titlescreen.dm
+++ b/code/controllers/subsystem/non-firing/titlescreen.dm
@@ -18,9 +18,14 @@ SUBSYSTEM_DEF(title)
import_html()
fill_title_images_pool()
current_title_screen = new(title_html = base_html, screen_image_file = pick_title_image())
- show_title_screen_to_all_new_players()
+ if(!CONFIG_GET(flag/enable_titlescreen_lateload))
+ show_title_screen_to_all_new_players()
return SS_INIT_SUCCESS
+/datum/controller/subsystem/title/OnMasterLoad()
+ if(CONFIG_GET(flag/enable_titlescreen_lateload))
+ show_title_screen_to_all_new_players()
+
/datum/controller/subsystem/title/Recover()
current_title_screen = SStitle.current_title_screen
title_images_pool = SStitle.title_images_pool
diff --git a/code/datums/action.dm b/code/datums/action.dm
index 415da08fa9f..ce7e9830f6e 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -317,6 +317,9 @@
desc = "Toggles if the club's blasts cause friendly fire."
button_icon_state = "vortex_ff_on"
+/datum/action/item_action/toggle_backpack_light
+ name = "Toggle Backpack Light"
+
/datum/action/item_action/toggle_unfriendly_fire/Trigger(left_click = TRUE)
if(..())
UpdateButtonIcon()
diff --git a/code/datums/helper_datums/map_template.dm b/code/datums/helper_datums/map_template.dm
index 3c6e5a2a0d4..4c9fca5d1d2 100644
--- a/code/datums/helper_datums/map_template.dm
+++ b/code/datums/helper_datums/map_template.dm
@@ -49,6 +49,7 @@
// if given a multi-z template
// it might need to be adapted for that when that time comes
GLOB.space_manager.add_dirt(placement.z)
+ SSicon_smooth.add_halt_source(src)
try
var/list/bounds = GLOB.maploader.load_map(get_file(), min_x, min_y, placement.z, shouldCropMap = TRUE)
if(!bounds)
@@ -58,11 +59,13 @@
if(ST_bot_left == null || ST_top_right == null)
stack_trace("One of the smoothing corners is bust")
catch(var/exception/e)
+ SSicon_smooth.remove_halt_source(src)
GLOB.space_manager.remove_dirt(placement.z)
message_admins("Map template [name] threw an error while loading. Safe exit attempted, but check for errors at [ADMIN_COORDJMP(placement)].")
log_admin("Map template [name] threw an error while loading. Safe exit attempted.")
throw e
+ SSicon_smooth.remove_halt_source(src)
GLOB.space_manager.remove_dirt(placement.z)
add_game_logs("[name] loaded at [min_x],[min_y],[placement.z]")
diff --git a/code/datums/looping_sounds/item_sounds.dm b/code/datums/looping_sounds/item_sounds.dm
index 4233c478644..e3a41b07ae5 100644
--- a/code/datums/looping_sounds/item_sounds.dm
+++ b/code/datums/looping_sounds/item_sounds.dm
@@ -3,3 +3,6 @@
start_sound = list('sound/items/taperecorder/taperecorder_hiss_start.ogg')
volume = 10
+/datum/looping_sound/ambulance_alarm/justice
+ mid_length = 1.5 SECONDS
+ falloff_exponent = 4
diff --git a/code/datums/rituals.dm b/code/datums/rituals.dm
index c48beea72f1..60be0aa23b1 100644
--- a/code/datums/rituals.dm
+++ b/code/datums/rituals.dm
@@ -508,7 +508,7 @@
)
/datum/ritual/ashwalker/curse/del_things()
- for(var/mob/living/carbon/human/human as anything in used_things)
+ for(var/mob/living/carbon/human/human in used_things)
human.gib()
return
@@ -519,7 +519,7 @@
if(!.)
return FALSE
- for(var/mob/living/carbon/human/human as anything in used_things)
+ for(var/mob/living/carbon/human/human in used_things)
if(human.stat != DEAD)
to_chat(invoker, "Гуманоиды должны быть мертвы.")
return FALSE
@@ -812,7 +812,7 @@
return TRUE
/datum/ritual/ashwalker/population/del_things()
- for(var/mob/living/living as anything in used_things)
+ for(var/mob/living/living in used_things)
living.gib()
return
@@ -823,7 +823,7 @@
if(!.)
return FALSE
- for(var/mob/living/living as anything in used_things)
+ for(var/mob/living/living in used_things)
if(living.stat != DEAD)
to_chat(invoker, "Существа должны быть мертвы.")
return FALSE
@@ -969,13 +969,9 @@
return TRUE
/datum/ritual/ashwalker/transmutation/do_ritual(mob/living/carbon/human/invoker)
- var/list/ore_types = list()
-
- for(var/obj/item/stack/ore/ore as anything in subtypesof(/obj/item/stack/ore))
- LAZYADD(ore_types, ore)
+ var/ore_type = pick(subtypesof(/obj/item/stack/ore))
- var/obj/item/stack/ore/ore = pick(ore_types)
- ore = new(get_turf(ritual_object))
+ var/obj/item/stack/ore/ore = new ore_type(get_turf(ritual_object))
ore.add(10)
return RITUAL_SUCCESSFUL
@@ -1113,7 +1109,7 @@
if(!.)
return FALSE
- for(var/mob/living/carbon/human/human as anything in used_things)
+ for(var/mob/living/carbon/human/human in used_things)
if(human.stat != DEAD)
to_chat(invoker, "Гуманоиды должны быть мертвы.")
return FALSE
@@ -1178,7 +1174,7 @@
if(!.)
return FALSE
- for(var/mob/living/simple_animal/living as anything in used_things)
+ for(var/mob/living/simple_animal/living in used_things)
if(living.client)
to_chat(invoker, "Существо должно быть бездушным.")
return FALSE
diff --git a/code/game/dna/genes/disabilities.dm b/code/game/dna/genes/disabilities.dm
index 70e7ab98ca0..3e17d60509f 100644
--- a/code/game/dna/genes/disabilities.dm
+++ b/code/game/dna/genes/disabilities.dm
@@ -266,7 +266,7 @@
/datum/dna/gene/disability/wingdings
name = "Alien Voice"
desc = "Искажает голос субъекта, превращая его в непонятную речь."
- activation_message = list(span_wingdings("Ваши голосовые связки кажутся инородными."))
+ activation_message = list(span_wingdings("Vashi golosovyye svyazki kazhutsya chuzhimi."))
deactivation_message = list("Ваши голосовые связки больше не кажутся инородными.")
instability = -GENE_INSTABILITY_MINOR
traits_to_add = list(TRAIT_WINGDINGS)
@@ -303,7 +303,7 @@
/datum/dna/gene/disability/weak
name = "Weak"
desc = "Делает мышцы субъекта более слабыми."
- activation_message = list("Вы чуствуете внезапную слабость в мышцах.")
+ activation_message = list("Вы чувствуете внезапную слабость в мышцах.")
deactivation_message = list("Вы снова ощущаете силу в мышцах.")
instability = -GENE_INSTABILITY_MODERATE
traits_to_add = list(TRAIT_GENE_WEAK)
@@ -378,7 +378,7 @@
/datum/dna/gene/disability/paraplegia
name = "Paraplegia"
desc = "Парализует мышцы ног."
- activation_message = list("Вы не чуствуете своих ног.")
+ activation_message = list("Вы не чувствуете своих ног.")
deactivation_message = list("Вы возвращаете контроль над ногами.")
instability = -GENE_INSTABILITY_MAJOR
traits_to_add = list(TRAIT_FLOORED)
diff --git a/code/game/dna/genes/goon_powers.dm b/code/game/dna/genes/goon_powers.dm
index 84908917c69..313db2a819a 100644
--- a/code/game/dna/genes/goon_powers.dm
+++ b/code/game/dna/genes/goon_powers.dm
@@ -586,7 +586,7 @@
numbers += H.mind.initial_account.account_number
numbers += H.mind.initial_account.remote_access_pin
if(numbers.len>0)
- to_chat(user, span_notice("Числа: Вы чувствуете, что [numbers.len > 1?"число является важным" : "числа являются важными"] для [M.name]."))
+ to_chat(user, span_notice("Числа: Вы чувствуете, что [numbers.len > 1 ? "числа" : "число"] [english_list(numbers)] [numbers.len > 1 ? "являются важными" : "является важным"] для [M.name]."))
to_chat(user, span_notice("Мысли: [M.name] сейчас [thoughts]."))
if(HAS_TRAIT(M, TRAIT_EMPATHY))
diff --git a/code/game/gamemodes/antag_paradise/antag_paradise.dm b/code/game/gamemodes/antag_paradise/antag_paradise.dm
index 7ac097ddd9c..fd86374286d 100644
--- a/code/game/gamemodes/antag_paradise/antag_paradise.dm
+++ b/code/game/gamemodes/antag_paradise/antag_paradise.dm
@@ -107,7 +107,7 @@
if(special_antag)
special_antag.restricted_roles = (restricted_jobs|protected_jobs|protected_jobs_AI)
special_antag.restricted_roles -= JOB_TITLE_AI
- special_antag.special_role = SPECIAL_ROLE_TRAITOR
+ special_antag.special_role = SPECIAL_ROLE_MALFAI
SSjobs.new_malf = special_antag.current
pre_antags[special_antag] = ROLE_MALF_AI
antags_amount--
diff --git a/code/game/gamemodes/clockwork/clockwork_structures.dm b/code/game/gamemodes/clockwork/clockwork_structures.dm
index b03ff5ed786..ba6f966f89f 100644
--- a/code/game/gamemodes/clockwork/clockwork_structures.dm
+++ b/code/game/gamemodes/clockwork/clockwork_structures.dm
@@ -18,12 +18,12 @@
/obj/structure/clockwork/functional
max_integrity = 100
var/cooldowntime = 0
- var/death_message = "The structure falls apart."
+ var/death_message = span_danger("The structure falls apart.")
var/death_sound = 'sound/effects/forge_destroy.ogg'
var/canbehidden = FALSE
var/hidden = FALSE
var/hidden_type
- var/list/choosable_items = list(
+ var/list/atom/choosable_items = list(
"rack" = /obj/structure/rack,
"table" = /obj/structure/table,
"wooden table" = /obj/structure/table/wood,
@@ -37,19 +37,7 @@
if(!hidden)
name = initial(name)
return
- switch(hidden_type)
- if("rack")
- name = "rack"
- if("table")
- name = "table"
- if("wooden table")
- name = "wooden table"
- if("personal closet")
- name = "personal closet"
- if("girder")
- name = "girder"
- if("bookcase")
- name = "bookcase"
+ name = choosable_items[hidden_type]::name
/obj/structure/clockwork/functional/update_desc(updates = ALL)
@@ -57,19 +45,19 @@
if(!hidden)
desc = initial(desc)
return
- switch(hidden_type)
+ switch(hidden_type) //used in case, where objects "examine" text aren't in their desc var (like in proc/examine()) or if you want do something funny
if("rack")
- desc = "Different from the Middle Ages version.
It's held together by a couple of bolts."
+ desc = "Different from the Middle Ages version.
[span_notice("It's held together by a couple of bolts.")]"
if("table")
- desc = "A square piece of metal standing on four metal legs. It can not move.
The top is screwed on, but the main bolts are also visible."
+ desc = "A square piece of metal standing on four metal legs. It can not move.
[span_notice("The top is screwed on, but the main bolts are also visible.")]"
if("wooden table")
- desc = "Do not apply fire to this. Rumour says it burns easily.
The top is screwed on, but the main bolts are also visible."
- if("personal closet")
- desc = "It's a secure locker for personnel. The first card swiped gains control."
+ desc = "Do not apply fire to this. Rumour says it burns easily.
[span_notice("The top is screwed on, but the main bolts are also visible.")]"
if("girder")
- desc = "The bolts are lodged in place."
- if("bookcase")
- desc = null
+ desc = "[span_notice("The bolts are lodged in place.")]"
+ if("broken grille")
+ desc = "A flimsy framework of metal rods.
[span_notice("It's secured in place with screws. The rods look like they could be cut through.")]"
+ else
+ desc = choosable_items[hidden_type]::desc
/obj/structure/clockwork/functional/update_icon_state()
@@ -77,25 +65,8 @@
icon = initial(icon)
icon_state = anchored ? "[initial(icon_state)]-off" : initial(icon_state)
return
- switch(hidden_type)
- if("rack")
- icon = 'icons/obj/objects.dmi'
- icon_state = "rack"
- if("table")
- icon = 'icons/obj/smooth_structures/table.dmi'
- icon_state = "table"
- if("wooden table")
- icon = 'icons/obj/smooth_structures/wood_table.dmi'
- icon_state = "wood_table"
- if("personal closet")
- icon = 'icons/obj/closet.dmi'
- icon_state = "secureoff"
- if("girder")
- icon = 'icons/obj/structures.dmi'
- icon_state = "girder"
- if("bookcase")
- icon = 'icons/obj/library.dmi'
- icon_state = "book-0"
+ icon = choosable_items[hidden_type]::icon
+ icon_state = choosable_items[hidden_type]::icon_state
/obj/structure/clockwork/functional/attackby(obj/item/I, mob/user, params)
@@ -139,7 +110,7 @@
/obj/structure/clockwork/functional/examine(mob/user)
. = ..()
if(hidden && isclocker(user))
- . += "It's a disguised [initial(name)]!"
+ . += span_notice("It's a disguised [initial(name)]!")
// returns TRUE if hidden, if unhidden FALSE
/obj/structure/clockwork/functional/proc/toggle_hide(chosen_type)
@@ -158,7 +129,7 @@
desc = "An imposing spire formed of brass. It somewhat pulsates."
icon_state = "beacon"
max_integrity = 250 // A very important one
- death_message = "The beacon crumbles and falls in parts to the ground relaesing it's power!"
+ death_message = span_danger("The beacon crumbles and falls in parts to the ground relaesing it's power!")
death_sound = 'sound/effects/creepyshriek.ogg'
var/heal_delay = 6 SECONDS
var/last_heal = 0
@@ -186,7 +157,7 @@
if(!isclocker(L))
continue
if(L.reagents?.has_reagent("holywater"))
- to_chat(L, "You feel a terrible liquid disappearing from your body.")
+ to_chat(L, span_warning("You feel a terrible liquid disappearing from your body."))
L.reagents.del_reagent("holywater")
if(iscogscarab(L))
var/mob/living/silicon/robot/cogscarab/C = L
@@ -213,7 +184,7 @@
GLOB.clockwork_beacons -= src
STOP_PROCESSING(SSobj, src)
for(var/datum/mind/M in SSticker.mode.clockwork_cult)
- to_chat(M.current, "You get the feeling that one of the beacons have been destroyed! The source comes from [areabeacon.name]")
+ to_chat(M.current, span_danger("You get the feeling that one of the beacons have been destroyed! The source comes from [areabeacon.name]"))
return ..()
/obj/structure/clockwork/functional/beacon/attackby(obj/item/I, mob/user, params)
@@ -228,7 +199,7 @@
desc = "A strange brass platform with spinning cogs inside. It demands something in exchange for goods..."
icon_state = "altar"
density = FALSE
- death_message = "The credence breaks in pieces as it dusts into nothing!"
+ death_message = span_danger("The credence breaks in pieces as it dusts into nothing!")
canbehidden = TRUE
choosable_items = list(
"potted plant" = /obj/item/twohanded/required/kirbyplants,
@@ -265,38 +236,6 @@
return ..()
-/obj/structure/clockwork/functional/altar/update_name(updates = ALL)
- . = ..()
- if(!hidden)
- name = initial(name)
- return
- switch(hidden_type)
- if("potted plant")
- name = "potted plant"
- if("chair")
- name = "chair"
- if("stool")
- name = "stool"
- if("broken grille")
- name = "grille"
-
-
-/obj/structure/clockwork/functional/altar/update_desc(updates = ALL)
- . = ..()
- if(!hidden)
- desc = initial(desc)
- return
- switch(hidden_type)
- if("potted plant")
- desc = null
- if("chair")
- desc = "You sit in this. Either by will or force."
- if("stool")
- desc = "Apply butt."
- if("broken grille")
- desc = "A flimsy framework of metal rods."
-
-
/obj/structure/clockwork/functional/altar/update_icon_state()
if(!hidden)
icon = initial(icon)
@@ -305,19 +244,11 @@
return
icon_state = first_stage ? "[initial(icon_state)]-fast" : initial(icon_state)
return
- switch(hidden_type)
- if("potted plant")
- icon = 'icons/obj/flora/plants.dmi'
- icon_state = "plant-[rand(1,36)]"
- if("chair")
- icon = 'icons/obj/chairs.dmi'
- icon_state = "chair"
- if("stool")
- icon = 'icons/obj/chairs.dmi'
- icon_state = "stool"
- if("broken grille")
- icon = 'icons/obj/structures.dmi'
- icon_state = "brokengrille"
+ icon = choosable_items[hidden_type]::icon
+ if(hidden_type == "potted plant")
+ icon_state = "plant-[rand(1,36)]"
+ else
+ icon_state = choosable_items[hidden_type]::icon_state
/obj/structure/clockwork/functional/altar/attackby(obj/item/I, mob/user, params)
@@ -408,7 +339,7 @@
/obj/structure/clockwork/functional/altar/proc/first_stage_check(var/mob/living/carbon/human/target)
first_stage = TRUE
- target.visible_message("[src] begins to glow a piercing amber!", "You feel something start to invade your mind...")
+ target.visible_message(span_warning("[src] begins to glow a piercing amber!"), span_clock("You feel something start to invade your mind..."))
glow = new (get_turf(src))
animate(glow, alpha = 255, time = 8 SECONDS)
update_icon(UPDATE_ICON_STATE)
@@ -416,11 +347,11 @@
/obj/structure/clockwork/functional/altar/proc/second_stage_check(var/mob/living/carbon/human/target)
second_stage = TRUE
if(!is_convertable_to_clocker(target.mind) || target.stat == DEAD) // mindshield or holy or mindless monkey. or dead guy
- target.visible_message("[src] in glowing manner starts corrupting [target]!", \
- "You feel as your body starts to corrupt by [src] underneath!")
+ target.visible_message(span_warning("[src] in glowing manner starts corrupting [target]!"), \
+ span_danger("You feel as your body starts to corrupt by [src] underneath!"))
target.Weaken(20 SECONDS)
else // just a living non-clocker civil
- to_chat(target, "\"You belong to me now.\"")
+ to_chat(target, span_clocklarge("\"You belong to me now.\""))
target.heal_overall_damage(50, 50)
if(isgolem(target))
target.mind.wipe_memory()
@@ -438,7 +369,7 @@
converting = null
update_icon(UPDATE_ICON_STATE)
if(!silent)
- visible_message("[src] slowly stops glowing!")
+ visible_message(span_warning("[src] slowly stops glowing!"))
/obj/structure/clockwork/functional/altar/attackby(obj/item/I, mob/user, params)
@@ -467,30 +398,30 @@
var/datum/game_mode/gamemode = SSticker.mode
if(GLOB.ark_of_the_clockwork_justiciar)
- to_chat(user, "There is already Gateway somewhere!")
+ to_chat(user, span_clockitalic("There is already Gateway somewhere!"))
return FALSE
if(gamemode.clocker_objs.clock_status < RATVAR_NEEDS_SUMMONING)
- to_chat(user, "Ratvar is not ready to be summoned yet!")
+ to_chat(user, span_clockitalic("Ratvar is not ready to be summoned yet!"))
return FALSE
if(gamemode.clocker_objs.clock_status == RATVAR_HAS_RISEN)
- to_chat(user, "\"My fellow. There is no need for it anymore.\"")
+ to_chat(user, span_clockitalic("\"My fellow. There is no need for it anymore.\""))
return FALSE
var/list/summon_areas = gamemode.clocker_objs.obj_summon.ritual_spots
if(!(A in summon_areas))
- to_chat(user, "Ratvar can only be summoned where the veil is weak - in [english_list(summon_areas)]!")
+ to_chat(user, span_cultlarge("Ratvar can only be summoned where the veil is weak - in [english_list(summon_areas)]!"))
return FALSE
var/confirm_final = tgui_alert(user, "This is the FINAL step to summon, the crew will be alerted to your presence AND your location!",
"The power comes...", list("Let Ratvar shine ones more!", "No"))
if(user)
if(confirm_final != "Let Ratvar shine ones more!")
- to_chat(user, "You decide to prepare further before pincing the shard.")
+ to_chat(user, span_clockitalic("You decide to prepare further before pincing the shard."))
return FALSE
return TRUE
/obj/structure/clockwork/functional/altar/proc/begin_the_ritual()
- visible_message("The [src] expands itself revealing into the great Ark!")
+ visible_message(span_danger("The [src] expands itself revealing into the great Ark!"))
new /obj/structure/clockwork/functional/celestial_gateway(get_turf(src))
qdel(src)
return
@@ -499,7 +430,7 @@
name = "cogscarab fabricator"
desc = "House for a tons of little cogscarabs, self-producing and maintaining itself."
icon_state = "fabricator"
- death_message = "Fabricator crumbles and dusts, leaving nothing behind!"
+ death_message = span_danger("Fabricator crumbles and dusts, leaving nothing behind!")
var/list/cogscarab_list = list()
canbehidden = TRUE
var/cog_slots = 0
@@ -508,11 +439,7 @@
/obj/structure/clockwork/functional/cogscarab_fabricator/examine(mob/user)
. = ..()
if(!hidden && (isclocker(user) || isobserver(user)))
- . += "There's [cog_slots - cogscarab_list.len] cogscarab ready. [timer_fabrictor ? "And it's creating another one now" : "It stopped creating."]."
-
-
-/obj/structure/clockwork/functional/cogscarab_fabricator/update_icon_state()
- icon_state = anchored ? "[initial(icon_state)]-off" : initial(icon_state)
+ . += span_notice("There's [cog_slots - cogscarab_list.len] cogscarab ready. [timer_fabrictor ? "And it's creating another one now" : "It stopped creating."].")
/obj/structure/clockwork/functional/cogscarab_fabricator/Initialize(mapload)
@@ -577,17 +504,17 @@
/obj/structure/clockwork/functional/cogscarab_fabricator/attack_ghost(mob/dead/observer/user)
if(hidden)
- to_chat(user, "It's hidden and cannot produce you at this state!")
+ to_chat(user, span_warning("It's hidden and cannot produce you at this state!"))
return FALSE
if(!anchored)
- to_chat(user, "It seems to be non-functional to produce a new shell!")
+ to_chat(user, span_warning("It seems to be non-functional to produce a new shell!"))
return FALSE
if(cogscarab_list.len >= cog_slots)
- to_chat(user, "There's no empty shells to take!")
+ to_chat(user, span_notice("There's no empty shells to take!"))
return FALSE
if(alert(user, "Do you wish to become cogscarab?",,"Yes","No") == "Yes")
if(cogscarab_list.len >= cog_slots) //Double check. No duplications
- to_chat(user, "There's no empty shells to take!")
+ to_chat(user, span_notice("There's no empty shells to take!"))
return FALSE
var/mob/living/silicon/robot/cogscarab/cog = new(loc)
cog.key = user.key
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index bdefc1983a3..26a3307edad 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -77,6 +77,7 @@
pre_malf_AI = traitor
pre_malf_AI.restricted_roles = (restricted_jobs|protected_jobs|protected_jobs_AI) // All jobs are restricted for malf AI despite the config.
pre_malf_AI.restricted_roles -= JOB_TITLE_AI
+ traitor.special_role = SPECIAL_ROLE_MALFAI
SSjobs.new_malf = traitor.current
else
pre_traitors += traitor
diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm
index 466ea8ab14a..7845ee9396e 100644
--- a/code/game/jobs/job/civilian.dm
+++ b/code/game/jobs/job/civilian.dm
@@ -9,8 +9,8 @@
supervisors = "the head of personnel"
department_head = list(JOB_TITLE_HOP)
selection_color = "#e6e6e6"
- access = list() //See /datum/job/assistant/get_access()
- minimal_access = list() //See /datum/job/assistant/get_access()
+ access = list(ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_MAINT_TUNNELS)
alt_titles = list("Tourist","Businessman","Trader","Assistant")
outfit = /datum/outfit/job/assistant
insurance_type = INSURANCE_TYPE_BUDGETARY
@@ -19,11 +19,6 @@
min_start_money = 10
max_start_money = 200
-/datum/job/civilian/get_access()
- if(CONFIG_GET(flag/assistant_maint))
- return list(ACCESS_MAINT_TUNNELS)
- else
- return list()
/datum/outfit/job/assistant
name = "Civilian"
diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm
index d90f74afdeb..06879c0c751 100644
--- a/code/game/jobs/job/medical.dm
+++ b/code/game/jobs/job/medical.dm
@@ -58,8 +58,8 @@
supervisors = "the chief medical officer"
department_head = list(JOB_TITLE_CMO)
selection_color = "#d1eeff"
- access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY)
+ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_MAINT_TUNNELS)
alt_titles = list("Surgeon","Nurse")
minimal_player_age = 3
exp_requirements = 600
@@ -145,8 +145,8 @@
supervisors = "the chief medical officer"
department_head = list(JOB_TITLE_CMO)
selection_color = "#d1eeff"
- access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE)
+ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS)
minimal_player_age = 3
exp_requirements = 180
exp_type = EXP_TYPE_CREW
@@ -211,8 +211,8 @@
supervisors = "the chief medical officer"
department_head = list(JOB_TITLE_CMO)
selection_color = "#d1eeff"
- access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_MEDICAL, ACCESS_CHEMISTRY, ACCESS_MINERAL_STOREROOM)
+ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_MEDICAL, ACCESS_CHEMISTRY, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS)
alt_titles = list("Pharmacist","Pharmacologist")
minimal_player_age = 7
exp_requirements = 600
@@ -250,8 +250,8 @@
supervisors = "the chief medical officer and the research director"
department_head = list(JOB_TITLE_CMO, JOB_TITLE_RD)
selection_color = "#d1eeff"
- access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_RESEARCH)
+ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_RESEARCH, ACCESS_MAINT_TUNNELS)
minimal_player_age = 3
exp_requirements = 900
exp_type = EXP_TYPE_MEDICAL
@@ -288,8 +288,8 @@
supervisors = "the chief medical officer"
department_head = list(JOB_TITLE_CMO)
selection_color = "#d1eeff"
- access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_MEDICAL, ACCESS_VIROLOGY, ACCESS_MINERAL_STOREROOM)
+ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_MEDICAL, ACCESS_VIROLOGY, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS)
alt_titles = list("Pathologist","Microbiologist")
minimal_player_age = 7
exp_requirements = 900
@@ -328,8 +328,8 @@
supervisors = "the chief medical officer"
department_head = list(JOB_TITLE_CMO)
selection_color = "#d1eeff"
- access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_PSYCHIATRIST)
- minimal_access = list(ACCESS_MEDICAL, ACCESS_PSYCHIATRIST)
+ access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_PSYCHIATRIST, ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_MEDICAL, ACCESS_PSYCHIATRIST, ACCESS_MAINT_TUNNELS)
alt_titles = list("Psychologist","Therapist")
outfit = /datum/outfit/job/psychiatrist
diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm
index a7ddd56690b..9529e98f49a 100644
--- a/code/game/jobs/job/science.dm
+++ b/code/game/jobs/job/science.dm
@@ -64,8 +64,8 @@
supervisors = "the research director"
department_head = list(JOB_TITLE_RD)
selection_color = "#e6d1f0"
- access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_XENOARCH, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_XENOARCH, ACCESS_MINERAL_STOREROOM)
+ access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_XENOARCH, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_XENOARCH, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS)
alt_titles = list("Anomalist", "Plasma Researcher", "Xenobiologist", "Chemical Researcher")
minimal_player_age = 3
exp_requirements = 600
@@ -149,8 +149,8 @@
supervisors = "the research director"
department_head = list(JOB_TITLE_RD)
selection_color = "#e6d1f0"
- access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM) //As a job that handles so many corpses, it makes sense for them to have morgue access.
- minimal_access = list(ACCESS_ROBOTICS, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM) //As a job that handles so many corpses, it makes sense for them to have morgue access.
+ access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS) //As a job that handles so many corpses, it makes sense for them to have morgue access.
+ minimal_access = list(ACCESS_ROBOTICS, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS) //As a job that handles so many corpses, it makes sense for them to have morgue access.
alt_titles = list("Biomechanical Engineer","Mechatronic Engineer")
minimal_player_age = 3
exp_requirements = 900
diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm
index 7fd0e3ec95f..d377bf1a6c0 100644
--- a/code/game/jobs/job/security.dm
+++ b/code/game/jobs/job/security.dm
@@ -71,8 +71,8 @@
supervisors = "the head of security"
department_head = list(JOB_TITLE_HOS)
selection_color = "#edcdcd"
- access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_WEAPONS)
- minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_WEAPONS)
+ access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_PILOT, ACCESS_FORENSICS_LOCKERS, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_GATEWAY, ACCESS_WEAPONS)
+ minimal_access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_ARMORY, ACCESS_PILOT, ACCESS_FORENSICS_LOCKERS, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_GATEWAY, ACCESS_WEAPONS)
alt_titles = list("Brig Sergeant")
minimal_player_age = 21
blocked_race_for_job = list(SPECIES_VOX)
diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm
index dfcd5916ab5..16a34ff3a41 100644
--- a/code/game/jobs/job/support.dm
+++ b/code/game/jobs/job/support.dm
@@ -151,8 +151,8 @@
supervisors = "the head of personnel"
department_head = list(JOB_TITLE_HOP)
selection_color = "#d1e8d3"
- access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM)
- minimal_access = list(ACCESS_BAR, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM)
+ access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_BAR, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM, ACCESS_MAINT_TUNNELS)
alt_titles = list("Barman","Barkeeper","Drink Artist")
outfit = /datum/outfit/job/bartender
@@ -193,8 +193,8 @@
supervisors = "the head of personnel"
department_head = list(JOB_TITLE_HOP)
selection_color = "#d1e8d3"
- access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE)
- minimal_access = list(ACCESS_KITCHEN)
+ access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_KITCHEN, ACCESS_MAINT_TUNNELS)
alt_titles = list("Cook","Culinary Artist","Butcher")
outfit = /datum/outfit/job/chef
@@ -245,8 +245,8 @@
supervisors = "the head of personnel"
department_head = list(JOB_TITLE_HOP)
selection_color = "#d1e8d3"
- access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE)
- minimal_access = list(ACCESS_HYDROPONICS, ACCESS_MORGUE)
+ access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_HYDROPONICS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS)
alt_titles = list("Hydroponicist", "Botanical Researcher")
exp_requirements = 300
exp_type = EXP_TYPE_CREW
@@ -284,8 +284,8 @@
supervisors = "the head of personnel"
department_head = list(JOB_TITLE_HOP)
selection_color = "#d1e8d3"
- access = list(ACCESS_CLOWN, ACCESS_THEATRE)
- minimal_access = list(ACCESS_CLOWN, ACCESS_THEATRE)
+ access = list(ACCESS_CLOWN, ACCESS_THEATRE, ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_CLOWN, ACCESS_THEATRE, ACCESS_MAINT_TUNNELS)
alt_titles = list("Performance Artist","Comedian","Jester")
outfit = /datum/outfit/job/clown
@@ -502,8 +502,8 @@
supervisors = "the head of personnel"
department_head = list(JOB_TITLE_HOP)
selection_color = "#d1e8d3"
- access = list(ACCESS_MIME, ACCESS_THEATRE)
- minimal_access = list(ACCESS_MIME, ACCESS_THEATRE)
+ access = list(ACCESS_MIME, ACCESS_THEATRE, ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_MIME, ACCESS_THEATRE, ACCESS_MAINT_TUNNELS)
alt_titles = list("Panthomimist")
outfit = /datum/outfit/job/mime
@@ -590,8 +590,8 @@
supervisors = "the head of personnel"
department_head = list(JOB_TITLE_HOP)
selection_color = "#d1e8d3"
- access = list(ACCESS_LIBRARY)
- minimal_access = list(ACCESS_LIBRARY)
+ access = list(ACCESS_LIBRARY, ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_LIBRARY, ACCESS_MAINT_TUNNELS)
alt_titles = list("Journalist")
outfit = /datum/outfit/job/librarian
@@ -624,8 +624,8 @@
department_head = list(JOB_TITLE_HOP)
selection_color = "#d1e8d3"
alt_titles = list("Hair Stylist","Beautician")
- access = list()
- minimal_access = list()
+ access = list(ACCESS_MAINT_TUNNELS)
+ minimal_access = list(ACCESS_MAINT_TUNNELS)
outfit = /datum/outfit/job/barber
salary = 100
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index 9b19f66a85f..f1bd6736acd 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -95,9 +95,11 @@
if(wood.get_amount() < 5)
to_chat(user, span_warning("You need at least five wooden planks to make a wall!"))
return ATTACK_CHAIN_PROCEED
+
to_chat(user, span_notice("You start adding [I] to [src]..."))
- if(do_after(user, 5 SECONDS, src) || QDELETED(wood) || !wood.use(5) || !isturf(loc))
+ if(!do_after(user, 5 SECONDS, src) || QDELETED(wood) || !wood.use(5) || !isturf(loc))
return ATTACK_CHAIN_PROCEED
+
var/turf/our_turf = loc
our_turf.ChangeTurf(/turf/simulated/wall/mineral/wood/nonmetal)
qdel(src)
diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index e0efa1afea8..a14a6de580d 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -1037,6 +1037,7 @@ GLOBAL_LIST_EMPTY(turret_icons)
use_power = NO_POWER_USE
has_cover = FALSE
raised = TRUE
+ density = TRUE
scan_range = 9
faction = "syndicate"
@@ -1060,6 +1061,8 @@ GLOBAL_LIST_EMPTY(turret_icons)
if(istype(depotarea))
depotarea.turret_died()
+ density = FALSE
+
/obj/machinery/porta_turret/syndicate/shootAt(mob/living/target)
if(istype(depotarea))
depotarea.list_add(target, depotarea.hostile_list)
diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm
index e5d81dc2777..e430616467b 100644
--- a/code/game/machinery/vending.dm
+++ b/code/game/machinery/vending.dm
@@ -1825,10 +1825,10 @@
req_access = list(ACCESS_SECURITY)
products = list(/obj/item/restraints/handcuffs = 8,/obj/item/restraints/handcuffs/cable/zipties = 8,/obj/item/grenade/flashbang = 4,/obj/item/flash = 5,
/obj/item/reagent_containers/food/snacks/donut = 12,/obj/item/storage/box/evidence = 6,/obj/item/flashlight/seclite = 4,/obj/item/restraints/legcuffs/bola/energy = 7,
- /obj/item/clothing/mask/muzzle/safety = 4, /obj/item/storage/box/swabs = 6, /obj/item/storage/box/fingerprints = 6, /obj/item/eftpos/sec = 4, /obj/item/storage/belt/security/webbing = 2, /obj/item/grenade/smokebomb = 8,
+ /obj/item/clothing/mask/muzzle/safety = 4, /obj/item/storage/box/swabs = 6, /obj/item/storage/box/fingerprints = 6, /obj/item/eftpos/sec = 4, /obj/item/storage/belt/security/webbing = 2, /obj/item/flashlight/sectaclight = 2, /obj/item/grenade/smokebomb = 8,
)
contraband = list(/obj/item/clothing/glasses/sunglasses = 2,/obj/item/storage/fancy/donut_box = 2,/obj/item/hailer = 5)
- prices = list(/obj/item/storage/belt/security/webbing = 2000,/obj/item/grenade/smokebomb = 250)
+ prices = list(/obj/item/storage/belt/security/webbing = 2000, /obj/item/flashlight/sectaclight = 300, /obj/item/grenade/smokebomb = 250)
refill_canister = /obj/item/vending_refill/security
/obj/machinery/vending/security/training
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 5df30b280e3..caa2e3e215a 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -132,6 +132,13 @@
light_range = 5 // A little better than the standard flashlight.
hitsound = 'sound/weapons/genhit1.ogg'
+/obj/item/flashlight/sectaclight
+ name = "security tactical flashlight"
+ desc = "Прочный тактический фонарь, оборудованный для комфортного ношения на голове. Используется представителями службы безопасности."
+ icon_state = "sectaclight"
+ item_state = ""
+ slot_flags = ITEM_SLOT_EARS
+
/obj/item/flashlight/drone
name = "low-power flashlight"
desc = "A miniature lamp, that might be used by small robots."
diff --git a/code/game/objects/items/weapons/storage/backpack.dm b/code/game/objects/items/weapons/storage/backpack.dm
index a248a8cad79..9085b6dbe40 100644
--- a/code/game/objects/items/weapons/storage/backpack.dm
+++ b/code/game/objects/items/weapons/storage/backpack.dm
@@ -264,6 +264,48 @@
icon_state = "blueshieldpack"
item_state = "blueshieldpack"
+/obj/item/storage/backpack/justice
+ name = "backpack of justice"
+ desc = "Крепкий рюкзак выданный специально для самых крепких офицеров."
+ icon_state = "backpack_justice0"
+ item_state = "backpack_justice0"
+ actions_types = list(/datum/action/item_action/toggle_backpack_light)
+ var/on = FALSE
+ var/datum/looping_sound/ambulance_alarm/justice/soundloop
+
+/obj/item/storage/backpack/justice/attack_self()
+ toggle_backpack_light()
+
+/obj/item/storage/backpack/justice/Initialize(mapload)
+ . = ..()
+ soundloop = new(list(src))
+
+/obj/item/storage/backpack/justice/Destroy(force)
+ QDEL_NULL(soundloop)
+ return ..()
+
+/obj/item/storage/backpack/justice/proc/toggle_backpack_light()
+ on = !on
+
+ if(on)
+ turn_on()
+ else
+ turn_off()
+
+ update_icon(UPDATE_ICON_STATE)
+
+/obj/item/storage/backpack/justice/update_icon_state()
+ icon_state = "backpack_justice[on]"
+ item_state = "backpack_justice[on]"
+ update_equipped_item(update_speedmods = FALSE)
+
+/obj/item/storage/backpack/justice/proc/turn_on()
+ soundloop.start()
+
+/obj/item/storage/backpack/justice/proc/turn_off()
+ soundloop.stop()
+
+
/*
* Syndicate backpacks. Sprites by ElGood
*/
diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm
index 9c6eb1c2b7b..85a4c2e9fa4 100644
--- a/code/game/objects/items/weapons/twohanded.dm
+++ b/code/game/objects/items/weapons/twohanded.dm
@@ -664,37 +664,49 @@
icon_state = "mjollnir[HAS_TRAIT(src, TRAIT_WIELDED)]"
-/obj/item/twohanded/singularityhammer/proc/vortex(turf/pull, mob/wielder)
- for(var/atom/movable/X in orange(5, pull))
- if(X == wielder)
- continue
- if((X) && (!X.anchored) && (!ishuman(X)))
- step_towards(X, pull)
- step_towards(X, pull)
- step_towards(X, pull)
- else if(ishuman(X))
- var/mob/living/carbon/human/H = X
- if(istype(H.shoes, /obj/item/clothing/shoes/magboots))
- var/obj/item/clothing/shoes/magboots/M = H.shoes
- if(M.magpulse)
- continue
- H.Weaken(2 SECONDS)
- step_towards(H, pull)
- step_towards(H, pull)
- step_towards(H, pull)
-
/obj/item/twohanded/singularityhammer/afterattack(atom/A, mob/user, proximity, params)
- if(!proximity)
+ if(!proximity || charged < 5 || !HAS_TRAIT(src, TRAIT_WIELDED))
return
- if(HAS_TRAIT(src, TRAIT_WIELDED))
- if(charged == 5)
- charged = 0
- if(isliving(A))
- var/mob/living/Z = A
- Z.take_organ_damage(20, 0)
- playsound(user, 'sound/weapons/marauder.ogg', 50, 1)
- var/turf/target = get_turf(A)
- vortex(target, user)
+
+ charged = 0
+ var/turf/target = get_turf(A)
+ playsound(target, 'sound/weapons/marauder.ogg', 50, TRUE)
+
+ if(isliving(A))
+ var/mob/living/victim = A
+ victim.take_organ_damage(20)
+
+ for(var/atom/pulled_thing as anything in (orange(5, target) - user))
+ pulled_thing.singularity_hammer_act(target)
+
+
+/atom/proc/singularity_hammer_act(turf/pull)
+ return
+
+
+/atom/movable/singularity_hammer_act(turf/pull)
+ if(anchored)
+ return
+
+ unbuckle_all_mobs()
+
+ for(var/a in 1 to 3)
+ if(!step_towards(src, pull))
+ return
+
+
+/mob/dead/observer/singularity_hammer_act(turf/pull)
+ return
+
+
+/mob/living/singularity_hammer_act(turf/pull)
+ if(HAS_TRAIT(src, TRAIT_NEGATES_GRAVITY))
+ return
+
+ buckled?.unbuckle_mob(src)
+ Weaken(2 SECONDS)
+ ..()
+
/obj/item/twohanded/mjollnir
name = "Mjolnir"
diff --git a/code/modules/antagonists/malf_ai/malf_ai_datum.dm b/code/modules/antagonists/malf_ai/malf_ai_datum.dm
index 80e25b3bd84..f16ed32201f 100644
--- a/code/modules/antagonists/malf_ai/malf_ai_datum.dm
+++ b/code/modules/antagonists/malf_ai/malf_ai_datum.dm
@@ -2,7 +2,7 @@
name = "Malfunctioning AI"
roundend_category = "traitors"
job_rank = ROLE_MALF_AI
- special_role = SPECIAL_ROLE_TRAITOR
+ special_role = SPECIAL_ROLE_MALFAI
antag_hud_name = "hudsyndicate"
antag_hud_type = ANTAG_HUD_TRAITOR
/// Should the AI get codewords?
diff --git a/code/modules/antagonists/vampire/vampire_datum.dm b/code/modules/antagonists/vampire/vampire_datum.dm
index c1dbb7ef48c..dc45020172a 100644
--- a/code/modules/antagonists/vampire/vampire_datum.dm
+++ b/code/modules/antagonists/vampire/vampire_datum.dm
@@ -198,12 +198,13 @@
/datum/antagonist/vampire/proc/handle_bloodsucking(mob/living/carbon/human/target, suck_rate_override)
draining = target
+ var/mob/living/carbon/human/cur = owner.current
var/unique_suck_id = target.UID()
var/blood = 0
var/blood_volume_warning = 9999 //Blood volume threshold for warnings
var/cycle_counter = 0
var/time_per_action
- var/vampire_dir = get_dir(owner.current, target)
+ var/vampire_dir = get_dir(cur, target)
var/old_bloodusable = 0 //used to see if we increased our blood usable
@@ -213,20 +214,20 @@
else
suck_rate_final = suck_rate
- if(owner.current.is_muzzled())
- to_chat(owner.current, span_warning("[owner.current.wear_mask] мешает вам укусить [target]!"))
+ if(cur.is_muzzled())
+ to_chat(cur, span_warning("[cur.wear_mask] мешает вам укусить [target]!"))
draining = null
return
- add_attack_logs(owner.current, target, "vampirebit & is draining their blood.", ATKLOG_ALMOSTALL)
+ add_attack_logs(cur, target, "vampirebit & is draining their blood.", ATKLOG_ALMOSTALL)
- if(!iscarbon(owner.current))
+ if(!iscarbon(cur))
target.LAssailant = null
else
- target.LAssailant = owner.current
+ target.LAssailant = cur
var/is_target_grabbed = FALSE
- if(target.pulledby == owner.current && owner.current.grab_state > GRAB_PASSIVE)
+ if(target.pulledby == cur && cur.grab_state > GRAB_PASSIVE)
is_target_grabbed = TRUE
if(!is_target_grabbed || vampire_dir == NORTHEAST || vampire_dir == NORTHWEST || \
@@ -238,25 +239,27 @@
cycle_counter = STATE_GRABBING
time_per_action = suck_rate_final*BITE_TIME_MOD
- while(do_after(owner.current, time_per_action, target, NONE, interaction_key = DOAFTER_SOURCE_VAMPIRE_SUCKING, max_interact_count = 1))
+ while(do_after(cur, time_per_action, target, NONE, interaction_key = DOAFTER_SOURCE_VAMPIRE_SUCKING, max_interact_count = 1))
cycle_counter++
- owner.current.face_atom(target)
+ cur.face_atom(target)
old_bloodusable = bloodusable
switch(cycle_counter)
if(STATE_CLOSING_IN)
- owner.current.visible_message(span_danger("[owner.current] приближается к [target]"), \
+ cur.visible_message(span_danger("[cur] приближается к [target]"), \
span_danger("Вы приближаетесь к [target]"))
getting_closer_animation(target, STATE_CLOSING_IN, vampire_dir)
time_per_action = suck_rate_final*GRABBING_TIME_MOD
continue
+
if(STATE_GRABBING)
- owner.current.visible_message(span_danger("[owner.current] грубо хватает шею [target]"), \
+ cur.visible_message(span_danger("[cur] грубо хватает шею [target]"), \
span_danger("Вы грубо хватает шею [target]"))
getting_closer_animation(target, STATE_GRABBING, vampire_dir)
time_per_action = suck_rate_final*BITE_TIME_MOD
continue
+
if(STATE_BITE)
- owner.current.visible_message(span_danger("[owner.current] вонзает [genderize_ru(owner.current.gender, "его", "её", "его", "их")] клыки!"), \
+ cur.visible_message(span_danger("[cur] вонзает [genderize_ru(cur.gender, "его", "её", "его", "их")] клыки!"), \
span_danger("Вы вонзаете клыки в шею [target] и начинаете высасывать [genderize_ru(target.gender, "его", "её", "его", "их")] кровь."), \
span_italics("Вы слышите тихий звук прокола и влажные хлюпающие звуки."))
bite_animation(target, vampire_dir)
@@ -265,9 +268,9 @@
if(unique_suck_id in drained_humans)
if(drained_humans[unique_suck_id] >= BLOOD_DRAIN_LIMIT)
- to_chat(owner.current, span_warning("Вы поглотили всю жизненную эссенцию [target], дальнейшее питьё крови будет только утолять голод!"))
+ to_chat(cur, span_warning("Вы поглотили всю жизненную эссенцию [target], дальнейшее питьё крови будет только утолять голод!"))
target.setBlood(max(target.blood_volume - 25, 0))
- owner.current.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, owner.current.nutrition + 5))
+ cur.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, cur.nutrition + 5))
continue
@@ -275,29 +278,47 @@
if(target.ckey || target.player_ghosted) //Requires ckey regardless if monkey or humanoid, or the body has been ghosted before it died
blood = min(20, target.blood_volume)
adjust_blood(target, blood * BLOOD_GAINED_MODIFIER)
- to_chat(owner.current, span_boldnotice("Вы накопили [bloodtotal] единиц[declension_ru(bloodtotal, "у", "ы", "")] крови[bloodusable != old_bloodusable ? ", и теперь вам доступно [bloodusable] единиц[declension_ru(bloodusable, "а", "ы", "")] крови" : ""]."))
+ cur.adjustBruteLoss(-3)
+ cur.adjustFireLoss(-3)
+ cur.adjustOxyLoss(-10)
+ cur.adjustToxLoss(-2)
+ cur.adjustBrainLoss(-1)
+ for(var/obj/item/organ/external/bodypart as anything in cur.bodyparts)
+ if(bodypart.has_fracture() && prob(5))
+ to_chat(cur, span_notice("You feel a burning sensation in your [bodypart.name] as it straightens involuntarily!"))
+ bodypart.mend_fracture()
+
+ if(bodypart.has_internal_bleeding() && prob(5))
+ to_chat(cur, span_notice("You feel a burning sensation in your [bodypart.name] as your veins begin to recover!"))
+ bodypart.stop_internal_bleeding()
+
+ if(bloodtotal >= REQ_BLOOD_FOR_SUBCLASS_ACT)
+ subclass?.on_blood_sucking(owner)
+
+ to_chat(cur, span_boldnotice("Вы накопили [bloodtotal] единиц[declension_ru(bloodtotal, "у", "ы", "")] крови[bloodusable != old_bloodusable ? ", и теперь вам доступно [bloodusable] единиц[declension_ru(bloodusable, "а", "ы", "")] крови" : ""]."))
target.setBlood(max(target.blood_volume - 25, 0))
//Blood level warnings (Code 'borrowed' from Fulp)
if(target.blood_volume)
if(target.blood_volume <= BLOOD_VOLUME_BAD && blood_volume_warning > BLOOD_VOLUME_BAD)
- to_chat(owner.current, span_danger("У вашей жертвы остаётся опасно мало крови!"))
+ to_chat(cur, span_danger("У вашей жертвы остаётся опасно мало крови!"))
else if(target.blood_volume <= BLOOD_VOLUME_OKAY && blood_volume_warning > BLOOD_VOLUME_OKAY)
- to_chat(owner.current, span_warning("У вашей жертвы остаётся тревожно мало крови!"))
+ to_chat(cur, span_warning("У вашей жертвы остаётся тревожно мало крови!"))
+
blood_volume_warning = target.blood_volume //Set to blood volume, so that you only get the message once
else
- to_chat(owner.current, span_warning("Вы выпили свою жертву досуха!"))
+ to_chat(cur, span_warning("Вы выпили свою жертву досуха!"))
break
if(!target.ckey && !target.player_ghosted)//Only runs if there is no ckey and the body has not being ghosted while alive
- to_chat(owner.current, span_boldnotice("Питьё крови у [target] насыщает вас, но доступной крови от этого вы не получаете."))
- owner.current.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, owner.current.nutrition + 5))
+ to_chat(cur, span_boldnotice("Питьё крови у [target] насыщает вас, но доступной крови от этого вы не получаете."))
+ cur.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, cur.nutrition + 5))
else
- owner.current.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, owner.current.nutrition + (blood / 2)))
+ cur.set_nutrition(min(NUTRITION_LEVEL_WELL_FED, cur.nutrition + (blood / 2)))
stop_sucking()
diff --git a/code/modules/antagonists/vampire/vampire_subclasses.dm b/code/modules/antagonists/vampire/vampire_subclasses.dm
index a3af73d3147..0884168f95c 100644
--- a/code/modules/antagonists/vampire/vampire_subclasses.dm
+++ b/code/modules/antagonists/vampire/vampire_subclasses.dm
@@ -28,6 +28,9 @@
)
+/datum/vampire_subclass/proc/on_blood_sucking(mob/living/carbon/human/H)
+ return
+
/datum/vampire_subclass/proc/add_subclass_ability(datum/antagonist/vampire/vamp)
for(var/thing in standard_powers)
if(vamp.bloodtotal >= standard_powers[thing])
@@ -51,6 +54,14 @@
/obj/effect/proc_holder/spell/vampire/self/eternal_darkness,
/datum/vampire_passive/xray)
+/datum/vampire_subclass/umbrae/on_blood_sucking(mob/living/carbon/human/H)
+ var/list/lights = list()
+ for(var/obj/machinery/light/L in GLOB.machines)
+ if(L.status && L.z == H.z)
+ lights += L
+
+ var/obj/machinery/light/L = pick(lights)
+ L.break_light_tube()
/datum/vampire_subclass/hemomancer
name = "hemomancer"
@@ -63,6 +74,8 @@
fully_powered_abilities = list(/datum/vampire_passive/full,
/obj/effect/proc_holder/spell/vampire/self/blood_spill)
+/datum/vampire_subclass/hemomancer/on_blood_sucking(mob/living/carbon/human/H)
+ H.blood_volume = min(H.blood_volume + 5, BLOOD_VOLUME_NORMAL)
/datum/vampire_subclass/gargantua
name = "gargantua"
@@ -76,6 +89,9 @@
/obj/effect/proc_holder/spell/vampire/charge)
improved_rejuv_healing = TRUE
+/datum/vampire_subclass/gargantua/on_blood_sucking(mob/living/carbon/human/H)
+ H.adjustBruteLoss(-2)
+ H.adjustFireLoss(-2)
/datum/vampire_subclass/dantalion
name = "dantalion"
@@ -92,6 +108,11 @@
/obj/effect/proc_holder/spell/vampire/hysteria,
/datum/vampire_passive/increment_thrall_cap/three)
+/datum/vampire_subclass/dantalion/on_blood_sucking(mob/living/carbon/human/H)
+ for(var/datum/mind/thrall in H?.mind?.som?.serv)
+ thrall.current?.adjustBruteLoss(-3)
+ thrall.current?.adjustFireLoss(-3)
+ thrall.current?.adjustOxyLoss(-5)
/datum/vampire_subclass/bestia
name = "bestia"
@@ -110,6 +131,9 @@
/datum/vampire_passive/dissection_cap/two)
improved_rejuv_healing = TRUE
+/datum/vampire_subclass/bestia/on_blood_sucking(mob/living/carbon/human/H)
+ H.adjustBruteLoss(-2)
+ H.adjustFireLoss(-2)
/datum/vampire_subclass/ancient
name = "ancient"
diff --git a/code/modules/client/preference/loadout/loadout_donor.dm b/code/modules/client/preference/loadout/loadout_donor.dm
index b21fb3aa18b..699d651fe52 100644
--- a/code/modules/client/preference/loadout/loadout_donor.dm
+++ b/code/modules/client/preference/loadout/loadout_donor.dm
@@ -428,4 +428,9 @@
display_name = "GSBussy doll"
path = /obj/item/toy/plushie/gsbplushie
-
+/datum/gear/donor/backpack_shitsec
+ donator_tier = 3
+ cost = 1
+ display_name = "backpack of justice"
+ path = /obj/item/storage/backpack/justice
+ allowed_roles = list(JOB_TITLE_HOS, JOB_TITLE_WARDEN, JOB_TITLE_OFFICER, JOB_TITLE_PILOT)
diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm
index ad4bfba80bc..7a371b75989 100644
--- a/code/modules/client/preference/preferences.dm
+++ b/code/modules/client/preference/preferences.dm
@@ -1761,7 +1761,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
b_type = new_b_type
if("hair")
- if(species in list(SPECIES_HUMAN, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_SKRELL, SPECIES_MACNINEPERSON, SPECIES_VULPKANIN, SPECIES_VOX)) //Species that have hair. (No HAS_HAIR flag)
+ if(species in list(SPECIES_HUMAN, SPECIES_UNATHI, SPECIES_TAJARAN, SPECIES_SKRELL, SPECIES_MACNINEPERSON, SPECIES_VULPKANIN, SPECIES_VOX, SPECIES_WRYN)) //Species that have hair. (No HAS_HAIR flag)
var/input = "Choose your character's hair colour:"
var/new_hair = input(user, input, "Character Preference", h_colour) as color|null
if(new_hair)
diff --git a/code/modules/clothing/chameleon/generic_chameleon_clothing.dm b/code/modules/clothing/chameleon/generic_chameleon_clothing.dm
index 135b23f2eb5..d30e5ea5321 100644
--- a/code/modules/clothing/chameleon/generic_chameleon_clothing.dm
+++ b/code/modules/clothing/chameleon/generic_chameleon_clothing.dm
@@ -220,6 +220,7 @@ do { \
SPECIES_WOLPIN = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_NEARA = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi',
+ SPECIES_WRYN = 'icons/mob/clothing/species/wryn/mask.dmi'
)
var/obj/item/voice_changer/voice_changer
diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm
index 251bebffc06..2b9de438487 100644
--- a/code/modules/clothing/masks/boxing.dm
+++ b/code/modules/clothing/masks/boxing.dm
@@ -24,7 +24,8 @@
SPECIES_FARWA = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_WOLPIN = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_NEARA = 'icons/mob/clothing/species/monkey/mask.dmi',
- SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi'
+ SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi',
+ SPECIES_WRYN = 'icons/mob/clothing/species/wryn/mask.dmi'
)
@@ -54,7 +55,8 @@
SPECIES_FARWA = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_WOLPIN = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_NEARA = 'icons/mob/clothing/species/monkey/mask.dmi',
- SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi'
+ SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi',
+ SPECIES_WRYN = 'icons/mob/clothing/species/wryn/mask.dmi'
)
/obj/item/clothing/mask/luchador/tecnicos
diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm
index 60740bcd960..7b7cf4c8306 100644
--- a/code/modules/clothing/masks/breath.dm
+++ b/code/modules/clothing/masks/breath.dm
@@ -27,7 +27,8 @@
SPECIES_FARWA = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_WOLPIN = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_NEARA = 'icons/mob/clothing/species/monkey/mask.dmi',
- SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi'
+ SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi',
+ SPECIES_WRYN = 'icons/mob/clothing/species/wryn/mask.dmi'
)
/obj/item/clothing/mask/breath/attack_self(mob/user)
diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm
index 0e729aa7815..b1dcdf8c4fd 100644
--- a/code/modules/clothing/masks/gasmask.dm
+++ b/code/modules/clothing/masks/gasmask.dm
@@ -26,7 +26,8 @@
SPECIES_FARWA = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_WOLPIN = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_NEARA = 'icons/mob/clothing/species/monkey/mask.dmi',
- SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi'
+ SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi',
+ SPECIES_WRYN = 'icons/mob/clothing/species/wryn/mask.dmi'
)
// **** Welding gas mask ****
@@ -79,7 +80,8 @@
SPECIES_FARWA = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_WOLPIN = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_NEARA = 'icons/mob/clothing/species/monkey/mask.dmi',
- SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi'
+ SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi',
+ SPECIES_WRYN = 'icons/mob/clothing/species/wryn/mask.dmi'
)
@@ -187,7 +189,8 @@
icon_state = "rainbow"
item_state = "rainbow"
sprite_sheets = list(
- SPECIES_VULPKANIN = 'icons/mob/clothing/species/vulpkanin/head.dmi'
+ SPECIES_VULPKANIN = 'icons/mob/clothing/species/vulpkanin/head.dmi',
+ SPECIES_WRYN = 'icons/mob/clothing/species/wryn/mask.dmi'
)
/obj/item/clothing/mask/gas/clownwiz
diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm
index 62aa93110ad..809fb5ff783 100644
--- a/code/modules/clothing/masks/miscellaneous.dm
+++ b/code/modules/clothing/masks/miscellaneous.dm
@@ -19,7 +19,8 @@
SPECIES_FARWA = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_WOLPIN = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_NEARA = 'icons/mob/clothing/species/monkey/mask.dmi',
- SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi'
+ SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi',
+ SPECIES_WRYN = 'icons/mob/clothing/species/wryn/mask.dmi'
)
// Clumsy folks can't take the mask off themselves.
@@ -249,7 +250,8 @@
SPECIES_FARWA = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_WOLPIN = 'icons/mob/clothing/species/monkey/mask.dmi',
SPECIES_NEARA = 'icons/mob/clothing/species/monkey/mask.dmi',
- SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi'
+ SPECIES_STOK = 'icons/mob/clothing/species/monkey/mask.dmi',
+ SPECIES_WRYN = 'icons/mob/clothing/species/wryn/mask.dmi'
)
@@ -474,7 +476,8 @@
icon_state = "pennywise_mask"
item_state = "pennywise_mask"
sprite_sheets = list(
- SPECIES_VULPKANIN = 'icons/mob/clothing/species/vulpkanin/head.dmi'
+ SPECIES_VULPKANIN = 'icons/mob/clothing/species/vulpkanin/head.dmi',
+ SPECIES_WRYN = 'icons/mob/clothing/species/wryn/mask.dmi'
)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index 42713971a0a..075c44d9ffd 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -58,7 +58,8 @@
SPECIAL_ROLE_TRAITOR,
SPECIAL_ROLE_VAMPIRE,
SPECIAL_ROLE_VAMPIRE_THRALL,
- SPECIAL_ROLE_THIEF
+ SPECIAL_ROLE_THIEF,
+ SPECIAL_ROLE_MALFAI
)
if(special_role in crew_roles)
return 0
diff --git a/code/modules/projectiles/ammunition/boxes.dm b/code/modules/projectiles/ammunition/boxes.dm
index ad228160606..c013870a107 100644
--- a/code/modules/projectiles/ammunition/boxes.dm
+++ b/code/modules/projectiles/ammunition/boxes.dm
@@ -153,7 +153,7 @@
icon_state = "10mmbox"
origin_tech = "combat=2"
ammo_type = /obj/item/ammo_casing/c10mm
- max_ammo = 20
+ max_ammo = 30
/obj/item/ammo_box/fortynr
name = "ammo box 40N&R"
diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm
index f3e556d0bfc..cc2c646014a 100644
--- a/code/modules/recycling/disposal.dm
+++ b/code/modules/recycling/disposal.dm
@@ -50,6 +50,7 @@
/obj/machinery/disposal/Initialize(mapload, obj/structure/disposalconstruct/made_from)
// this will get a copy of the air turf and take a SEND PRESSURE amount of air from it
. = ..()
+ air_contents = new
if(made_from)
setDir(made_from.dir)
return INITIALIZE_HINT_LATELOAD
@@ -60,7 +61,6 @@
var/datum/gas_mixture/env = new
env.copy_from(loc.return_air())
var/datum/gas_mixture/removed = env.remove(SEND_PRESSURE + 1)
- air_contents = new
air_contents.merge(removed)
trunk_check()
update()
diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm
index 38cdb253772..ee47d5e60bd 100644
--- a/code/modules/research/designs/autolathe_designs.dm
+++ b/code/modules/research/designs/autolathe_designs.dm
@@ -941,7 +941,7 @@
name = "Ammo Box (10mm)"
id = "c10mm"
build_type = AUTOLATHE
- materials = list(MAT_METAL = 30500)
+ materials = list(MAT_METAL = 45750)
build_path = /obj/item/ammo_box/c10mm
category = list("hacked", "Security")
diff --git a/config/example/config.txt b/config/example/config.txt
index e40ed4fc4a9..3c2fab540af 100644
--- a/config/example/config.txt
+++ b/config/example/config.txt
@@ -388,9 +388,6 @@ SOCKET_TALK 0
## How long the delay is before the Away Mission gate opens. Default is half an hour.
GATEWAY_DELAY 6000
-## Remove the # to give assistants maint access.
-ASSISTANT_MAINT
-
## Remove the # to enable assistant limiting.
ASSISTANT_LIMIT
@@ -473,18 +470,6 @@ PLAYER_REROUTE_CAP 0
## Server to reroute to
#TUTORIAL_SERVER_URL byond://example.org:1111
-## Disable the loading of away missions
-#DISABLE_AWAY_MISSIONS
-
-## Disable the loading of space ruins
-#DISABLE_SPACE_RUINS
-
-## Minimum number of space ruins levels to generate
-EXTRA_SPACE_RUIN_LEVELS_MIN 4
-
-## Maximum number of space ruins levels to generate
-EXTRA_SPACE_RUIN_LEVELS_MAX 8
-
## Uncomment to disable the OOC/LOOC channel by default.
#DISABLE_OOC
@@ -648,7 +633,6 @@ TOPIC_FILTERING_WHITELIST 127.0.0.1
# Number of players required for automatic gamemode change to extended. Doesn't work if set to zero or commented
#AUTO_EXTENDED_PLAYERS_NUM 10
-
## CPU Affinity for FFmpeg. Check out taskset man page.
## Example valid values: "0-3" or "1,4-7"
#FFMPEG_CPUAFFINITY 0-3
@@ -666,21 +650,9 @@ MAP_ROTATE none
## notriples - current map can't be selected as next if played twice in a row
MAP_VOTE_MODE all
-## Default server map
-DEFAULT_MAP /datum/map/cyberiad
-
-## Override server map by specified, uncomment to apply
-# OVERRIDE_MAP /datum/map/delta
-
## Enable animations on item pickup and drop down
# ITEM_ANIMATIONS_ENABLED
-## Disable the loading of "Taipan"
-# DISABLE_TAIPAN
-
-## Disable the loading of Lavaland
-# DISABLE_LAVALAND
-
## If the number of players is more or same than this, then we apply the highpop jobs config.
JOBS_HIGH_POP_MODE_AMOUNT 80
@@ -733,3 +705,38 @@ CACHE_ASSETS 0
## Enable the replay demo recording subsystem
#DEMOS_ENABLED
+
+### INITIALIZATION SETTINGS ###
+## This section contains settings directly affecting initializing progress. Uncomment these to make your world load faster.
+
+## Loads only space without anything in station sector. Still makes landmarks for spawnpoints, though.
+#LOAD_NO_STATION
+
+## Enables loading titlescreen only after master has been loaded. Recommended to be used on local server for faster loading.
+#ENABLE_TITLESCREEN_LATELOAD
+
+## Disable the loading of "Taipan"
+#DISABLE_TAIPAN
+
+## Disable the loading of Lavaland
+#DISABLE_LAVALAND
+
+## Disable the loading of away missions
+#DISABLE_AWAY_MISSIONS
+
+## Disable the loading of space ruins
+#DISABLE_SPACE_RUINS
+
+## Default server map
+DEFAULT_MAP /datum/map/cyberiad
+
+## Override server map by specified, uncomment to apply
+# OVERRIDE_MAP /datum/map/delta
+
+## Minimum number of space ruins levels to generate
+EXTRA_SPACE_RUIN_LEVELS_MIN 4
+
+## Maximum number of space ruins levels to generate
+EXTRA_SPACE_RUIN_LEVELS_MAX 8
+
+### INITIALIZATION SETTINGS END ###
diff --git a/html/changelogs/archive/2024-11.yml b/html/changelogs/archive/2024-11.yml
index 399b2d34c37..f51cc549c9e 100644
--- a/html/changelogs/archive/2024-11.yml
+++ b/html/changelogs/archive/2024-11.yml
@@ -66,6 +66,7 @@
'2024-11-06':
Antoonij:
- bugfix: ash walker rituals fix (#6138)
+ - bugfix: some rituals fix (#6140)
LiquidPotroh:
- bugfix: Xeno cant evolve to queen (#6136)
PlayerUnknown14:
@@ -73,5 +74,32 @@
- bugfix: RD doll now works properly (#6106)
Vladisvell:
- bugfix: Fixed headphones not unable to play songs (#6139)
+ - bugfix: Wooden wall creation fix (#6141)
+ - bugfix: Syndicate turrets are now dense (#6142)
userbaza:
- add: cloth footwraps now paintable, craftable and edible (#6042)
+'2024-11-07':
+ Anorak2020:
+ - add: vampire sucking effects (#6029)
+ KefirTT:
+ - bugfix: singularity hammer no longer pulling ghosts (#6143)
+'2024-11-09':
+ Vitalya:
+ - bugfix: Wryn hair color change (#6152)
+ Vladisvell:
+ - bugfix: Removes density on syndicate turret upon destruction (#6146)
+ - add: Titlescreen optimization for dreamseeker debug mode (#6148)
+ - bugfix: Setups Malfunctioning AI as a special role to prevent double antaging
+ (#6151)
+'2024-11-11':
+ Den109G:
+ - bugfix: Now clock-structure can disguise (#6156)
+ Mahimka42:
+ - add: New robust security backpack (#6135)
+ - tweak: 30 bullets instead 20 in 10mm ammo box. (#6163)
+ PlayerUnknown14:
+ - add: warden got more access (#6157)
+ - add: Security tactical flashlight (#5948)
+ - balance: maintenance tunnels access for everyone (#6158)
+ Vitalya:
+ - imageadd: New sprites for some Wryn masks (#6144)
diff --git a/icons/mob/clothing/back.dmi b/icons/mob/clothing/back.dmi
index af13248a790..90f04c72f47 100644
Binary files a/icons/mob/clothing/back.dmi and b/icons/mob/clothing/back.dmi differ
diff --git a/icons/mob/clothing/ears.dmi b/icons/mob/clothing/ears.dmi
index 3e55861f85f..9ca38ef1ffc 100644
Binary files a/icons/mob/clothing/ears.dmi and b/icons/mob/clothing/ears.dmi differ
diff --git a/icons/mob/clothing/species/grey/back.dmi b/icons/mob/clothing/species/grey/back.dmi
index 1ad5b9b9dcd..d20e8ac2174 100644
Binary files a/icons/mob/clothing/species/grey/back.dmi and b/icons/mob/clothing/species/grey/back.dmi differ
diff --git a/icons/mob/clothing/species/monkey/ears.dmi b/icons/mob/clothing/species/monkey/ears.dmi
index b55a433dfb3..fe201b6c978 100644
Binary files a/icons/mob/clothing/species/monkey/ears.dmi and b/icons/mob/clothing/species/monkey/ears.dmi differ
diff --git a/icons/mob/clothing/species/vox/back.dmi b/icons/mob/clothing/species/vox/back.dmi
index 8274c45cb9c..8d1f48dd247 100644
Binary files a/icons/mob/clothing/species/vox/back.dmi and b/icons/mob/clothing/species/vox/back.dmi differ
diff --git a/icons/mob/clothing/species/vox/ears.dmi b/icons/mob/clothing/species/vox/ears.dmi
index 5168e567419..b19672c81b2 100644
Binary files a/icons/mob/clothing/species/vox/ears.dmi and b/icons/mob/clothing/species/vox/ears.dmi differ
diff --git a/icons/mob/clothing/species/wryn/mask.dmi b/icons/mob/clothing/species/wryn/mask.dmi
index 5e72a8730da..05d6662faea 100644
Binary files a/icons/mob/clothing/species/wryn/mask.dmi and b/icons/mob/clothing/species/wryn/mask.dmi differ
diff --git a/icons/obj/lighting.dmi b/icons/obj/lighting.dmi
index 8b853ba2bc8..ceb86c0667b 100644
Binary files a/icons/obj/lighting.dmi and b/icons/obj/lighting.dmi differ
diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi
index f26aa801de5..f928128df10 100644
Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ
diff --git a/paradise.dme b/paradise.dme
index 85c7ad843a5..30b22704ec1 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -424,12 +424,12 @@
#include "code\datums\cache\powermonitor.dm"
#include "code\datums\changelog\changelog.dm"
#include "code\datums\cinematics\cinematic_datum.dm"
+#include "code\datums\cinematics\kharin_summon.dm"
#include "code\datums\cinematics\malf_doomsday.dm"
#include "code\datums\cinematics\narsie_summon.dm"
-#include "code\datums\cinematics\kharin_summon.dm"
+#include "code\datums\cinematics\nuke_cinematics.dm"
#include "code\datums\cinematics\ratvar_summon.dm"
#include "code\datums\cinematics\reaper_summon.dm"
-#include "code\datums\cinematics\nuke_cinematics.dm"
#include "code\datums\components\_component.dm"
#include "code\datums\components\after_attacks_hub.dm"
#include "code\datums\components\animal_temperature.dm"