diff --git a/aurorastation.dme b/aurorastation.dme index 8ad55da15f1..4f0798ee15b 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -222,6 +222,7 @@ #include "code\controllers\subsystems\law.dm" #include "code\controllers\subsystems\lighting.dm" #include "code\controllers\subsystems\machinery.dm" +#include "code\controllers\subsystems\mapping.dm" #include "code\controllers\subsystems\materials.dm" #include "code\controllers\subsystems\mob.dm" #include "code\controllers\subsystems\mob_ai.dm" @@ -1965,6 +1966,7 @@ #include "code\modules\lighting\lighting_corner.dm" #include "code\modules\lighting\lighting_overlay.dm" #include "code\modules\lighting\lighting_profiler.dm" +#include "code\modules\lighting\lighting_setup.dm" #include "code\modules\lighting\lighting_source.dm" #include "code\modules\lighting\lighting_source_sunlight.dm" #include "code\modules\lighting\lighting_turf.dm" @@ -1976,6 +1978,7 @@ #include "code\modules\lock\lock_construct.dm" #include "code\modules\makeshift\makeshift_reagents.dm" #include "code\modules\maps\dmm_suite.dm" +#include "code\modules\maps\helper_landmarks.dm" #include "code\modules\maps\map_template.dm" #include "code\modules\maps\reader.dm" #include "code\modules\maps\ruins.dm" @@ -2942,6 +2945,9 @@ #include "code\modules\spell_system\spells\spell_list\self\generic\rune_write.dm" #include "code\modules\spell_system\spells\spell_list\self\generic\shadow_shroud.dm" #include "code\modules\spell_system\spells\spell_list\self\generic\shift.dm" +#include "code\modules\submaps\_submap.dm" +#include "code\modules\submaps\submap_archetype.dm" +#include "code\modules\submaps\submap_landmark.dm" #include "code\modules\supermatter\setup_supermatter.dm" #include "code\modules\supermatter\supermatter.dm" #include "code\modules\surgery\_defines.dm" @@ -3060,6 +3066,7 @@ #include "maps\aurora\code\aurora_lifts.dm" #include "maps\aurora\code\aurora_shuttles.dm" #include "maps\aurora\code\aurora_unittest.dm" +#include "maps\away\away_sites.dm" #include "maps\event\code\event.dm" #include "maps\event\odin_departure\code\odin_departure_areas.dm" #include "maps\event\odin_departure\code\odin_depature.dm" @@ -3071,8 +3078,10 @@ #include "maps\exodus\code\exodus_holodeck.dm" #include "maps\exodus\code\exodus_shuttles.dm" #include "maps\exodus\code\exodus_unittest.dm" -#include "maps\random_ruins\exoplanet_ruins\asteroid\asteroid.dm" #include "maps\random_ruins\exoplanets\exoplanet_ruins.dm" +#include "maps\random_ruins\exoplanets\asteroid\asteroid.dm" +#include "maps\random_ruins\exoplanets\crashed_pod\crashed_pod.dm" +#include "maps\random_ruins\space_ruins\space_ruins.dm" #include "maps\runtime\runtime_overmap.dm" #include "maps\runtime\code\runtime.dm" #include "maps\runtime\code\runtime_lifts.dm" diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm index a52509ae0b7..635014e20d6 100644 --- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm +++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm @@ -60,8 +60,8 @@ var/turf/T = get_turf(src) if(!istype(T)) return - add_underlay(T, node1, turn(dir, 180), node1?.icon_connect_type) - add_underlay(T, node2, dir, node2?.icon_connect_type) + add_underlay(T, node1, turn(dir, 180), icon_connect_type) + add_underlay(T, node2, dir, icon_connect_type) /obj/machinery/atmospherics/binary/passive_gate/hide(var/i) update_underlays() diff --git a/code/ATMOSPHERICS/components/unary/outlet_injector.dm b/code/ATMOSPHERICS/components/unary/outlet_injector.dm index 9f5c645e2b7..3b9b09be55c 100644 --- a/code/ATMOSPHERICS/components/unary/outlet_injector.dm +++ b/code/ATMOSPHERICS/components/unary/outlet_injector.dm @@ -129,6 +129,7 @@ ..() set_frequency(frequency) + broadcast_status() /obj/machinery/atmospherics/unary/outlet_injector/receive_signal(datum/signal/signal) if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command")) diff --git a/code/__defines/_layers.dm b/code/__defines/_layers.dm index e5a4670dc33..1a966fa0160 100644 --- a/code/__defines/_layers.dm +++ b/code/__defines/_layers.dm @@ -2,6 +2,7 @@ #define PLANE_SPACE_PARALLAX (PLANE_SPACE_BACKGROUND + 1) // -97 #define PLANE_SPACE_DUST (PLANE_SPACE_PARALLAX + 1) // -96 #define PLANE_ABOVE_PARALLAX (PLANE_SPACE_BACKGROUND + 3) // -95 +#define PLANE_DEFAULT 0 #define LOWER_ON_TURF_LAYER (TURF_LAYER + 0.05) // under the below #define ON_TURF_LAYER (TURF_LAYER + 0.1) // sitting on the turf - should be preferred over direct use of TURF_LAYER diff --git a/code/__defines/_macros.dm b/code/__defines/_macros.dm index e971d18f155..fdca86af2bf 100644 --- a/code/__defines/_macros.dm +++ b/code/__defines/_macros.dm @@ -1,6 +1,7 @@ #define Clamp(x, low, high) max(low, min(high, x)) #define CLAMP01(x) (Clamp(x, 0, 1)) #define JOINTEXT(X) jointext(X, null) +#define list_find(L, needle, LIMITS...) L.Find(needle, LIMITS) #define span(class, text) ("" + text + "") #define SPAN_NOTICE(X) ("" + X + "") diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm index 4c71d271d54..ec05e0a8bc2 100644 --- a/code/__defines/dcs/signals.dm +++ b/code/__defines/dcs/signals.dm @@ -33,5 +33,13 @@ // /mob signals // /obj signals +/// when a hood is unequipped +#define COMSIG_ITEM_REMOVE "item_remove" +/// checks an item's state +#define COMSIG_ITEM_STATE_CHECK "state_check" +/// updates an item between several states +#define COMSIG_ITEM_UPDATE_STATE "update_state" +/// updates sprites +#define COMSIG_ITEM_ICON_UPDATE "icon_update" /*******Component Specific Signals*******/ diff --git a/code/__defines/lighting.dm b/code/__defines/lighting.dm index 77da81798f8..4f7ac6ee97b 100644 --- a/code/__defines/lighting.dm +++ b/code/__defines/lighting.dm @@ -93,6 +93,13 @@ #define LIGHT_COLOR_HALOGEN "#C0C0CA" //Soft lighting for general-purpose light fixtures. rgb(192, 192, 202) #define LIGHT_COLOR_EMERGENCY "#FF3232" //Red color used by emergency lighting. rgb(255, 50, 50) #define LIGHT_COLOR_EMERGENCY_SOFT "#FA8282" //A softer emergency red, used for small bulbs. rgb(250, 130, 130) +#define LIGHT_COLOUR_WHITE "#FEFEFE" // Clinical white light bulbs +#define LIGHT_COLOUR_WARM "#FFFEE0" // Warm yellowish light bulbs + +#define LIGHT_STANDARD_COLORS list(LIGHT_COLOUR_WHITE, LIGHT_COLOUR_WARM, LIGHT_COLOR_HALOGEN) // List of standard light colors used for randomized lighting and selectable printed lights. + +#define LIGHT_MODE_RED "red" +#define LIGHT_MODE_DELTA "delta" //Defines for lighting status, see power/lighting.dm #define LIGHT_OK 0 @@ -109,7 +116,7 @@ #define LIGHT_NARROW 45 // Some brightness/range defines for objects. -#define L_WALLMOUNT_POWER 0.4 +#define L_WALLMOUNT_POWER 1.3 #define L_WALLMOUNT_RANGE 2 #define L_WALLMOUNT_HI_POWER 1 // For red/delta alert on fire alarms. #define L_WALLMOUNT_HI_RANGE 4 diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 0400a428abe..33d3b079543 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -491,7 +491,10 @@ Define for getting a bitfield of adjacent turfs that meet a condition. #define TEMPLATE_FLAG_SPAWN_GUARANTEED 2 // Makes it ignore away site budget and just spawn (only for away sites) #define TEMPLATE_FLAG_CLEAR_CONTENTS 4 // if it should destroy objects it spawns on top of #define TEMPLATE_FLAG_NO_RUINS 8 // if it should forbid ruins from spawning on top of it -#define TEMPLATE_FLAG_NO_RADS 16// Removes all radiation from the template after spawning. -#define LANDING_ZONE_RADIUS 15 // Used for autoplacing landmarks on exoplanets \ No newline at end of file +#define LANDING_ZONE_RADIUS 15 // Used for autoplacing landmarks on exoplanets + +//Ruin map template flags +#define TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED 32 // Ruin is not available during spawning unless another ruin permits it. + diff --git a/code/_helpers/icons.dm b/code/_helpers/icons.dm index 173b04febd8..1e7b75964f0 100644 --- a/code/_helpers/icons.dm +++ b/code/_helpers/icons.dm @@ -640,7 +640,7 @@ proc/ColorTone(rgb, tone) /// appearance system (overlays/underlays, etc.) is not available. /// /// Only the first argument is required. -/proc/getFlatIcon(image/A, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE) +/proc/getFlatIcon(image/A, defdir, deficon, defstate, defblend, start = TRUE, no_anim = FALSE, ignore_parent_dir = FALSE) //Define... defines. var/static/icon/flat_template = icon('icons/effects/effects.dmi', "nothing") @@ -701,7 +701,7 @@ proc/ColorTone(rgb, tone) var/base_icon_dir //We'll use this to get the icon state to display if not null BUT NOT pass it to overlays as the dir we have //These should use the parent's direction (most likely) - if(!A.dir || A.dir == SOUTH) + if(!A.dir || A.dir == SOUTH || ignore_parent_dir) curdir = defdir else curdir = A.dir diff --git a/code/_helpers/sorting/cmp.dm b/code/_helpers/sorting/cmp.dm index 41ca9c64c8c..b6deea30a9b 100644 --- a/code/_helpers/sorting/cmp.dm +++ b/code/_helpers/sorting/cmp.dm @@ -85,3 +85,6 @@ /proc/cmp_clientcolor_priority(datum/client_color/A, datum/client_color/B) return B.priority - A.priority + +/proc/cmp_ruincost_priority(datum/map_template/ruin/A, datum/map_template/ruin/B) + return initial(A.spawn_cost) - initial(B.spawn_cost) diff --git a/code/_helpers/type2type.dm b/code/_helpers/type2type.dm index 61ca2daa2c5..8b933f9fdb6 100644 --- a/code/_helpers/type2type.dm +++ b/code/_helpers/type2type.dm @@ -50,6 +50,14 @@ while (left-- > 0) . = "0[.]" +// Splits the text of a file at seperator and returns them in a list. +/proc/file2list(filename, seperator="\n") + return splittext(file2text(filename) || "", seperator) + +//Splits the text of a file at seperator and returns them in a list. +/world/proc/file2list(filename, seperator="\n") + return splittext(file2text(filename), seperator) + // Slower then list2text (replaced with jointext), but correctly processes associative lists. proc/tg_list2text(list/list, glue=",") if (!istype(list) || !list.len) @@ -97,10 +105,6 @@ proc/tg_list2text(list/list, glue=",") num_list += text2num(x) return num_list -// Splits the text of a file at seperator and returns them in a list. -/proc/file2list(filename, seperator="\n") - return text2list(return_file_text(filename),seperator) - // Turns a direction into text /proc/num2dir(direction) switch (direction) diff --git a/code/_onclick/hud/ability_screen_objects.dm b/code/_onclick/hud/ability_screen_objects.dm index cff2b45eaae..201c313744c 100644 --- a/code/_onclick/hud/ability_screen_objects.dm +++ b/code/_onclick/hud/ability_screen_objects.dm @@ -232,7 +232,7 @@ /obj/screen/ability/verb_based/activate() if(object_used && verb_to_call) - call(object_used,verb_to_call)(arguments_to_use) //TODOMATT: WHY GOD WHY + call(object_used,verb_to_call)(arguments_to_use) /obj/screen/movable/ability_master/proc/add_verb_ability(var/object_given, var/verb_given, var/name_given, var/ability_icon_given, var/arguments) if(!object_given) diff --git a/code/controllers/subsystems/garbage-debug.dm b/code/controllers/subsystems/garbage-debug.dm index b4a2077005f..d13ef1dd5a6 100644 --- a/code/controllers/subsystems/garbage-debug.dm +++ b/code/controllers/subsystems/garbage-debug.dm @@ -380,6 +380,7 @@ SearchVar(SSpipenet) SearchVar(SSprocessing) SearchVar(SSshuttle) + SearchVar(SSmapping) SearchVar(base_law_type) SearchVar(discord_bot) SearchVar(diseases) diff --git a/code/controllers/subsystems/initialization/misc_late.dm b/code/controllers/subsystems/initialization/misc_late.dm index b21ab2fcb91..9b7a781afcd 100644 --- a/code/controllers/subsystems/initialization/misc_late.dm +++ b/code/controllers/subsystems/initialization/misc_late.dm @@ -46,6 +46,8 @@ click_catchers = create_click_catcher() + current_map.build_away_sites() + current_map.build_exoplanets() ..(timeofday) diff --git a/code/controllers/subsystems/machinery.dm b/code/controllers/subsystems/machinery.dm index e88cb2f4ac3..091370d27bd 100644 --- a/code/controllers/subsystems/machinery.dm +++ b/code/controllers/subsystems/machinery.dm @@ -214,4 +214,18 @@ /datum/controller/subsystem/machinery/ExplosionEnd() wake() +/datum/controller/subsystem/machinery/proc/setup_atmos_machinery(list/machines) + set background = TRUE + var/list/atmos_machines = list() + for (var/obj/machinery/atmospherics/machine in machines) + atmos_machines += machine + log_game("Initializing atmos machinery") + for (var/obj/machinery/atmospherics/machine as anything in atmos_machines) + machine.atmos_init() + CHECK_TICK + log_game("Initializing pipe networks") + for (var/obj/machinery/atmospherics/machine as anything in atmos_machines) + machine.build_network() + CHECK_TICK + #undef MACHINERY_GO_TO_NEXT diff --git a/code/controllers/subsystems/mapping.dm b/code/controllers/subsystems/mapping.dm new file mode 100644 index 00000000000..1e4b14364b0 --- /dev/null +++ b/code/controllers/subsystems/mapping.dm @@ -0,0 +1,94 @@ +var/datum/controller/subsystem/mapping/SSmapping + +/datum/controller/subsystem/mapping + name = "Mapping" + init_order = SS_INIT_MISC + flags = SS_NO_FIRE + + var/list/map_templates = list() + var/list/space_ruins_templates = list() + var/list/exoplanet_ruins_templates = list() + var/list/away_sites_templates = list() + var/list/submaps = list() + var/list/submap_archetypes = list() + +/datum/controller/subsystem/mapping/New() + NEW_SS_GLOBAL(SSmapping) + +/datum/controller/subsystem/mapping/Initialize(timeofday) + // Load templates and build away sites. + preloadTemplates() + for(var/atype in subtypesof(/decl/submap_archetype)) + submap_archetypes[atype] = new atype + . = ..() + +/datum/controller/subsystem/mapping/Recover() + flags |= SS_NO_INIT + map_templates = SSmapping.map_templates + space_ruins_templates = SSmapping.space_ruins_templates + exoplanet_ruins_templates = SSmapping.exoplanet_ruins_templates + away_sites_templates = SSmapping.away_sites_templates + +/datum/controller/subsystem/mapping/proc/preloadTemplates(path = "maps/templates/") //see master controller setup + var/list/filelist = flist(path) + for(var/map in filelist) + var/datum/map_template/T = new(path = "[path][map]", rename = "[map]") + map_templates[T.name] = T + preloadBlacklistableTemplates() + +/datum/controller/subsystem/mapping/proc/preloadBlacklistableTemplates() + // Still supporting bans by filename + var/list/banned_exoplanet_dmms = generateMapList("config/exoplanet_ruin_blacklist.txt") + var/list/banned_space_dmms = generateMapList("config/space_ruin_blacklist.txt") + var/list/banned_away_site_dmms = generateMapList("config/away_site_blacklist.txt") + + if (!banned_exoplanet_dmms || !banned_space_dmms || !banned_away_site_dmms) + log_admin("One or more map blacklist files are not present in the config directory!") + + var/list/banned_maps = list() + banned_exoplanet_dmms + banned_space_dmms + banned_away_site_dmms + + for(var/item in sortList(subtypesof(/datum/map_template), /proc/cmp_ruincost_priority)) + var/datum/map_template/map_template_type = item + // screen out the abstract subtypes + if(!initial(map_template_type.id)) + continue + var/datum/map_template/MT = new map_template_type() + + if (banned_maps) + var/mappath = MT.mappath + if(list_find(banned_maps, mappath)) + break + + map_templates[MT.name] = MT + + // This is nasty.. + if(istype(MT, /datum/map_template/ruin/exoplanet)) + exoplanet_ruins_templates[MT.name] = MT + else if(istype(MT, /datum/map_template/ruin/space)) + space_ruins_templates[MT.name] = MT + else if(istype(MT, /datum/map_template/ruin/away_site)) + away_sites_templates[MT.name] = MT + +/proc/generateMapList(filename) + var/list/potentialMaps = list() + var/list/Lines = world.file2list(filename) + if(!Lines.len) + return + for (var/t in Lines) + if (!t) + continue + t = trim(t) + if (length(t) == 0) + continue + else if (copytext(t, 1, 2) == "#") + continue + var/pos = findtext(t, " ") + var/name = null + if (pos) + name = lowertext(copytext(t, 1, pos)) + else + name = lowertext(t) + if (!name) + continue + potentialMaps.Add(t) + return potentialMaps diff --git a/code/datums/observation/equipped.dm b/code/datums/observation/equipped.dm index 06dc5a8b013..acddd989d67 100644 --- a/code/datums/observation/equipped.dm +++ b/code/datums/observation/equipped.dm @@ -38,6 +38,7 @@ var/datum/observ/item_equipped/item_equipped_event = new() . = ..() mob_equipped_event.raise_event(user, src, slot) item_equipped_event.raise_event(src, user, slot) + SEND_SIGNAL(src, COMSIG_ITEM_REMOVE, src) /obj/item/proc/check_equipped(var/mob/user, var/slot, var/assisted_equip = FALSE) return TRUE \ No newline at end of file diff --git a/code/datums/outfits/outfit.dm b/code/datums/outfits/outfit.dm index 2146c6da504..243adf19e26 100644 --- a/code/datums/outfits/outfit.dm +++ b/code/datums/outfits/outfit.dm @@ -369,7 +369,7 @@ var/obj/item/I = new id(H) imprint_idcard(H,I) if(istype(P) && P.card_slot) - addtimer(CALLBACK(src, .proc/register_pda, P, I), 1 SECOND) + addtimer(CALLBACK(src, .proc/register_pda, P, I), 2 SECOND) else H.equip_or_collect(I, slot_wear_id) diff --git a/code/datums/ruins.dm b/code/datums/ruins.dm index 093e5a742f8..c9d521c9423 100644 --- a/code/datums/ruins.dm +++ b/code/datums/ruins.dm @@ -6,13 +6,19 @@ It is clearly a mystery." var/spawn_weight = 1 - var/cost = null + var/spawn_cost = 0 + var/player_cost = 0 var/list/sectors = list() //This ruin can only spawn in the sectors in this list. var/prefix = null var/suffix = null template_flags = 0 // No duplicates by default + // !! Currently only implemented for away sites + var/list/force_ruins // Listed ruins are always spawned unless disallowed by flags. + var/list/allow_ruins // Listed ruins are added to the set of available spawns. + var/list/ban_ruins // Listed ruins are removed from the set of available spawns. Beats allowed. + /datum/map_template/ruin/New() if (suffix) mappath += (prefix + suffix) diff --git a/code/datums/uplink/announcements.dm b/code/datums/uplink/announcements.dm index 9e7acaa7dc2..93ae47ad22c 100644 --- a/code/datums/uplink/announcements.dm +++ b/code/datums/uplink/announcements.dm @@ -46,18 +46,23 @@ random_record = new(user) var/datum/record/general/record = random_record.Copy() - + if(I) record.age = I.age - record.rank = I.assignment - record.real_rank = I.assignment record.name = I.registered_name record.sex = I.sex + record.employer = I.employer_faction + var/datum/faction/id_faction = SSjobs.name_factions[I.employer_faction] + var/faction_abbreviation = id_faction.title_suffix + var/assignment = "[I.assignment][ faction_abbreviation ? " ([faction_abbreviation])" : ""]" + record.rank = assignment + record.real_rank = assignment else var/mob/living/carbon/human/H if(istype(user,/mob/living/carbon/human)) H = user record.age = H.age + record.employer = H.employer_faction else record.age = initial(H.age) var/assignment = GetAssignment(user) diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index 2c48f34f460..8eaf23b8c49 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -199,6 +199,7 @@ //Ensure that antags with ANTAG_OVERRIDE_JOB do not occupy job slots. if(flags & ANTAG_OVERRIDE_JOB) player.assigned_role = role_text + player.role_alt_title = role_text //Ensure that a player cannot be drafted for multiple antag roles, taking up slots for antag roles that they will not fill. player.special_role = role_text diff --git a/code/game/antagonist/antagonist_add.dm b/code/game/antagonist/antagonist_add.dm index d08f7920a2d..1cc74fc0432 100644 --- a/code/game/antagonist/antagonist_add.dm +++ b/code/game/antagonist/antagonist_add.dm @@ -6,6 +6,7 @@ //do this again, just in case if(flags & ANTAG_OVERRIDE_JOB) player.assigned_role = role_text + player.role_alt_title = role_text player.special_role = role_text if(istype(player.current, /mob/abstract)) @@ -122,4 +123,4 @@ //Run the query to update the db entry with the removal time var/DBQuery/update_query = dbcon.NewQuery("UPDATE ss13_antag_log SET special_role_removed = :special_role_removed: WHERE id = :id:") - update_query.Execute(list("id"=db_log_id,"special_role_removed"="[get_round_duration_formatted()]:00")) \ No newline at end of file + update_query.Execute(list("id"=db_log_id,"special_role_removed"="[get_round_duration_formatted()]:00")) diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 555eca31262..631e43f8e1b 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -47,6 +47,7 @@ var/turf/base_turf //The base turf type of the area, which can be used to override the z-level's base turf var/no_light_control = 0 // if 1, lights in area cannot be toggled with light controller var/allow_nightmode = 0 // if 1, lights in area will be darkened by the night mode controller + var/emergency_lights = FALSE var/station_area = 0 var/centcomm_area = 0 var/has_weird_power = FALSE // If TRUE, SSmachinery will not use the inlined power checks and will call powered() and use_power() on this area. diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 1a2787cff7f..7e0823e48cf 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -292,7 +292,7 @@ /atom/proc/emag_act(var/remaining_charges, var/mob/user, var/emag_source) return NO_EMAG_ACT -/atom/proc/fire_act() +/atom/proc/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) return /atom/proc/melt() diff --git a/code/game/gamemodes/cult/items/talisman.dm b/code/game/gamemodes/cult/items/talisman.dm index e0bc85b3384..b19084233ce 100644 --- a/code/game/gamemodes/cult/items/talisman.dm +++ b/code/game/gamemodes/cult/items/talisman.dm @@ -1,5 +1,6 @@ /obj/item/paper/talisman icon_state = "paper_talisman" + can_change_icon_state = FALSE var/uses = 1 var/datum/rune/rune info = "


" @@ -33,4 +34,4 @@ /obj/item/paper/talisman/proc/use() uses-- if(uses <= 0) - qdel(src) \ No newline at end of file + qdel(src) diff --git a/code/game/gamemodes/technomancer/spells/audible_deception.dm b/code/game/gamemodes/technomancer/spells/audible_deception.dm index b3704bef6dd..dd8ac673b21 100644 --- a/code/game/gamemodes/technomancer/spells/audible_deception.dm +++ b/code/game/gamemodes/technomancer/spells/audible_deception.dm @@ -81,8 +81,6 @@ if(selected_sound == 'sound/items/AirHorn.ogg' && pay_energy(3800)) adjust_instability(49) // Pay for your sins. for(var/mob/living/carbon/M in ohearers(6, T)) - //if(M.get_ear_protection() >= 2) todomatt: ear protection - // continue M.SetSleeping(0) M.stuttering += 20 M.ear_deaf += 30 diff --git a/code/game/gamemodes/technomancer/spells/dispel.dm b/code/game/gamemodes/technomancer/spells/dispel.dm index 0597f0a51a4..17895c6d4bb 100644 --- a/code/game/gamemodes/technomancer/spells/dispel.dm +++ b/code/game/gamemodes/technomancer/spells/dispel.dm @@ -16,8 +16,5 @@ aspect = ASPECT_BIOMED /obj/item/spell/dispel/on_ranged_cast(atom/hit_atom, mob/living/user) - //if(isliving(hit_atom) && within_range(hit_atom) && pay_energy(1000)) todomatt: fuck this thinjg - // var/mob/living/target = hit_atom - // target.remove_modifiers_of_type(/datum/modifier/technomancer) user.adjust_instability(10) qdel(src) \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/modifier/mend_all.dm b/code/game/gamemodes/technomancer/spells/modifier/mend_all.dm deleted file mode 100644 index a94906c6ddc..00000000000 --- a/code/game/gamemodes/technomancer/spells/modifier/mend_all.dm +++ /dev/null @@ -1,35 +0,0 @@ -// Gambit only spell. Heals everything unconditionally. - -/obj/item/spell/modifier/mend_all - name = "mend all" - desc = "One function to heal them all." - icon_state = "mend_all" - cast_methods = CAST_MELEE - aspect = ASPECT_BIOMED - light_color = "#FF5C5C" - modifier_type = /datum/modifier/technomancer/mend_life - modifier_duration = 1 MINUTE - -/datum/modifier/technomancer/mend_all - name = "mend all" - desc = "You feel serene and well rested." - mob_overlay_state = "green_sparkles" - - on_created_text = "Sparkles begin to appear around you, and all your ills seem to fade away." - on_expired_text = "The sparkles have faded, although you feel much healthier than before." - stacks = MODIFIER_STACK_EXTEND - -/datum/modifier/technomancer/mend_all/tick() - if(!holder.getBruteLoss() && !holder.getFireLoss() && !holder.getToxLoss() && !holder.getOxyLoss() && !holder.getCloneLoss()) // No point existing if the spell can't heal. - stop() - return - holder.adjustBruteLoss(-4 * spell_power) // Should heal roughly 120 damage over 1 minute, as tick() is run every 2 seconds. - holder.adjustFireLoss(-4 * spell_power) - holder.adjustToxLoss(-4 * spell_power) - holder.adjustOxyLoss(-4 * spell_power) - holder.adjustCloneLoss(-2 * spell_power) // 60 cloneloss - holder.adjust_instability(1) - if(origin) - var/mob/living/L = origin.resolve() - if(istype(L)) - L.adjust_instability(1) //TODOMATT: Tick this file and figure this out \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/modifier/mend_life.dm b/code/game/gamemodes/technomancer/spells/modifier/mend_life.dm index b7f0eac5678..c65f3c65efe 100644 --- a/code/game/gamemodes/technomancer/spells/modifier/mend_life.dm +++ b/code/game/gamemodes/technomancer/spells/modifier/mend_life.dm @@ -39,4 +39,4 @@ if(source) var/mob/living/L = source if(istype(L)) - L.adjust_instability(1) //TODOMATT: Tick this file and figure this out \ No newline at end of file + L.adjust_instability(1) \ No newline at end of file diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index 905275703d2..934e58609ef 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -88,9 +88,12 @@ icon_state = H.pulse() ? "[modify_state]-active" : "[modify_state]-idle" victim = H if(victim && !victim.isSynthetic()) - if(suppressing && victim.sleeping < 3) - victim.Sleeping(3 - victim.sleeping) + if(suppressing && victim.sleeping < 7) + victim.Sleeping(7 - victim.sleeping) victim.willfully_sleeping = FALSE + icon_state = victim.pulse() ? "[modify_state]-active" : "[modify_state]-idle" + if(victim.stat == DEAD || victim.is_asystole() || victim.status_flags & FAKEDEATH) + icon_state = "[modify_state]-critical" return TRUE icon_state = "[modify_state]-idle" return FALSE @@ -113,6 +116,8 @@ var/mob/living/carbon/human/H = C victim = H icon_state = H.pulse() ? "[modify_state]-active" : "[modify_state]-idle" + if(H.stat == DEAD || H.is_asystole() || H.status_flags & FAKEDEATH) + icon_state = "[modify_state]-critical" else icon_state = "[modify_state]-idle" diff --git a/code/game/machinery/autolathe/autolathe.dm b/code/game/machinery/autolathe/autolathe.dm index b19ee182093..24e06172624 100644 --- a/code/game/machinery/autolathe/autolathe.dm +++ b/code/game/machinery/autolathe/autolathe.dm @@ -174,55 +174,7 @@ if(is_robot_module(O)) return FALSE - //Resources are being loaded. - var/obj/item/eating = O - if(!eating.matter || !eating.recyclable) - to_chat(user, SPAN_WARNING("\The [eating] cannot be recycled by \the [src].")) - return - - var/filltype = 0 // Used to determine message. - var/total_used = 0 // Amount of material used. - var/mass_per_sheet = 0 // Amount of material constituting one sheet. - - for(var/material in eating.matter) - if(isnull(stored_material[material]) || isnull(storage_capacity[material])) - continue - if(stored_material[material] >= storage_capacity[material]) - continue - - var/total_material = eating.matter[material] - - //If it's a stack, we eat multiple sheets. - if(istype(eating, /obj/item/stack)) - var/obj/item/stack/stack = eating - total_material *= stack.get_amount() - - if(stored_material[material] + total_material > storage_capacity[material]) - total_material = storage_capacity[material] - stored_material[material] - filltype = 1 - else - filltype = 2 - - stored_material[material] += total_material - total_used += total_material - mass_per_sheet += eating.matter[material] - - if(!filltype) - to_chat(user, SPAN_WARNING("\The [src] is full. Please remove some material in order to insert more.")) - return - else if(filltype == 1) - to_chat(user, SPAN_NOTICE("You fill \the [src] to capacity with \the [eating].")) - else - to_chat(user, SPAN_NOTICE("You fill \the [src] with \the [eating].")) - - flick("autolathe_o", src) // Plays metal insertion animation. Work out a good way to work out a fitting animation. ~Z - - if(istype(eating, /obj/item/stack)) - var/obj/item/stack/stack = eating - stack.use(max(1, round(total_used / mass_per_sheet))) // Always use at least 1 to prevent infinite materials. - else - user.remove_from_mob(O) - qdel(O) + load_lathe(O, user) updateUsrDialog() return @@ -334,3 +286,64 @@ qdel(S) ..() return TRUE + +#define NO_SPACE "No Space" +#define FILL_COMPLETELY "Fill Completely" +#define FILL_INCOMPLETELY "Fill Incompletely" + +/obj/machinery/autolathe/proc/load_lathe(obj/item/O, mob/user) + + //Resources are being loaded. + var/obj/item/eating = O + if(!eating.matter || !eating.recyclable) + to_chat(user, SPAN_WARNING("\The [eating] cannot be recycled by \the [src].")) + return + + var/list/fill_status = list() // Used to determine message in cases of multiple materials. + var/total_used = 0 // Amount of material used. + var/mass_per_sheet = 0 // Amount of material constituting one sheet. + + for(var/material in eating.matter) + if(isnull(stored_material[material]) || isnull(storage_capacity[material])) + continue + if(stored_material[material] >= storage_capacity[material]) + LAZYADD(fill_status[NO_SPACE], material) + continue + + var/total_material = eating.matter[material] + + //If it's a stack, we eat multiple sheets. + if(istype(eating, /obj/item/stack)) + var/obj/item/stack/stack = eating + total_material *= stack.get_amount() + + if(stored_material[material] + total_material > storage_capacity[material]) + total_material = storage_capacity[material] - stored_material[material] + LAZYADD(fill_status[FILL_COMPLETELY], material) + else + LAZYADD(fill_status[FILL_INCOMPLETELY], material) + + stored_material[material] += total_material + total_used += total_material + mass_per_sheet += eating.matter[material] + + if(fill_status[NO_SPACE]) + to_chat(user, SPAN_WARNING("\The [src] is full of [english_list(fill_status[NO_SPACE])]. Please remove some material in order to insert more.")) + return + else if(fill_status[FILL_COMPLETELY]) + to_chat(user, SPAN_NOTICE("You fill \the [src] to capacity with [english_list(fill_status[FILL_COMPLETELY])] with \the [eating].")) + else if(fill_status[FILL_INCOMPLETELY]) + to_chat(user, SPAN_NOTICE("You fill \the [src] with [english_list(fill_status[FILL_INCOMPLETELY])] \the [eating].")) + + flick("autolathe_o", src) // Plays metal insertion animation. Work out a good way to work out a fitting animation. ~Z + + if(istype(eating, /obj/item/stack)) + var/obj/item/stack/stack = eating + stack.use(min(stack.get_amount(), total_used / mass_per_sheet)) // Prevent maths imprecision from leading to infinite resources + else + user.remove_from_mob(O) + qdel(O) + +#undef NO_SPACE +#undef FILL_COMPLETELY +#undef FILL_INCOMPLETELY \ No newline at end of file diff --git a/code/game/machinery/body_scanner.dm b/code/game/machinery/body_scanner.dm index 4ee5bb11c93..2caac270567 100644 --- a/code/game/machinery/body_scanner.dm +++ b/code/game/machinery/body_scanner.dm @@ -330,7 +330,7 @@ // shouldn't be reachable if occupant is invalid if(href_list["print"]) - var/obj/item/paper/R = new(loc) + var/obj/item/paper/medscan/R = new(loc) R.color = "#eeffe8" R.set_content_unsafe("Scan ([connected.occupant])", format_occupant_data(connected.get_occupant_data())) diff --git a/code/game/machinery/chem_heater.dm b/code/game/machinery/chem_heater.dm index 23ec388b5a6..f5766e01715 100644 --- a/code/game/machinery/chem_heater.dm +++ b/code/game/machinery/chem_heater.dm @@ -1,3 +1,5 @@ +#define SLOW_MODE_MAX_TEMP_CHANGE 2 //C + /obj/machinery/chem_heater name = "chemical heater" desc = "A simple device that can be used to heat the contents of a beaker to a precise temperature." @@ -14,6 +16,7 @@ var/should_heat = TRUE var/min_temperature = 100 var/max_temperature = 600 + var/slow_mode = FALSE component_types = list( /obj/item/circuitboard/chem_heater, @@ -56,6 +59,7 @@ var/dat = "" dat += "Power: [use_power ? "On" : "Off"]" + dat += "

Slow Heating Mode: [slow_mode ? "On" : "Off"]" dat += "

Target Temp: [round(target_temperature)]K / [round(target_temperature - T0C,0.1)]C
" @@ -102,6 +106,8 @@ target_temperature = max(min_temperature,min(target_temperature + text2num(href_list["power"]),max_temperature)) if(container) should_heat = target_temperature >= container.get_temperature() + if("slowmode") + slow_mode = !slow_mode updateUsrDialog() @@ -115,6 +121,7 @@ if(container && container.reagents) var/current_temperature = container.reagents.get_temperature() + var/target_temperature_limited = slow_mode ? current_temperature + SLOW_MODE_MAX_TEMP_CHANGE : target_temperature if(should_heat && current_temperature >= target_temperature) use_power = 0 @@ -128,7 +135,7 @@ var/joules_to_use = machine_strength * 1000 var/mod = should_heat ? 1 : -1 var/thermal_energy_change = 0 - var/thermal_energy_limit = container.reagents.get_thermal_energy_change(current_temperature,target_temperature) //Don't go over the target temperature + var/thermal_energy_limit = container.reagents.get_thermal_energy_change(current_temperature,target_temperature_limited) //Don't go over the target temperature var/thermal_energy_limit2 = container.reagents.get_thermal_energy_change(current_temperature,current_temperature + machine_strength*mod*5) //So small reagents don't go from 0 to 1000 in a few seconds. if(mod > 0) //GOING UP thermal_energy_change = min(joules_to_use,thermal_energy_limit,thermal_energy_limit2) @@ -155,3 +162,4 @@ +#undef SLOW_MODE_MAX_TEMP_CHANGE \ No newline at end of file diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 5bedfba05b6..2c841a9bbad 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -11,6 +11,11 @@ circuit = /obj/item/circuitboard/operating var/mob/living/carbon/human/victim = null var/obj/machinery/optable/table = null + var/last_ba // Brain Activity + var/last_bo // Blood Oxygenation + var/last_critical + var/obj/item/paper/medscan/input_scan = null + var/obj/machinery/body_scanconsole/internal_bodyscanner = null /obj/machinery/computer/operating/Initialize() . = ..() @@ -19,6 +24,11 @@ if (table) table.computer = src break + if(!internal_bodyscanner) // So it can scan correctly + var/obj/machinery/body_scanconsole/S = new (src) + S.forceMove(src) + S.use_power = FALSE + internal_bodyscanner = S /obj/machinery/computer/operating/attack_ai(mob/user) if(!ai_can_interact(user)) @@ -35,6 +45,22 @@ return interact(user) +/obj/machinery/computer/operating/attackby(obj/item/O as obj, mob/user) + if(istype(O, /obj/item/paper/medscan)) + if(input_scan) + to_chat(usr, SPAN_NOTICE("There is already a [O] inside!")) + return + user.drop_from_inventory(O,src) + input_scan = O + input_scan.color = "#272727" + input_scan.set_content_unsafe("Scan ([victim])", operating_format(get_medical_data(victim))) + usr.visible_message("\The [src] pings, displaying \the [input_scan].") + to_chat(usr, SPAN_NOTICE("You insert \the [O] into [src].")) + playsound(src, 'sound/bureaucracy/scan.ogg', 50, 1) + else + to_chat(usr, SPAN_NOTICE("You try to insert \the [O], but \the [src] buzzes, unable to read it.")) + playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1) + return /obj/machinery/computer/operating/interact(mob/user) if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) ) @@ -48,12 +74,23 @@ if(src.table && (src.table.check_victim())) src.victim = src.table.victim dat += {" -Patient Information:
-Brain Activity: [victim.isFBP() ? "N/A" : victim.get_brain_status()]
-Pulse: [victim.get_pulse(GETPULSE_TOOL)]
-BP: [victim.get_blood_pressure()]
-Blood Oxygenation: [victim.get_blood_oxygenation()]
-"} + Patient Information:
+ Brain Activity: [victim.isFBP() ? "N/A" : victim.get_brain_status()]
+ Pulse: [victim.get_pulse(GETPULSE_TOOL)]
+ BP: [victim.get_blood_pressure()]
+ Blood Oxygenation: [victim.get_blood_oxygenation()]
+ Blood Volume: [victim.get_blood_volume()]%
+ "} + if(!input_scan) + dat += "Patient Scan: Scan not found. Please insert a Medical Scan.
" + else + dat += {" + Patient Scan: [input_scan]
+ Update scan + Remove and update scan + Print new scan


+ "} + dat += "[input_scan.get_content()]" else src.victim = null dat += {" @@ -61,7 +98,7 @@ Blood Oxygenation: [victim.get_blood_oxygenation()]

No Patient Detected "} - var/datum/browser/op_win = new(user, "op", capitalize_first_letters(name), 200, 200) + var/datum/browser/op_win = new(user, "op", capitalize_first_letters(name), 450, 800) op_win.set_content(dat) op_win.open() @@ -76,18 +113,217 @@ Blood Oxygenation: [victim.get_blood_oxygenation()]
to_chat(user, SPAN_NOTICE("Pulse: [victim.get_pulse(GETPULSE_TOOL)]")) to_chat(user, SPAN_NOTICE("BP: [victim.get_blood_pressure()]")) to_chat(user, SPAN_NOTICE("Blood Oxygenation: [victim.get_blood_oxygenation()]")) + to_chat(user, SPAN_NOTICE("Blood Volume: [victim.get_blood_volume()]%")) + if(!input_scan) + to_chat(user, SPAN_NOTICE("Patient Scan: Scan not found. Please insert the Medical Scan.")) + else + to_chat(user, SPAN_NOTICE("Patient Scan: [input_scan]")) else src.victim = null to_chat(user, SPAN_NOTICE("No Patient Detected")) /obj/machinery/computer/operating/Topic(href, href_list) - if(..()) - return 1 + ..() + if(href_list["action"]) + switch(href_list["action"]) + if("update") + input_scan.set_content_unsafe("Scan ([victim])", operating_format(get_medical_data(victim))) + usr.visible_message("\The [src] chimes, updating \the [input_scan].") + playsound(src, 'sound/machines/chime.ogg', 50, 1) + if("eject") + usr.visible_message("\The [src] beeps, ejecting \the [input_scan].") + input_scan.color = "#eeffe8" + input_scan.set_content_unsafe("Scan ([victim])", internal_bodyscanner.format_occupant_data(get_medical_data(victim))) // Re-formats it correctly + input_scan.forceMove(usr.loc) + usr.put_in_hands(input_scan) + input_scan = null + playsound(src, 'sound/machines/twobeep.ogg', 50, 1) + if("print_new") + print_new() + usr.visible_message("\The [src] beeps, printing a new [input_scan] after a moment.") if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon))) usr.set_machine(src) return - /obj/machinery/computer/operating/machinery_process() if(operable()) src.updateDialog() + if(src.table && (src.table.check_victim())) // Specific warning alarms for specific conditions. Times to be tweaked according to feedback + src.victim = src.table.victim + if(src.victim.stat != DEAD && !src.victim.is_diona()) + if(victim.get_blood_oxygenation() < 30 && victim.get_brain_result() < 20) + if(world.time > last_critical + 25 SECONDS) + last_critical = world.time + src.visible_message(SPAN_WARNING("Warning! [victim]'s Blood Oxygenation AND Brain Activity are in critical condition!")) + playsound(src, 'sound/effects/3.wav', 75) + else + if(victim.get_blood_oxygenation() < 30 && victim.get_brain_result() > 20) + blood_oxygenation_alarm() + if(victim.get_brain_result() < 20 && victim.get_blood_oxygenation() > 30) + brain_activity_alarm() + + +/obj/machinery/computer/operating/proc/blood_oxygenation_alarm() + if(world.time > last_bo + 25 SECONDS) + last_bo = world.time + src.visible_message(SPAN_WARNING("Warning! [victim]'s Blood Oxygenation is in critical condition!")) + playsound(src, 'sound/machines/ringer.ogg', 50) + +/obj/machinery/computer/operating/proc/brain_activity_alarm() + if(world.time > last_ba + 20 SECONDS) + last_ba = world.time + src.visible_message(SPAN_WARNING("Warning! [victim]'s Brain Activity is in critical condition!")) + playsound(src, 'sound/effects/alert.ogg', 50) + +// PRINTING SHENANIGANRY +/obj/machinery/computer/operating/proc/print_new() + var/obj/item/paper/medscan/S = new() + usr.put_in_hands(S) + S.color = "#eeffe8" + S.set_content_unsafe("Scan ([victim])", internal_bodyscanner.format_occupant_data(get_medical_data(victim))) + playsound(src, 'sound/bureaucracy/print.ogg', 50, 1) + +/obj/machinery/computer/operating/proc/get_medical_data(var/mob/living/carbon/human/H) + if (!ishuman(H)) + return + + var/list/medical_data = list( + "stationtime" = worldtime2text(), + "brain_activity" = H.get_brain_status(), + "blood_volume" = H.get_blood_volume(), + "blood_oxygenation" = H.get_blood_oxygenation(), + "blood_pressure" = H.get_blood_pressure(), + + "bruteloss" = get_severity(H.getBruteLoss(), TRUE), + "fireloss" = get_severity(H.getFireLoss(), TRUE), + "oxyloss" = get_severity(H.getOxyLoss(), TRUE), + "toxloss" = get_severity(H.getToxLoss(), TRUE), + "cloneloss" = get_severity(H.getCloneLoss(), TRUE), + + "rads" = H.total_radiation, + "paralysis" = H.paralysis, + "bodytemp" = H.bodytemperature, + "borer_present" = H.has_brain_worms(), + "inaprovaline_amount" = REAGENT_VOLUME(H.reagents, /decl/reagent/inaprovaline), + "dexalin_amount" = REAGENT_VOLUME(H.reagents, /decl/reagent/dexalin), + "stoxin_amount" = REAGENT_VOLUME(H.reagents, /decl/reagent/soporific), + "bicaridine_amount" = REAGENT_VOLUME(H.reagents, /decl/reagent/bicaridine), + "dermaline_amount" = REAGENT_VOLUME(H.reagents, /decl/reagent/dermaline), + "thetamycin_amount" = REAGENT_VOLUME(H.reagents, /decl/reagent/thetamycin), + "blood_amount" = REAGENT_VOLUME(H.vessel, /decl/reagent/blood), + "disabilities" = H.sdisabilities, + "lung_ruptured" = H.is_lung_ruptured(), + "external_organs" = H.organs.Copy(), + "internal_organs" = H.internal_organs.Copy(), + "species_organs" = H.species.has_organ + ) + return medical_data + +/obj/machinery/computer/operating/proc/operating_format(var/list/occ) // Format to cut out redundant information + var/dat = "
Scan last updated at [occ["stationtime"]]
" + if(occ["borer_present"]) + dat += "Large growth detected in frontal lobe, possibly cancerous. Surgical removal is recommended.
" + + dat += "
" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + dat += "" + + for(var/obj/item/organ/external/e in occ["external_organs"]) + var/AN = "" + var/open = "" + var/infected = "" + var/imp = "" + var/bled = "" + var/robot = "" + var/splint = "" + var/internal_bleeding = "" + var/severed_tendon = "" + var/lung_ruptured = "" + var/dislocated = "" + + dat += "" + + if(e.status & ORGAN_ARTERY_CUT) + internal_bleeding = "Arterial bleeding." + if(e.tendon_status() & TENDON_CUT) + severed_tendon = "Severed tendon." + if(istype(e, /obj/item/organ/external/chest) && occ["lung_ruptured"]) + lung_ruptured = "Lung ruptured." + if(e.status & ORGAN_SPLINTED) + splint = "Splinted." + if(e.is_dislocated()) + dislocated = "Dislocated." + if(e.status & ORGAN_BLEEDING) + bled = "Bleeding." + if(e.status & ORGAN_BROKEN) + AN = "[e.broken_description]." + if(e.status & ORGAN_ROBOT) + robot = "Prosthetic." + if(e.open) + open = "Open." + + var/infection = internal_bodyscanner.get_infection_level(e.germ_level) + if (infection != "") + infected = "[infection] infection" + if(e.rejecting) + infected += " (being rejected)" + + if (e.implants.len) + var/unknown_body = 0 + for(var/I in e.implants) + if(is_type_in_list(I,internal_bodyscanner.known_implants)) + imp += "[I] implanted:" + else + unknown_body++ + if(unknown_body) + imp += "Unknown body present:" + + if(!AN && !open && !infected & !imp) + AN = "None:" + if(!e.is_stump()) + dat += "" + else + dat += "" + dat += "" + + for(var/obj/item/organ/internal/i in occ["internal_organs"]) + + var/mech = "" + if(i.robotic == ROBOTIC_ASSISTED) + mech = "Assisted:" + if(i.robotic == ROBOTIC_MECHANICAL) + mech = "Mechanical:" + + var/infection = internal_bodyscanner.get_infection_level(i.germ_level) + if(infection == "") + infection = "No Infection" + else + infection = "[infection] infection" + if(i.rejecting) + infection += "(being rejected)" + + var/necrotic = "" + if(i.get_scarring_level() > 0.01) + necrotic += ", [i.get_scarring_results()]" + if(i.status & ORGAN_DEAD) + necrotic = ", necrotic and decaying" + + dat += "" + dat += "" + dat += "" + dat += "
OrganBurn SeverityPhysical TraumaOther Wounds
[e.name][e.burn_dam][get_severity(e.brute_dam, TRUE)][robot][bled][AN][splint][open][infected][imp][dislocated][internal_bleeding][severed_tendon][lung_ruptured][e.name]--Not [e.is_stump() ? "Found" : "Attached Completely"]
[i.name]N/A[internal_bodyscanner.get_internal_damage(i)][infection], [mech][necrotic]
" + + var/list/species_organs = occ["species_organs"] + for(var/organ_name in species_organs) + if(!locate(species_organs[organ_name]) in occ["internal_organs"]) + dat += text("No [organ_name] detected.
") + + if(occ["sdisabilities"] & BLIND) + dat += text("Cataracts detected.
") + if(occ["sdisabilities"] & NEARSIGHTED) + dat += text("Retinal misalignment detected.
") + return dat diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index f6083e39f77..cb71771495c 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -15,7 +15,7 @@ var/icon_screen = "generic" var/icon_scanline var/light_range_on = 2 - var/light_power_on = 1 + var/light_power_on = 1.3 var/overlay_layer var/is_holographic = TRUE var/icon_broken = "broken" @@ -63,7 +63,7 @@ set_light(0) return else - set_light(light_range_on, light_power_on) + set_light(light_range_on, light_power_on, COLOR_CYAN) icon_state = initial(icon_state) @@ -89,7 +89,7 @@ if(stat & NOPOWER) set_light(0) else - set_light(light_range_on, light_power_on) + set_light(light_range_on, light_power_on, COLOR_CYAN) /obj/machinery/computer/proc/set_broken() diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index a3a46b68259..835222946e3 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -236,9 +236,9 @@ update_icon() return -/obj/machinery/firealarm/proc/set_security_level(var/newlevel) - if(seclevel != newlevel) - seclevel = newlevel +/obj/machinery/firealarm/set_emergency_state(var/new_security_level) + if(seclevel != new_security_level) + seclevel = new_security_level update_icon() /obj/machinery/firealarm/Initialize(mapload, ndir = 0, building) diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 5f08692b093..4361fef870b 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -530,5 +530,10 @@ Class Procs: if((. = .(candidate))) return + /obj/machinery/proc/on_user_login(mob/M) return + +/obj/machinery/proc/set_emergency_state(var/new_security_level) + return + diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index 76c74099166..01ad60f0d3f 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -93,7 +93,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co cut_overlays() //reset overlays add_overlay(screen_overlays["newscaster-screen"]) - set_light(1.4, 1, COLOR_CYAN) + set_light(1.4, 1.3, COLOR_CYAN) if(!alert || !SSnews.wanted_issue) // since we're transparent I don't want overlay nonsense add_overlay(screen_overlays["newscaster-title"]) diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index 82ba7411c29..6d90fb9b6d2 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -135,8 +135,10 @@ Buildable meters else if(istype(make_from, /obj/machinery/atmospherics/unary/vent_scrubber)) src.pipe_type = PIPE_SCRUBBER else if(istype(make_from, /obj/machinery/atmospherics/binary/passive_gate/scrubbers)) + connect_types = CONNECT_TYPE_SCRUBBER src.pipe_type = PIPE_PASSIVE_GATE_SCRUBBER else if(istype(make_from, /obj/machinery/atmospherics/binary/passive_gate/supply)) + connect_types = CONNECT_TYPE_SUPPLY src.pipe_type = PIPE_PASSIVE_GATE_SUPPLY else if(istype(make_from, /obj/machinery/atmospherics/binary/passive_gate)) src.pipe_type = PIPE_PASSIVE_GATE diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index e1366ac89ae..c0bb4d0ba4d 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -154,6 +154,14 @@ else if(default_part_replacement(user, O)) return + if(istype(O, /obj/item/grab)) + var/obj/item/grab/grab = O + var/mob/living/L = grab.affecting + if(!L.isSynthetic()) + return + + move_ipc(grab.affecting) + qdel(O) ..() /obj/machinery/recharge_station/RefreshParts() @@ -256,6 +264,19 @@ occupant = null update_icon() +/obj/machinery/recharge_station/proc/move_ipc(var/mob/M) // For the grab/drag and drop + var/mob/living/R = M + usr.visible_message(SPAN_NOTICE("[usr] starts putting [R] into [src]."), SPAN_NOTICE("You start putting [R] into [src]."), range = 3) + if(do_mob(usr, R, 5 SECONDS)) + if(go_in(R)) + usr.visible_message(SPAN_NOTICE("After some effort, [usr] manages to get [R] into the recharging unit!")) + return 1 + else + to_chat(usr, SPAN_DANGER("Failed loading [R] into charger. Please ensure that [R]'s limbs are safely within the charger and has a power cell, and that the charger is functioning.")) + else + to_chat(usr, SPAN_DANGER("Cancelled loading [R] into the charger. You and [R] must stay still!")) + return + /obj/machinery/recharge_station/verb/move_eject() set category = "Object" set name = "Eject Recharger" @@ -277,7 +298,6 @@ return go_in(usr) - /obj/machinery/recharge_station/MouseDrop_T(var/atom/movable/C, mob/user) if (istype(C, /mob/living/silicon/robot)) var/mob/living/silicon/robot/R = C @@ -295,4 +315,21 @@ else to_chat(user, SPAN_DANGER("Cancelled loading [C] into the charger. You and [C] must stay still!")) return + + else if(isipc(C)) // IPCs don't take as long + var/mob/living/carbon/human/machine/R = C + if(!user.Adjacent(R) || !Adjacent(user)) + to_chat(user, SPAN_DANGER("You need to get closer if you want to put [C] into that charger!")) + return + + var/bucklestatus = R.bucklecheck(user) + if(!bucklestatus) + return + if(bucklestatus == 2) + var/obj/structure/LB = R.buckled_to + LB.user_unbuckle(user) + return + + user.face_atom(src) + move_ipc(R) return ..() diff --git a/code/game/machinery/requests_console.dm b/code/game/machinery/requests_console.dm index a7b5bc60098..60cbece7f1c 100644 --- a/code/game/machinery/requests_console.dm +++ b/code/game/machinery/requests_console.dm @@ -90,16 +90,16 @@ var/list/obj/machinery/requests_console/allConsoles = list() switch(newmessagepriority) if(0) add_overlay(screen_overlays["req_comp-idle"]) - set_light(1.4, 1, COLOR_CYAN) + set_light(1.4, 1.3, COLOR_CYAN) if(1) add_overlay(screen_overlays["req_comp-alert"]) - set_light(1.4, 1, COLOR_CYAN) + set_light(1.4, 1.3, COLOR_CYAN) if(2) add_overlay(screen_overlays["req_comp-redalert"]) - set_light(1.4, 1, COLOR_ORANGE) + set_light(1.4, 1.3, COLOR_ORANGE) if(3) add_overlay(screen_overlays["req_comp-yellowalert"]) - set_light(1.4, 1, COLOR_ORANGE) + set_light(1.4, 1.3, COLOR_ORANGE) add_overlay(screen_overlays["req_comp-scanline"]) diff --git a/code/game/machinery/turret_control.dm b/code/game/machinery/turret_control.dm index bbaeedf18fd..e54b105c242 100644 --- a/code/game/machinery/turret_control.dm +++ b/code/game/machinery/turret_control.dm @@ -63,7 +63,7 @@ A.turret_controls += src else control_area = null - + updateTurrets() if (!mapload) power_change() //Checks power and initial settings turretModes() @@ -201,7 +201,6 @@ else if(href_list["command"] == "check_wildlife") check_wildlife = value updateTurrets() - update_icon() SSvueui.check_uis_for_change(src) else if(href_list["turret_ref"]) var/obj/machinery/porta_turret/aTurret = locate(href_list["turret_ref"]) in (control_area.turrets) @@ -209,7 +208,6 @@ return . = aTurret.Topic(href, href_list) SSvueui.check_uis_for_change(src) - update_icon() /obj/machinery/turretid/proc/updateTurrets() var/datum/turret_checks/TC = getState() @@ -222,6 +220,8 @@ TC.enabled = 0 aTurret.setState(TC) + queue_icon_update() + /obj/machinery/turretid/proc/getState() var/datum/turret_checks/TC = new TC.enabled = enabled @@ -256,12 +256,10 @@ var/obj/machinery/porta_turret/aTurret = control_area.turrets[1] lethal = aTurret.lethal updateTurrets() - update_icon() /obj/machinery/turretid/power_change() ..() updateTurrets() - update_icon() /obj/machinery/turretid/update_icon() ..() diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 2b33878f280..60b1af7c3e0 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -127,7 +127,7 @@ var/datum/asset/spritesheet/vending/v_asset light_range = 2 - light_power = 1 + light_power = 1.3 /obj/machinery/vending/Initialize(mapload) . = ..() diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm index 84af8110334..3dcfd75a852 100644 --- a/code/game/objects/effects/decals/Cleanable/misc.dm +++ b/code/game/objects/effects/decals/Cleanable/misc.dm @@ -104,7 +104,7 @@ var/list/viruses = list() /obj/effect/decal/cleanable/vomit/Initialize() - ..() + . = ..() create_reagents(20, src) /obj/effect/decal/cleanable/tomato_smudge diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 308898fc8ca..15fecfd12f4 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -336,6 +336,7 @@ /obj/item/proc/dropped(var/mob/user) if(zoom) zoom(user) //binoculars, scope, etc + SEND_SIGNAL(src, COMSIG_ITEM_REMOVE, src) // Called whenever an object is moved around inside the mob's contents. // Linker proc: mob/proc/prepare_for_slotmove, which is referenced in proc/handle_item_insertion and obj/item/attack_hand. @@ -343,6 +344,7 @@ /obj/item/proc/on_slotmove(var/mob/user, slot) if(zoom) zoom(user) + SEND_SIGNAL(src, COMSIG_ITEM_REMOVE, src) // called just as an item is picked up (loc is not yet changed) /obj/item/proc/pickup(mob/user) diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm index f595ee7fde5..48f7c5cc949 100644 --- a/code/game/objects/items/devices/radio/intercom.dm +++ b/code/game/objects/items/devices/radio/intercom.dm @@ -153,7 +153,7 @@ else add_overlay(screen_overlays["intercom_screen"]) add_overlay(screen_overlays["intercom_scanline"]) - set_light(1.4, 1, COLOR_CYAN) + set_light(1.4, 1.3, COLOR_CYAN) if(broadcasting) add_overlay(screen_overlays["intercom_b"]) if(listening) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 662ca859364..294731b4802 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -667,7 +667,7 @@ BREATH ANALYZER add_fingerprint(user) /obj/item/device/advanced_healthanalyzer/proc/print_scan(var/mob/M, var/mob/living/user) - var/obj/item/paper/R = new(user.loc) + var/obj/item/paper/medscan/R = new(user.loc) R.color = "#eeffe8" R.set_content_unsafe("Scan ([M.name])", internal_bodyscanner.format_occupant_data(get_medical_data(M))) diff --git a/code/game/objects/items/glassjar.dm b/code/game/objects/items/glassjar.dm index 1911677236e..67adb1d44e0 100644 --- a/code/game/objects/items/glassjar.dm +++ b/code/game/objects/items/glassjar.dm @@ -214,11 +214,15 @@ /obj/item/glass_jar/gumball contains = JAR_GUMBALL + var/gumball_path = /obj/item/clothing/mask/chewable/candy/gum/gumball + +/obj/item/glass_jar/gumball/medical + gumball_path = /obj/item/clothing/mask/chewable/candy/gum/gumball/medical /obj/item/glass_jar/gumball/Initialize() ..() for(var/i = 1 to GUMBALL_MAX) - var/obj/item/clothing/mask/chewable/candy/gum/gumball/G = new(src) + var/obj/item/clothing/mask/chewable/candy/gum/gumball/G = new gumball_path(src) contained += G return INITIALIZE_HINT_LATELOAD @@ -226,13 +230,6 @@ /obj/item/glass_jar/gumball/LateInitialize() update_icon() -/obj/item/glass_jar/gumball/medical/Initialize() - for(var/i = 1 to GUMBALL_MAX) - var/obj/item/clothing/mask/chewable/candy/gum/gumball/medical/G = new(src) - contained += G - - return INITIALIZE_HINT_LATELOAD - #undef JAR_NOTHING #undef JAR_MONEY #undef JAR_ANIMAL diff --git a/code/game/objects/items/knitting.dm b/code/game/objects/items/knitting.dm index aa446ce2890..01ad357cb77 100644 --- a/code/game/objects/items/knitting.dm +++ b/code/game/objects/items/knitting.dm @@ -11,6 +11,29 @@ var/static/list/knitables = list(/obj/item/clothing/accessory/sweater, /obj/item/clothing/suit/storage/toggle/cardigan, /obj/item/clothing/suit/storage/toggle/cardigan/sweater, /obj/item/clothing/suit/storage/toggle/cardigan/argyle, /obj/item/clothing/accessory/sweatervest, /obj/item/clothing/accessory/sweaterturtleneck, /obj/item/clothing/gloves/fingerless/colour/knitted, /obj/item/clothing/gloves/knitted, /obj/item/clothing/accessory/bandanna/colorable/knitted, /obj/item/clothing/accessory/scarf) var/static/list/name2knit +/obj/item/knittingneedles/verb/remove_yarn() + set name = "Remove Yarn" + set category = "Object" + set src in usr + + if(use_check_and_message(usr)) + return + + if(!ball) + to_chat(usr, SPAN_WARNING("There is no yarn on \the [src]!")) + return + + if(working) + to_chat(usr, SPAN_WARNING("You can't remove \the [ball] while using \the [src]!")) + return + + var/mob/living/carbon/human/H = usr + + H.put_in_hands(ball) + ball = null + to_chat(usr, SPAN_NOTICE("You remove \the [ball] from \the [src].")) + update_icon() + /obj/item/knittingneedles/Destroy() if(ball) QDEL_NULL(ball) @@ -30,9 +53,15 @@ item_state = initial(item_state) if(ball) - add_overlay("[ball.icon_state]") + var/mutable_appearance/yarn_overlay = mutable_appearance(icon, "[ball.icon_state]") + if(ball.color) + yarn_overlay.color = ball.color + else + yarn_overlay.appearance_flags = RESET_COLOR + add_overlay(yarn_overlay) else cut_overlays() + update_held_icon() /obj/item/knittingneedles/attackby(obj/item/O, mob/user) if(istype(O, /obj/item/yarn)) @@ -62,6 +91,8 @@ var/image/radial_button = image(icon = initial(i.icon), icon_state = initial(i.icon_state)) options[initial(i.name)] = radial_button var/knit_name = show_radial_menu(user, user, options, radius = 42, tooltips = TRUE) + if(!knit_name) + return var/type_path = name2knit[knit_name] user.visible_message("[user] begins knitting something soft and cozy.") diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 72817c8c91e..403df8e9a66 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -213,8 +213,6 @@ update_icon() return 1 else - if(get_amount() < used) - return 0 for(var/i = 1 to charge_costs.len) var/datum/matter_synth/S = synths[i] if(!S.use_charge(charge_costs[i] * used)) // Doesn't need to be deleted diff --git a/code/game/objects/items/tajara.dm b/code/game/objects/items/tajara.dm index 1bc2cd2bbfb..ab16bec25f9 100644 --- a/code/game/objects/items/tajara.dm +++ b/code/game/objects/items/tajara.dm @@ -232,6 +232,12 @@ add_fingerprint(user) +/obj/item/flame/lighter/adhomai/AltClick(mob/user) + if(Adjacent(user) && !lit) + protection = !protection + playsound(src.loc, 'sound/weapons/blade_open.ogg', 50, 1) + update_icon() + /obj/item/stack/dice/tajara name = "adhomian dice" desc = "An adhomian dice made out of wood. Commonly used to play Suns and Moon." diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 4656ef1783c..dfd053e8a62 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -118,6 +118,7 @@ var/const/NO_EMAG_ACT = -50 //alt titles are handled a bit weirdly in order to unobtrusively integrate into existing ID system var/assignment = null //can be alt title or the actual job var/rank = null //actual job + var/employer_faction = null var/dorm = 0 // determines if this ID has claimed a dorm already var/datum/ntnet_user/chat_user @@ -150,9 +151,9 @@ var/const/NO_EMAG_ACT = -50 chat_user.username = chat_user.generateUsernameIdCard(src) /obj/item/card/id/proc/set_id_photo(var/mob/M) - front = getFlatIcon(M, SOUTH) + front = getFlatIcon(M, SOUTH, ignore_parent_dir = TRUE) front.Scale(128, 128) - side = getFlatIcon(M, WEST) + side = getFlatIcon(M, WEST, ignore_parent_dir = TRUE) side.Scale(128, 128) /mob/proc/set_id_info(var/obj/item/card/id/id_card) @@ -173,6 +174,7 @@ var/const/NO_EMAG_ACT = -50 id_card.citizenship = citizenship id_card.religion = SSrecords.get_religion_record_name(religion) id_card.mob = src + id_card.employer_faction = employer_faction /obj/item/card/id/proc/dat() var/dat = ("
") diff --git a/code/game/objects/items/weapons/cards_ids_syndicate.dm b/code/game/objects/items/weapons/cards_ids_syndicate.dm index 05feb5c5e80..f1136b6284c 100644 --- a/code/game/objects/items/weapons/cards_ids_syndicate.dm +++ b/code/game/objects/items/weapons/cards_ids_syndicate.dm @@ -67,6 +67,7 @@ entries[++entries.len] = list("name" = "Sex", "value" = sex) entries[++entries.len] = list("name" = "Citizenship", "value" = citizenship) entries[++entries.len] = list("name" = "Religion", "value" = religion) + entries[++entries.len] = list("name" = "Faction", "value" = employer_faction) entries[++entries.len] = list("name" = "Factory Reset", "value" = "Use With Care") data["electronic_warfare"] = electronic_warfare data["entries"] = entries @@ -229,6 +230,12 @@ src.religion = new_religion to_chat(user, SPAN_NOTICE("Religion changed to '[new_religion]'.")) . = 1 + if("Faction") + var/new_faction = sanitize(input(user,"Which faction would you like to put on this card?","Agent Card Faction", employer_faction) as null|text) + if(!isnull(new_faction) && CanUseTopic(user,state)) + src.employer_faction = new_faction + to_chat(user, SPAN_NOTICE("Faction changed to '[new_faction]'.")) + . = 1 if("Factory Reset") if(alert("This will factory reset the card, including access and owner. Continue?", "Factory Reset", "No", "Yes") == "Yes" && CanUseTopic(user, state)) age = initial(age) @@ -245,6 +252,7 @@ unset_registered_user() religion = initial(religion) sex = initial(sex) + employer_faction = initial(employer_faction) to_chat(user, "All information has been deleted from \the [src].") . = 1 diff --git a/code/game/objects/items/weapons/storage/wallets.dm b/code/game/objects/items/weapons/storage/wallets.dm index 8832c74d145..1c2aac1e68b 100644 --- a/code/game/objects/items/weapons/storage/wallets.dm +++ b/code/game/objects/items/weapons/storage/wallets.dm @@ -15,8 +15,10 @@ /obj/item/device/flashlight/pen, /obj/item/seeds, /obj/item/coin, + /obj/item/stack/dice, /obj/item/disk, /obj/item/implanter, + /obj/item/flame/lighter, /obj/item/flame/match, /obj/item/lipstick, /obj/item/haircomb, @@ -30,7 +32,8 @@ /obj/item/device/encryptionkey, /obj/item/fluff, /obj/item/storage/business_card_holder, - /obj/item/sample + /obj/item/sample, + /obj/item/key ) slot_flags = SLOT_ID diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index dde3e3aabbb..185ea3af7d7 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -25,7 +25,7 @@ var/mob/living/pulling /obj/structure/janitorialcart/full/Initialize() - ..() + . = ..() mybag = new /obj/item/storage/bag/trash(src) mymop = new /obj/item/mop(src) myspray = new /obj/item/reagent_containers/spray/cleaner(src) diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm index ed4ce7d3f6a..1ec719a5f06 100644 --- a/code/game/objects/structures/railing.dm +++ b/code/game/objects/structures/railing.dm @@ -187,6 +187,8 @@ update_icon() /obj/structure/railing/CheckExit(var/atom/movable/O, var/turf/target) + if(istype(O) && CanPass(O, target)) + return TRUE if(get_dir(O.loc, target) == dir) if(!density) return TRUE diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm index 792f40d4fdc..74a14ba9335 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm @@ -358,7 +358,7 @@ slowdown = 0 /obj/structure/bed/roller/Initialize() - ..() + . = ..() LAZYADD(can_buckle, /obj/structure/closet/body_bag) /obj/structure/bed/roller/Destroy() diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 854da925b7e..045b62357be 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -104,6 +104,7 @@ changing_turf = FALSE turfs -= src + remove_cleanables() cleanup_roof() if (ao_queued) @@ -524,3 +525,8 @@ var/const/enterloopsanity = 100 /turf/proc/is_floor() return FALSE + +/turf/proc/remove_cleanables() + for(var/obj/effect/O in src) + if(istype(O,/obj/effect/rune) || istype(O,/obj/effect/decal/cleanable)) + qdel(O) \ No newline at end of file diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index b7a0c50073e..f66813a7e82 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -178,6 +178,10 @@ listening_objects += src /obj/item/device/assembly_holder/Destroy() + if(a_left) + a_left.holder = null + if(a_right) + a_right.holder = null listening_objects -= src return ..() diff --git a/code/modules/background/defines.dm b/code/modules/background/defines.dm index bde03756f3b..ec9bf075758 100644 --- a/code/modules/background/defines.dm +++ b/code/modules/background/defines.dm @@ -55,6 +55,8 @@ #define RELIGION_PILOTDREAM "Pilot Dream" #define RELIGION_ETERNAL "The Eternal" +#define RELIGION_KSSHR "Ksshr" +#define RELIGION_SHRKH "Shrkh" //accent defines diff --git a/code/modules/background/religion/diona.dm b/code/modules/background/religion/diona.dm index 3c271e06054..652f6ce3153 100644 --- a/code/modules/background/religion/diona.dm +++ b/code/modules/background/religion/diona.dm @@ -8,3 +8,26 @@ eventually going supernova and expelling matter or essence across the cosmos." book_name = "book of the eternal" book_sprite = "eternal" + +/datum/religion/ksshr + name = RELIGION_KSSHR + description = "The Ksshr, also known as the Enlightened, is a religious sect on Xrim known for their complete rejection of The First Consciousness, instead of being an agnostic \ + sect that centers around working together to create a better future, as well as the advancement of technology and understanding how the universe works. The Ksshr faith is the \ + primary religion of Xrim, with most of its inhabitants considering themselves a part of the religion. The Jargon Federation does encourage practicing the faith amongst the \ + population so long as they continue to reject The First Consciousness, as well as stay away from the teachings of the Shrkh." + book_name = "ksshr codex" + book_sprite = "holybook" + +/datum/religion/shrkh + name = RELIGION_SHRKH + description = "The Shrkh, or 'Scorned' as they call themselves, continue to follow the age-old tradition of worshipping Glorsh-Omega. They believe that Glorsh-Omega planted them \ + on the planet intentionally, granting them a blissful haven via the use of technology. Once the prominent and only religion on the planet, Shrkh-ism was quickly displaced when \ + Skrell explorers crashlanded and their memories, thoughts, emotions, everything was consumed, and doubt was first seeded in the minds of all Dionae on Xrim. The premise \ + behind the religion itself is simple; revere, help sustain and maintain synthetic life. As synthetic life brought dionae into this haven, so too shall it be preserved. In the \ + minds of the Shrkh worshippers, the Skrell that brought Ksshr to the planet were misguided. To the Shrkh, the genophage was something that never happened, a myth made up by \ + the Federation to indoctrinate its population into its anti-synthetic and authoritarian beliefs. \ + \ + Note that due to their beliefs, those that are openly members of the faith are barred from command, machinist, and chaplain positions. They are also completely barred from \ + working for Zeng-Hu due to the megacorporations ties with the Federation." + book_name = "shrkh codex" + book_sprite = "holybook" diff --git a/code/modules/background/space_sectors/space_sector.dm b/code/modules/background/space_sectors/space_sector.dm index e204eef94c1..68046d789e2 100644 --- a/code/modules/background/space_sectors/space_sector.dm +++ b/code/modules/background/space_sectors/space_sector.dm @@ -2,7 +2,7 @@ var/name var/description var/list/possible_erts = list() - var/list/possible_exoplanets = list() + var/list/possible_exoplanets = list(/obj/effect/overmap/visitable/sector/exoplanet/snow, /obj/effect/overmap/visitable/sector/exoplanet/desert) var/list/cargo_price_coef = list("nt" = 1, "hpi" = 1, "zhu" = 1, "een" = 1, "get" = 1, "arz" = 1, "blm" = 1, "iac" = 1, "zsc" = 1, "vfc" = 1, "bis" = 1, "xmg" = 1, "npi" = 1) //how much the space sector afffects how expensive is ordering from that cargo supplier diff --git a/code/modules/client/preference_setup/loadout/loadout_factions.dm b/code/modules/client/preference_setup/loadout/loadout_factions.dm index 1d9a72c74fa..54dfab7f618 100644 --- a/code/modules/client/preference_setup/loadout/loadout_factions.dm +++ b/code/modules/client/preference_setup/loadout/loadout_factions.dm @@ -262,7 +262,7 @@ faction = "Hephaestus Industries" /datum/gear/faction/heph_passcard - display_name = "hephaestus burszia passcard" - path = /obj/item/clothing/accessory/badge/passcard/burszia + display_name = "hephaestus burzsia passcard" + path = /obj/item/clothing/accessory/badge/passcard/burzsia slot = slot_tie faction = "Hephaestus Industries" diff --git a/code/modules/client/preference_setup/loadout/loadout_uniform.dm b/code/modules/client/preference_setup/loadout/loadout_uniform.dm index 448964684f0..1219b746083 100644 --- a/code/modules/client/preference_setup/loadout/loadout_uniform.dm +++ b/code/modules/client/preference_setup/loadout/loadout_uniform.dm @@ -202,6 +202,7 @@ colorpants["striped pants"] = /obj/item/clothing/under/pants/striped colorpants["tailored jeans"] = /obj/item/clothing/under/pants/tailoredjeans colorpants["mustang jeans"] = /obj/item/clothing/under/pants/musthangcolour + colorpants["shorts"] = /obj/item/clothing/under/shorts/color gear_tweaks += new /datum/gear_tweak/path(colorpants) /datum/gear/uniform/turtleneck diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index ed6f0910b7c..c2c8d6a9c3c 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -31,7 +31,6 @@ var/move_trail = /obj/effect/decal/cleanable/blood/tracks/footprints - /obj/item/clothing/Initialize(var/mapload, var/material_key) . = ..(mapload) if(!material_key) @@ -292,6 +291,15 @@ siemens_coefficient = between(0, material.conductivity / 10, 10) slowdown = between(0, round(material.weight / 10, 0.1), 6) +/obj/item/clothing/proc/get_accessory(var/typepath) + if(istype(src, typepath)) + return src + if(LAZYLEN(accessories)) + var/accessory = locate(typepath) in accessories + if(accessory) + return accessory + return null + /////////////////////////////////////////////////////////////////////// // Ears: headsets, earmuffs and tiny objects /obj/item/clothing/ears @@ -388,7 +396,7 @@ /obj/item/clothing/gloves/get_mob_overlay(mob/living/carbon/human/H, mob_icon, mob_state, slot) var/image/I = ..() - if(blood_DNA) + if(blood_DNA && slot != slot_l_hand_str && slot != slot_r_hand_str) var/image/bloodsies = image(H.species.blood_mask, "bloodyhands") bloodsies.color = blood_color I.add_overlay(bloodsies) @@ -614,7 +622,7 @@ /obj/item/clothing/head/get_mob_overlay(mob/living/carbon/human/H, mob_icon, mob_state, slot) var/image/I = ..() - if(blood_DNA) + if(blood_DNA && slot != slot_l_hand_str && slot != slot_r_hand_str) var/image/bloodsies = image(H.species.blood_mask, icon_state = "helmetblood") bloodsies.color = blood_color bloodsies.appearance_flags = RESET_ALPHA @@ -690,7 +698,7 @@ /obj/item/clothing/mask/get_mob_overlay(mob/living/carbon/human/H, mob_icon, mob_state, slot) var/image/I = ..() - if(blood_DNA && has_blood_overlay) + if(blood_DNA && has_blood_overlay && slot != slot_l_hand_str && slot != slot_r_hand_str) var/image/bloodsies = image(H.species.blood_mask, "maskblood") bloodsies.color = blood_color bloodsies.appearance_flags = RESET_ALPHA @@ -851,7 +859,7 @@ /obj/item/clothing/shoes/get_mob_overlay(mob/living/carbon/human/H, mob_icon, mob_state, slot) var/image/I = ..() - if(blood_DNA) + if(blood_DNA && slot != slot_l_hand_str && slot != slot_r_hand_str) for(var/limb_tag in list(BP_L_FOOT, BP_R_FOOT)) var/obj/item/organ/external/E = H.get_organ(limb_tag) if(E && !E.is_stump()) @@ -888,6 +896,10 @@ /obj/item/clothing/shoes/clothing_class() return "shoes" +/obj/item/clothing/shoes/clean_blood() + . = ..() + track_footprint = 0 + /////////////////////////////////////////////////////////////////////// //Suit /obj/item/clothing/suit @@ -937,7 +949,7 @@ var/image/accessory_image = A.get_accessory_mob_overlay(H) I.add_overlay(accessory_image) - if(blood_DNA) + if(blood_DNA && slot != slot_l_hand_str && slot != slot_r_hand_str) var/image/bloodsies = image(icon = H.species.blood_mask, icon_state = "[blood_overlay_type]blood") bloodsies.color = blood_color I.add_overlay(bloodsies) @@ -1021,7 +1033,7 @@ var/image/accessory_image = A.get_accessory_mob_overlay(H) I.add_overlay(accessory_image) - if(blood_DNA) + if(blood_DNA && slot != slot_l_hand_str && slot != slot_r_hand_str) var/image/bloodsies = image(icon = H.species.blood_mask, icon_state = "uniformblood") bloodsies.color = blood_color I.add_overlay(bloodsies) diff --git a/code/modules/clothing/suits/hoodies.dm b/code/modules/clothing/suits/hoodies.dm index e4247e1ff52..4512f077813 100644 --- a/code/modules/clothing/suits/hoodies.dm +++ b/code/modules/clothing/suits/hoodies.dm @@ -1,51 +1,23 @@ //Hoods for winter coats and chaplain hoodie etc /obj/item/clothing/suit/storage/hooded - var/obj/item/clothing/head/winterhood/hood - var/hoodtype = null - var/suittoggled = FALSE var/opened = FALSE sprite_sheets = list( BODYTYPE_VAURCA_BULWARK = 'icons/mob/species/bulwark/hoodie.dmi' ) + var/hoodtype = /obj/item/clothing/head/winterhood /obj/item/clothing/suit/storage/hooded/Initialize() . = ..() - MakeHood() + new hoodtype(src) -/obj/item/clothing/suit/storage/hooded/Destroy() - QDEL_NULL(hood) - return ..() - -/obj/item/clothing/suit/storage/hooded/proc/MakeHood() - if(!hood) - hood = new hoodtype(src) - -/obj/item/clothing/suit/storage/hooded/equipped(mob/user, slot) - if(slot != slot_wear_suit) - RemoveHood() - ..() - -/obj/item/clothing/suit/storage/hooded/proc/RemoveHood() - suittoggled = FALSE - icon_state = "[initial(icon_state)][opened ? "_open" : ""][suittoggled ? "_t" : ""]" +/obj/item/clothing/suit/storage/hooded/update_icon(var/hooded = FALSE) + SEND_SIGNAL(src, COMSIG_ITEM_STATE_CHECK, args) + icon_state = "[initial(icon_state)][hooded ? "_t" : ""]" item_state = icon_state - // Hood got nuked. Probably because of RIGs or the like. - if(!hood) - MakeHood() - return - - if(ishuman(hood.loc)) - var/mob/living/carbon/H = hood.loc - H.unEquip(hood, 1) - H.update_inv_wear_suit() - hood.forceMove(src) - -/obj/item/clothing/suit/storage/hooded/dropped() - RemoveHood() - -/obj/item/clothing/suit/storage/hooded/on_slotmove() - RemoveHood() + . = ..() + if(usr) + usr.update_inv_wear_suit() /obj/item/clothing/suit/storage/hooded/verb/ToggleHood() set name = "Toggle Coat Hood" @@ -55,31 +27,7 @@ if(use_check_and_message(usr)) return 0 - if(!suittoggled) - if(ishuman(loc)) - var/mob/living/carbon/human/H = src.loc - if(H.wear_suit != src) - to_chat(H, "You must be wearing [src] to put up the hood!") - return - if(H.head) - to_chat(H, "You're already wearing something on your head!") - return - else - suittoggled = TRUE - icon_state = "[initial(icon_state)][opened ? "_open" : ""]" - //spawn appropriate hood. - CreateHood() - H.equip_to_slot_if_possible(hood,slot_head,0,0,1) - H.update_inv_wear_suit() - else - RemoveHood() - -/obj/item/clothing/suit/storage/hooded/proc/CreateHood() - hood.color = src.color - hood.icon_state = "[icon_state]_hood" - hood.item_state = "[icon_state]_hood" - icon_state = "[icon_state][suittoggled ? "_t" : ""]" - item_state = icon_state + SEND_SIGNAL(src, COMSIG_ITEM_UPDATE_STATE) update_icon() //hoodies and the like @@ -98,7 +46,6 @@ bio = ARMOR_BIO_MINOR ) siemens_coefficient = 0.75 - hoodtype = /obj/item/clothing/head/winterhood /obj/item/clothing/head/winterhood name = "winter hood" @@ -112,6 +59,75 @@ flags_inv = HIDEEARS | BLOCKHAIR | HIDEEARS min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE canremove = 0 + var/hooded = FALSE + +/obj/item/clothing/head/winterhood/Initialize(mapload, material_key) + . = ..() + if(isclothing(loc)) + RegisterSignal(loc, COMSIG_ITEM_REMOVE, .proc/RemoveHood) + RegisterSignal(loc, COMSIG_PARENT_QDELETING, /datum/.proc/Destroy) + RegisterSignal(loc, COMSIG_ITEM_STATE_CHECK, .proc/hooded) + RegisterSignal(loc, COMSIG_ITEM_UPDATE_STATE, .proc/change_hood) + RegisterSignal(loc, COMSIG_ITEM_ICON_UPDATE, /atom/.proc/update_icon) + color = loc.color + icon_state = "[loc.icon_state]_hood" + item_state = "[loc.icon_state]_hood" + +/obj/item/clothing/head/winterhood/update_icon(mob/user) + . = ..() + if(isclothing(loc)) + color = loc.color + icon_state = "[loc.icon_state]_hood" + item_state = "[loc.icon_state]_hood" + +/obj/item/clothing/head/winterhood/proc/hooded(var/hood, list/arguments) + arguments[1] = hooded + +/obj/item/clothing/head/winterhood/proc/change_hood(var/parent) + if(!hooded) + if(CheckSlot(parent)) + var/mob/living/carbon/human/H = get_human(parent) + hooded = TRUE + update_icon(H) + H.equip_to_slot_if_possible(src,slot_head,0,0,1) + usr.visible_message(SPAN_NOTICE("[usr] pulls up the hood on \the [src].")) + else + RemoveHood(parent) + usr.visible_message(SPAN_NOTICE("[usr] pulls down the hood on \the [src].")) + +/obj/item/clothing/head/winterhood/proc/RemoveHood(var/parent) + if(ishuman(loc)) + var/mob/living/carbon/H = loc + H.unEquip(src, 1) + forceMove(parent) + update_icon(H) + hooded = FALSE + +/obj/item/clothing/head/winterhood/proc/get_human(var/obj/parent) + var/mob/living/carbon/human/H + if(isclothing(parent.loc)) + if(ishuman(parent.loc.loc)) + H = parent.loc.loc + else if(ishuman(parent.loc)) + H = parent.loc + return H + +/obj/item/clothing/head/winterhood/proc/CheckSlot(var/parent) + var/mob/living/carbon/human/H = get_human(parent) + var/obj/base_item = loc + if(isclothing(loc.loc)) + base_item = loc.loc + + if(H) + if(H.wear_suit != base_item && H.w_uniform != base_item) + to_chat(H, SPAN_WARNING("You must be wearing [base_item] to put up the hood!")) + return FALSE + else if(H.head) + to_chat(H, SPAN_WARNING("You're already wearing something on your head!")) + return FALSE + else + return TRUE + return FALSE /obj/item/clothing/suit/storage/hooded/wintercoat/red name = "red winter coat" @@ -210,8 +226,6 @@ playsound(src, 'sound/items/zip.ogg', EQUIP_SOUND_VOLUME, TRUE) icon_state = "[initial(icon_state)][opened ? "_open" : ""]" item_state = icon_state - if(suittoggled) - CreateHood() //rebuild the hood with open/closed version update_icon() update_clothing_icon() usr.update_inv_head() diff --git a/code/modules/clothing/suits/jobs.dm b/code/modules/clothing/suits/jobs.dm index cae667e9272..f0a259be7a9 100644 --- a/code/modules/clothing/suits/jobs.dm +++ b/code/modules/clothing/suits/jobs.dm @@ -337,7 +337,7 @@ obj/item/clothing/suit/apron/overalls/blue item_state = "firstresponderjacket" /obj/item/clothing/suit/storage/toggle/fr_jacket/zeng - desc = "A dark green first responder jacket." + desc = "A first responder jacket in the classic white and purple of Zeng-Hu Pharmaceuticals." icon = 'icons/clothing/suits/coats/zeng_responder.dmi' contained_sprite = TRUE icon_state = "zengresponderjacket" diff --git a/code/modules/clothing/suits/xeno/tajara.dm b/code/modules/clothing/suits/xeno/tajara.dm index 63cdd9a12bb..de69293c22b 100644 --- a/code/modules/clothing/suits/xeno/tajara.dm +++ b/code/modules/clothing/suits/xeno/tajara.dm @@ -108,7 +108,6 @@ contained_sprite = TRUE flags_inv = HIDETAIL no_overheat = TRUE - hoodtype = /obj/item/clothing/head/winterhood desc_fluff = "Today the fashion that dominates Adhomai shares few similarities to the clothing of old Furs, linen, hemp, silk and other such fabrics were traded for \ synthetic versions, creating a massive boom in the nylon industry and textile industry in the cities. Jeans, overcoats, army uniforms, parade uniforms, flags, pants, shirts, ties, \ suspenders, overalls are now the fashion of every Tajara from Nal'Tor to Kaltir. The protests of \"Old fashion\" supporters can't stand against how undeniably effective and cheap \ diff --git a/code/modules/clothing/under/accessories/badges.dm b/code/modules/clothing/under/accessories/badges.dm index b550cd33ea4..643e21a05c9 100644 --- a/code/modules/clothing/under/accessories/badges.dm +++ b/code/modules/clothing/under/accessories/badges.dm @@ -451,9 +451,9 @@ icon_state = "passcard_techno" item_state = "passcard_techno" -/obj/item/clothing/accessory/badge/passcard/burszia - name = "burszian passcard" - desc = "A passcard issued to Burszian Hephaestus employees and- owned IPCs- working abroad." +/obj/item/clothing/accessory/badge/passcard/burzsia + name = "burzsian passcard" + desc = "A passcard issued to Burzsian Hephaestus employees and- owned IPCs- working abroad." desc_fluff = "Despite protest from the Himean representatives in government, Hephaestus Industries- citing their 'Home is where the Hephaestus is' initiative- is permitted to issue up to five thousand \ sponsored passcards to participating employees on a yearly basis, both to remind them of their home and to save on imported labor costs." icon_state = "passcard_burs" diff --git a/code/modules/clothing/under/accessories/holster.dm b/code/modules/clothing/under/accessories/holster.dm index 3f0bb3bcfeb..062e5a0cbea 100644 --- a/code/modules/clothing/under/accessories/holster.dm +++ b/code/modules/clothing/under/accessories/holster.dm @@ -116,14 +116,8 @@ if(usr.stat) return //can't we just use src here? - var/obj/item/clothing/accessory/holster/H = null - if(istype(src, /obj/item/clothing/accessory/holster)) - H = src - if(!H && istype(src, /obj/item/clothing)) - var/obj/item/clothing/S = src - if(LAZYLEN(S.accessories)) - H = locate() in S.accessories - if(!H && istype(src, /obj/item/clothing/suit/armor/tactical)) // This armor is a snowflake and has an integrated holster. + var/obj/item/clothing/accessory/holster/H = get_accessory(/obj/item/clothing/accessory/holster) + if(!H && istype(src, /obj/item/clothing/suit/armor/tactical)) // This armor is a snowflake and has an integrated holster. var/obj/item/clothing/suit/armor/tactical/tacticool = src H = tacticool.holster diff --git a/code/modules/clothing/under/shorts.dm b/code/modules/clothing/under/shorts.dm index 73ac4c3a048..03ea357d0d2 100644 --- a/code/modules/clothing/under/shorts.dm +++ b/code/modules/clothing/under/shorts.dm @@ -29,6 +29,10 @@ icon_state = "greyshorts" item_state = "greyshorts" +/obj/item/clothing/under/shorts/color + icon_state = "colshorts" + item_state = "colshorts" + /obj/item/clothing/under/shorts/scc name = "Stellar Corporate Conglomerate shorts" desc = "Shorts displaying the wearer's pride in their assigned corporate entity." diff --git a/code/modules/customitems/item_defines.dm b/code/modules/customitems/item_defines.dm index 5fb05b1c5bb..a8557a117e2 100644 --- a/code/modules/customitems/item_defines.dm +++ b/code/modules/customitems/item_defines.dm @@ -1354,11 +1354,14 @@ All custom items with worn sprites must follow the contained sprite system: http /obj/item/clothing/suit/storage/toggle/labcoat/fluff/mekesatis_labcoat //Biochemist Holocoat - Neith Mekesatis - vrow name = "biochemist holocoat" - desc = "An Eridani Corporate Federation holocoat modelled after a standard biochemist labcoat. It is extremely well cared for." + desc = "An extremely cared for and high quality labcoat that protects against minor chemical spills. The material feels like it could shimmer. There is a pharmaceutical logo displayed on the front." icon = 'icons/obj/custom_items/mekesatis_holocoat.dmi' icon_override = 'icons/obj/custom_items/mekesatis_holocoat.dmi' icon_state = "mekesatis_labcoat" item_state = "mekesatis_labcoat" + var/holo_name = "eridanian holocoat" + var/holo_desc = "An impeccably designed and cared for dark Eridani Corporate Federation holocoat modelled after a high quality labcoat. It has a prominent animated logo of the ECF on the back, \ + as well as a minor one across the front." var/changed = FALSE var/changing = FALSE @@ -1369,14 +1372,17 @@ All custom items with worn sprites must follow the contained sprite system: http return if(!(all_languages[LANGUAGE_TRADEBAND] in user.languages)) - to_chat(user, SPAN_NOTICE("On the inside of the coat there are various sentences in Tradeband printed in an elegant blue font.")) + to_chat(user, SPAN_NOTICE("On the inside of the coat there is a sentence in Tradeband printed in [changed ? "an elegant blue" : "a stylish red"] font.")) + return + + else if(!changed) + to_chat(user, SPAN_NOTICE("On the inside of the coat, the following words are printed in a stylish red font:
Exclusive Time Limited Holocoat Deal from July 30, 2459. \ + Now with graced with an animated Eridani Corporate Federation logo. For the Prosperity of all Eridanians - Delta HoloTextiles. Sector Alpha's best wears.")) return else - to_chat(user, SPAN_NOTICE("On the inside of the coat, the following words are printed in an elegant blue font:
Exclusive Time Limited Holocoat Deal from July 30, 2459. \ - Now with graced with an animated Eridani Corporate Federation logo. For the Prosperity of all Eridanians - Delta HoloTextiles. Sector Alpha's best \ - wears.
Every cloud has a silver lining, and you should be happy for yours. Congratulations on your \ - graduation. - Teremun A. M.")) + to_chat(user, SPAN_NOTICE("On the inside of the coat, the following words are printed in an elegant blue font:
Every cloud has a silver lining, \ + and you should be grateful for yours. Congratulations on your graduation. - Taiwo O. M.")) return /obj/item/clothing/suit/storage/toggle/labcoat/fluff/mekesatis_labcoat/toggle_open() @@ -1399,15 +1405,17 @@ All custom items with worn sprites must follow the contained sprite system: http if(changing) return - usr.visible_message("With a subtle gesture, [changed ? "the holocoat fades to a normal labcoat." : "the labcoat flickers in activity!"]") + usr.visible_message("With a subtle gesture, [changed ? "the holocoat fades to a normal labcoat." : "the labcoat shimmers in activity!"]") icon_state = "mekesatis_[changed ? "labcoat_r" : "holocoat_t"][opened ? "_open" : ""]" item_state = icon_state + name = "[changed ? initial(name) : holo_name]" + desc = "[changed ? initial(desc) : holo_desc]" flick("mekesatis_[changed ? "labcoat_r" : "holocoat_t"][opened ? "_open" : ""]", src) update_icon() usr.update_inv_wear_suit() changing = TRUE - addtimer(CALLBACK(src, .proc/finish_toggle, usr), 10 SECONDS) + addtimer(CALLBACK(src, .proc/finish_toggle, usr), 6 SECONDS) /obj/item/clothing/suit/storage/toggle/labcoat/fluff/mekesatis_labcoat/proc/finish_toggle(mob/user) changed = !changed @@ -2094,6 +2102,35 @@ All custom items with worn sprites must follow the contained sprite system: http var/desc2 = "A blue cloak with the symbol of the New Kingdom of Adhomai proudly displayed on the back.\nUpon closer examination it appears to be a patchwork of older textile and newer fabrics, with the inside of the cloak appearing to be colored differently." var/changed = FALSE + var/hoodtype = /obj/item/clothing/head/winterhood/fluff/kathira_hood + +/obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/Initialize() + . = ..() + new hoodtype(src) + +/obj/item/clothing/head/winterhood/fluff/kathira_hood + name = "handsewn hood" + desc = "A hood attached to a cloak." + icon = 'icons/obj/custom_items/kathira_cloak.dmi' + icon_override = 'icons/obj/custom_items/kathira_cloak.dmi' + icon_state = "idris_cloak_hood" + contained_sprite = TRUE + flags_inv = HIDEEARS | BLOCKHAIR | HIDEEARS + +/obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/update_icon(var/hooded = FALSE) + var/obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/K = get_accessory(/obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak) + K.icon_state = "[K.changed ? K.style : initial(K.icon_state)]" + SEND_SIGNAL(K, COMSIG_ITEM_STATE_CHECK, args) + K.item_state = "[K.icon_state][hooded ? "_up" : ""]" + K.name = "[K.changed ? K.name2 : initial(K.name)]" + K.desc = "[K.changed ? K.desc2 : initial(K.desc)]" + K.accessory_mob_overlay = null + . = ..() + SEND_SIGNAL(K, COMSIG_ITEM_ICON_UPDATE) + if(usr) + usr.update_inv_w_uniform() + usr.update_inv_wear_suit() + /obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/verb/change_cloak() set name = "Change Cloak" set category = "Object" @@ -2102,38 +2139,40 @@ All custom items with worn sprites must follow the contained sprite system: http if(use_check_and_message(usr)) return - var/obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/K = null - if(istype(src, /obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak)) - K = src - if(!K && isclothing(src)) - var/obj/item/clothing/S = src - if(LAZYLEN(S.accessories)) - K = locate() in S.accessories + var/obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/K = get_accessory(/obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak) if(!K) return usr.visible_message(SPAN_NOTICE("[usr] swiftly pulls \the [K] inside out, changing its appearance.")) - K.icon_state = "[K.changed ? initial(K.icon_state) : K.style]" - K.item_state = K.icon_state - K.name = "[K.changed ? initial(K.name) : K.name2]" - K.desc = "[K.changed ? initial(K.desc) : K.desc2]" - K.accessory_mob_overlay = null - K.changed = !K.changed K.update_icon() - usr.update_icon() - usr.update_inv_w_uniform() - usr.update_inv_wear_suit() + SEND_SIGNAL(K, COMSIG_ITEM_REMOVE, K) /obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/on_attached(obj/item/clothing/S, mob/user as mob) ..() has_suit.verbs += /obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/verb/change_cloak + has_suit.verbs += /obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/verb/change_hood /obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/on_removed(mob/user as mob) if(has_suit) has_suit.verbs -= /obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/verb/change_cloak + has_suit.verbs -= /obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/verb/change_hood ..() +/obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/verb/change_hood() + set name = "Toggle Hood" + set category = "Object" + set src in usr + + if(use_check_and_message(usr)) + return + + var/obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak/K = get_accessory(/obj/item/clothing/accessory/poncho/tajarancloak/fluff/kathira_cloak) + if(!K) + return + + SEND_SIGNAL(K, COMSIG_ITEM_UPDATE_STATE, K) + K.update_icon() /obj/item/clothing/suit/storage/toggle/fluff/leonid_chokha //Old Rebel's Chokha - Leonid Myagmar - lucaken name = "old rebel's chokha" @@ -2146,7 +2185,6 @@ All custom items with worn sprites must follow the contained sprite system: http item_state = "leonid_chokha" contained_sprite = TRUE - /obj/item/clothing/suit/storage/toggle/fluff/sezrak_coat //red Domelkoan Coat - Sezrak Han'san - captaingecko name = "red Domelkoan Coat" desc = "A warm coat made in Domelkos. This red coat is stuffed with yupmi fur and made out of reinforced cloth-like synthetic materials, both to keep the wearer warm in the cold winters of \ @@ -2178,11 +2216,68 @@ All custom items with worn sprites must follow the contained sprite system: http icon_state = "mrakiizar_book" item_state = "mrakiizar_book" contained_sprite = TRUE + var/open_state = "mrakiizar_book1" + var/list/open_states = list("mrakiizar_book1", "mrakiizar_book2", "mrakiizar_book3", "mrakiizar_book4") /obj/item/journal/fluff/mrakiizar_book/update_icon() - ..() - if(open) - icon_state = pick("mrakiizar_book1","mrakiizar_book2","mrakiizar_book3","mrakiizar_book4") + if(!open) + icon_state = "mrakiizar_book_closed" + else + icon_state = open_state + + if(closed_desc) + desc = open ? initial(desc) + closed_desc : initial(desc) + +/obj/item/journal/fluff/mrakiizar_book/attack_hand(mob/user) + if(open && user.a_intent == I_HURT) + if(!LAZYLEN(indices)) + to_chat(user, SPAN_WARNING("There aren't any indices to rip a paper out of!")) + return + + var/list/viable_indices = list() + for(var/index in indices) + var/obj/item/folder/embedded/E = indices[index] + if(!(locate(/obj/item/paper) in E)) + continue + viable_indices += index + + if(!length(viable_indices)) + to_chat(user, SPAN_WARNING("None of the indices in \the [src] contain a paper!")) + return + + var/selected_folder = input(user, "Select an index to rip a paper out of.", "Rip Index Select") as null|anything in viable_indices + if(isnull(selected_folder)) + return + + var/obj/item/folder/embedded/E = indices[selected_folder] + var/list/papers = list() + + for(var/obj/item/paper/P in E) + papers += P + + var/obj/item/paper/selected_paper = input(user, "Select a paper to rip out.", "Rip Paper Select") as null|anything in papers + if(isnull(selected_paper)) + return + + user.visible_message(SPAN_WARNING("[user] rips \the [selected_paper] out of \the [src]."), SPAN_NOTICE("You rip \the [selected_paper] out of \the [src]."), range = 5) + if(selected_paper.can_change_icon_state) + selected_paper.icon = icon + selected_paper.base_state = "torn" + selected_paper.update_icon() + user.put_in_hands(selected_paper) + E.handle_post_remove() + playsound(loc, 'sound/items/poster_ripped.ogg', 50, FALSE) + return + return ..() + +/obj/item/journal/fluff/mrakiizar_book/CtrlClick(mob/user) + if(open && Adjacent(user)) + open_state = next_in_list(icon_state, open_states) + user.visible_message("[user] flips a page in \the [src].", SPAN_NOTICE("You flip a page in \the [src]."), range = 3) + playsound(loc, 'sound/items/pickup/paper.ogg', 50, FALSE) + update_icon() + return + return ..() /obj/item/clothing/accessory/fluff/jaquelyn_necklace //Shrapnel Necklace - Jaquelyn Roberts - roostercat12 name = "shrapnel necklace" @@ -2195,7 +2290,6 @@ All custom items with worn sprites must follow the contained sprite system: http contained_sprite = TRUE slot_flags = SLOT_EARS | SLOT_TIE - /obj/item/clothing/under/fluff/quoro_robes //Black Robes - Quoro Wurri'Til - witchbells name = "black robes" desc = "Some simple black robes, made to wear under something more elaborate. The fabric has a distinct texture to it, giving you the impression of activewear or swimsuits." diff --git a/code/modules/detectivework/tools/sample_kits.dm b/code/modules/detectivework/tools/sample_kits.dm index 15ce1012a1c..3818dd65b7b 100644 --- a/code/modules/detectivework/tools/sample_kits.dm +++ b/code/modules/detectivework/tools/sample_kits.dm @@ -7,14 +7,14 @@ var/label_text = "" /obj/item/sample/Initialize(var/newloc, var/atom/supplied) - ..(newloc) + . = ..(newloc) if(supplied) copy_evidence(supplied) name = "[initial(name)] ([supplied.get_swab_name()])" LAZYADD(source, supplied.get_swab_name()) /obj/item/sample/print/Initialize(var/newloc, var/atom/supplied) - ..(newloc, supplied) + . = ..(newloc, supplied) if(LAZYLEN(evidence)) icon_state = "fingerprint1" @@ -68,12 +68,6 @@ else name = "[initial(name)] ([label_text])" -/obj/item/sample/Initialize(var/newloc, var/atom/supplied) - ..(newloc) - if(supplied) - copy_evidence(supplied) - name = "[initial(name)] ([supplied.get_swab_name()])" - LAZYADD(source, supplied.get_swab_name()) /atom/proc/get_swab_name() return "\the [initial(name)]" diff --git a/code/modules/heavy_vehicle/premade/_premade.dm b/code/modules/heavy_vehicle/premade/_premade.dm index 372eae95b4b..1addcd180c3 100644 --- a/code/modules/heavy_vehicle/premade/_premade.dm +++ b/code/modules/heavy_vehicle/premade/_premade.dm @@ -222,7 +222,7 @@ ..() /mob/living/heavy_vehicle/premade/random/boring/Initialize(mapload, var/obj/structure/heavy_vehicle_frame/source_frame) - ..(mapload, source_frame, using_boring_colours = TRUE) + . = ..(mapload, source_frame, using_boring_colours = TRUE) /mob/living/heavy_vehicle/premade/random/extra/Initialize(mapload, var/obj/structure/heavy_vehicle_frame/source_frame) - ..(mapload, source_frame, super_random = TRUE) + . = ..(mapload, source_frame, super_random = TRUE) diff --git a/code/modules/lighting/lighting_setup.dm b/code/modules/lighting/lighting_setup.dm new file mode 100644 index 00000000000..68311a32b2f --- /dev/null +++ b/code/modules/lighting/lighting_setup.dm @@ -0,0 +1,10 @@ +/proc/create_all_lighting_overlays() + for(var/zlevel = 1 to world.maxz) + create_lighting_overlays_zlevel(zlevel) + +/proc/create_lighting_overlays_zlevel(var/zlevel) + ASSERT(zlevel) + + for(var/turf/T in block(locate(1, 1, zlevel), locate(world.maxx, world.maxy, zlevel))) + if(T.dynamic_lighting) + T.lighting_build_overlay() diff --git a/code/modules/maps/helper_landmarks.dm b/code/modules/maps/helper_landmarks.dm new file mode 100644 index 00000000000..2bec33a763e --- /dev/null +++ b/code/modules/maps/helper_landmarks.dm @@ -0,0 +1,32 @@ +/obj/effect/landmark/map_load_mark + name = "map loader landmark" + var/list/templates //list of template types to pick from + +//Clears walls +/obj/effect/landmark/clear + name = "clear turf" + icon = 'icons/effects/landmarks.dmi' + icon_state = "clear" + delete_me = TRUE + +/obj/effect/landmark/clear/Initialize() + var/turf/simulated/wall/W = get_turf(src) + if(istype(W)) + W.dismantle_wall(TRUE, TRUE) + var/turf/simulated/mineral/M = W + if(istype(M)) + M.GetDrilled() + . = ..() + +//Applies fire act to the turf +/obj/effect/landmark/scorcher + name = "fire" + icon = 'icons/effects/landmarks.dmi' + icon_state = "fire" + var/temp = T0C + 3000 + +/obj/effect/landmark/scorcher/Initialize() + var/turf/simulated/T = get_turf(src) + if(istype(T)) + T.fire_act(temp) + . = ..() \ No newline at end of file diff --git a/code/modules/maps/map_template.dm b/code/modules/maps/map_template.dm index 81b2357aca3..381cb1b312a 100644 --- a/code/modules/maps/map_template.dm +++ b/code/modules/maps/map_template.dm @@ -21,52 +21,113 @@ name = rename /datum/map_template/proc/preload_size(path) - var/bounds = maploader.load_map(file(path), 1, 1, 1, cropMap=FALSE, measureOnly=TRUE) - if(bounds) - width = bounds[MAP_MAXX] // Assumes all templates are rectangular, have a single Z level, and begin at 1,1,1 - height = bounds[MAP_MAXY] + var/list/bounds = list(1.#INF, 1.#INF, 1.#INF, -1.#INF, -1.#INF, -1.#INF) + var/z_offset = 1 // needed to calculate z-bounds correctly + var/datum/map_load_metadata/M = maploader.load_map(file(path), 1, 1, z_offset, cropMap=FALSE, measureOnly=TRUE) + if(M) + bounds = extend_bounds_if_needed(bounds, M.bounds) + z_offset++ + else + return FALSE + width = bounds[MAP_MAXX] - bounds[MAP_MINX] + 1 + height = bounds[MAP_MAXY] - bounds[MAP_MINX] + 1 return bounds -/datum/map_template/proc/initTemplateBounds(var/list/bounds) - var/list/obj/structure/cable/cables = list() - var/list/atom/atoms = list() +/datum/map_template/proc/load_new_z(var/no_changeturf = TRUE) + var/x = round((world.maxx - width)/2) + var/y = round((world.maxy - height)/2) + var/initial_z = world.maxz + 1 - for(var/L in block(locate(bounds[MAP_MINX], bounds[MAP_MINY], bounds[MAP_MINZ]), - locate(bounds[MAP_MAXX], bounds[MAP_MAXY], bounds[MAP_MAXZ]))) + if (x < 1) x = 1 + if (y < 1) y = 1 + var/list/bounds = list(1.#INF, 1.#INF, 1.#INF, -1.#INF, -1.#INF, -1.#INF) + var/list/atoms_to_initialise = list() + var/shuttle_state = pre_init_shuttles() - var/turf/B = L - if (!B.initialized) - atoms += B - - if (TURF_IS_DYNAMICALLY_LIT_UNSAFE(B) && !B.lighting_overlay) - new /atom/movable/lighting_overlay(B) - - for(var/thing in B) - if(istype(thing, /obj/structure/cable)) - cables += thing - - var/atom/movable/AM = thing - if (!AM.initialized) - atoms += AM - - SSatoms.InitializeAtoms(atoms) - SSmachinery.setup_template_powernets(cables) - -/datum/map_template/proc/load_new_z() - var/x = round(world.maxx / 2) - var/y = round(world.maxy / 2) - - var/list/bounds = maploader.load_map(file(mappath), x, y, no_changeturf = TRUE) - if(!bounds) + var/datum/map_load_metadata/M = maploader.load_map(file(mappath), x, y, no_changeturf = no_changeturf) + if (M) + bounds = extend_bounds_if_needed(bounds, M.bounds) + atoms_to_initialise += M.atoms_to_initialise + else return FALSE + for (var/z_index = bounds[MAP_MINZ]; z_index <= bounds[MAP_MAXZ]; z_index++) + if (accessibility_weight) + current_map.accessible_z_levels[num2text(z_index)] = accessibility_weight + if (base_turf_for_zs) + current_map.base_turf_by_z[num2text(z_index)] = base_turf_for_zs + current_map.player_levels |= z_index + smooth_zlevel(world.maxz) resort_all_areas() //initialize things that are normally initialized after map load - initTemplateBounds(bounds) + init_atoms(atoms_to_initialise) + init_shuttles(shuttle_state) + after_load(initial_z) + for(var/light_z = initial_z to world.maxz) + create_lighting_overlays_zlevel(light_z) log_game("Z-level [name] loaded at [x], [y], [world.maxz]") + loaded++ + + return locate(world.maxx/2, world.maxy/2, world.maxz) + +/datum/map_template/proc/pre_init_shuttles() + . = SSshuttle.block_queue + SSshuttle.block_queue = TRUE + +/datum/map_template/proc/init_shuttles(var/pre_init_state) + for (var/shuttle_type in shuttles_to_initialise) + LAZYADD(SSshuttle.shuttles_to_initialize, shuttle_type) // queue up for init. + SSshuttle.block_queue = pre_init_state + SSshuttle.clear_init_queue() // We will flush the queue unless there were other blockers, in which case they will do it. + +/datum/map_template/proc/init_atoms(var/list/atoms) + if (SSatoms.initialized == INITIALIZATION_INSSATOMS) + return // let proper initialisation handle it later + + var/list/turf/turfs = list() + var/list/obj/machinery/atmospherics/atmos_machines = list() + var/list/obj/machinery/machines = list() + var/list/obj/structure/cable/cables = list() + + for(var/atom/A in atoms) + if(istype(A, /turf)) + turfs += A + if(istype(A, /obj/structure/cable)) + cables += A + if(istype(A, /obj/machinery/atmospherics)) + atmos_machines += A + if(istype(A, /obj/machinery)) + machines += A + if(istype(A,/obj/effect/landmark/map_load_mark)) + LAZYADD(subtemplates_to_spawn, A) + + var/notsuspended + if(!SSmachinery.suspended) + SSmachinery.suspend() + notsuspended = TRUE + + SSatoms.InitializeAtoms() // The atoms should have been getting queued there. This flushes the queue. + + SSmachinery.setup_template_powernets(cables) + SSmachinery.setup_atmos_machinery(atmos_machines) + if(notsuspended) + SSmachinery.wake() + + for (var/i in machines) + var/obj/machinery/machine = i + machine.power_change() + + for (var/i in turfs) + var/turf/T = i + T.post_change() + if(template_flags & TEMPLATE_FLAG_NO_RUINS) + T.flags |= TURF_NORUINS + if(istype(T,/turf/simulated)) + var/turf/simulated/sim = T + sim.update_air_properties() /datum/map_template/proc/load(turf/T, centered = FALSE) if(centered) @@ -78,12 +139,18 @@ if(T.y + height > world.maxy) return - var/list/bounds = maploader.load_map(file(mappath), T.x, T.y, T.z, cropMap=TRUE, no_changeturf = FALSE) - if(!bounds) - return + var/list/atoms_to_initialise = list() + var/shuttle_state = pre_init_shuttles() + var/datum/map_load_metadata/M = maploader.load_map(file(mappath), T.x, T.y, T.z, cropMap=TRUE, no_changeturf = FALSE) + if (M) + atoms_to_initialise += M.atoms_to_initialise + else + return FALSE + //initialize things that are normally initialized after map load - initTemplateBounds(bounds) + init_atoms(atoms_to_initialise) + init_shuttles(shuttle_state) log_game("[name] loaded at [T.x], [T.y], [T.z]") return TRUE @@ -95,3 +162,21 @@ if(corner) placement = corner return block(placement, locate(placement.x + width-1, placement.y + height-1, placement.z)) + +/datum/map_template/proc/extend_bounds_if_needed(var/list/existing_bounds, var/list/new_bounds) + var/list/bounds_to_combine = existing_bounds.Copy() + for (var/min_bound in list(MAP_MINX, MAP_MINY, MAP_MINZ)) + bounds_to_combine[min_bound] = min(existing_bounds[min_bound], new_bounds[min_bound]) + for (var/max_bound in list(MAP_MAXX, MAP_MAXY, MAP_MAXZ)) + bounds_to_combine[max_bound] = max(existing_bounds[max_bound], new_bounds[max_bound]) + return bounds_to_combine + +/datum/map_template/proc/after_load(z) + for(var/obj/effect/landmark/map_load_mark/mark in subtemplates_to_spawn) + subtemplates_to_spawn -= mark + if(LAZYLEN(mark.templates)) + var/template = pick(mark.templates) + var/datum/map_template/M = new template() + M.load(get_turf(mark), TRUE) + qdel(mark) + LAZYCLEARLIST(subtemplates_to_spawn) \ No newline at end of file diff --git a/code/modules/maps/planet_types/desert.dm b/code/modules/maps/planet_types/desert.dm index a5bdab00cc5..4f0110de836 100644 --- a/code/modules/maps/planet_types/desert.dm +++ b/code/modules/maps/planet_types/desert.dm @@ -42,8 +42,7 @@ smoothing_iterations = 4 land_type = /turf/simulated/floor/exoplanet/desert - flora_prob = 5 - flora_diversity = 4 + flora_prob = 0 fauna_types = list(/mob/living/simple_animal/thinbug, /mob/living/simple_animal/tindalos) /datum/random_map/noise/exoplanet/desert/get_additional_spawns(var/value, var/turf/T) @@ -52,7 +51,6 @@ return var/v = noise2value(value) if(v > 6) - T.icon_state = "desert[v-1]" if(prob(10)) new/obj/structure/quicksand(T) diff --git a/code/modules/maps/reader.dm b/code/modules/maps/reader.dm index c36fd070540..f5a0eb37266 100644 --- a/code/modules/maps/reader.dm +++ b/code/modules/maps/reader.dm @@ -6,6 +6,10 @@ var/global/use_preloader = FALSE var/global/dmm_suite/preloader/_preloader = new +/datum/map_load_metadata + var/bounds + var/list/atoms_to_initialise + /dmm_suite // /"([a-zA-Z]+)" = \(((?:.|\n)*?)\)\n(?!\t)|\((\d+),(\d+),(\d+)\) = \{"([a-zA-Z\n]*)"\}/g var/static/regex/dmmRegex = new/regex({""(\[a-zA-Z]+)" = \\(((?:.|\n)*?)\\)\n(?!\t)|\\((\\d+),(\\d+),(\\d+)\\) = \\{"(\[a-zA-Z\n]*)"\\}"}, "g") @@ -60,6 +64,7 @@ var/global/dmm_suite/preloader/_preloader = new var/key_len = 0 var/stored_index = 1 + var/list/atoms_to_initialise = list() while(dmmRegex.Find(tfile, stored_index)) stored_index = dmmRegex.next @@ -156,7 +161,9 @@ var/global/dmm_suite/preloader/_preloader = new if(!no_afterchange || (model_key != space_key)) if(!grid_models[model_key]) throw EXCEPTION("Undefined model key in DMM.") - parse_grid(grid_models[model_key], model_key, xcrd, ycrd, zcrd, no_changeturf || zexpansion) + var/datum/grid_load_metadata/M = parse_grid(grid_models[model_key], model_key, xcrd, ycrd, zcrd, no_changeturf || zexpansion) + if (M) + atoms_to_initialise += M.atoms_to_initialise #ifdef TESTING else ++turfsSkipped @@ -179,7 +186,15 @@ var/global/dmm_suite/preloader/_preloader = new var/turf/T = t //we do this after we load everything in. if we don't; we'll have weird atmos bugs regarding atmos adjacent turfs T.post_change(TRUE) - return bounds + var/datum/map_load_metadata/M = new + M.bounds = bounds + M.atoms_to_initialise = atoms_to_initialise + return M + +/datum/grid_load_metadata + var/list/atoms_to_initialise + var/list/atoms_to_delete + /** * Fill a given tile with its area/turf/objects/mobs @@ -308,23 +323,35 @@ var/global/dmm_suite/preloader/_preloader = new //turn off base new Initialization until the whole thing is loaded SSatoms.map_loader_begin() + //since we've switched off autoinitialisation, record atoms to initialise later + var/list/atoms_to_initialise = list() + //instanciate the first /turf var/turf/T if(members[first_turf_index] != /turf/template_noop) T = instance_atom(members[first_turf_index],members_attributes[first_turf_index],crds,no_changeturf) + atoms_to_initialise += T if(T) + //if others /turf are presents, simulates the underlays piling effect index = first_turf_index + 1 while(index <= members.len - 1) // Last item is an /area - crash_with("Tried to load additional turf at [model_key].") + var/underlay = T.appearance + T = instance_atom(members[index],members_attributes[index],crds,no_changeturf)//instance new turf + T.underlays += underlay index++ + atoms_to_initialise += T //finally instance all remainings objects/mobs for(index in 1 to first_turf_index-1) - instance_atom(members[index],members_attributes[index],crds,no_changeturf) + atoms_to_initialise += instance_atom(members[index],members_attributes[index],crds,no_changeturf) //Restore initialization to the previous value SSatoms.map_loader_stop() + var/datum/grid_load_metadata/M = new + M.atoms_to_initialise = atoms_to_initialise + return M + //////////////// //Helpers procs //////////////// diff --git a/code/modules/maps/ruins.dm b/code/modules/maps/ruins.dm index 9846281fa55..35ec64a611c 100644 --- a/code/modules/maps/ruins.dm +++ b/code/modules/maps/ruins.dm @@ -18,7 +18,7 @@ var/list/banned_ruin_ids = list() for(var/datum/map_template/ruin/ruin in potentialRuins) if (ruin.id in banned_ruin_ids) continue - if(!(SSatlas.current_sector.name in ruin.sectors) && !length(ruin.sectors)) + if(!(SSatlas.current_sector.name in ruin.sectors)) continue available[ruin] = ruin.spawn_weight @@ -27,7 +27,7 @@ var/list/banned_ruin_ids = list() while (remaining > 0 && length(available)) var/datum/map_template/ruin/ruin = pickweight(available) - if (ruin.cost > budget) + if (ruin.spawn_cost > budget) available -= ruin continue @@ -52,12 +52,12 @@ var/list/banned_ruin_ids = list() if (!valid) continue - log_admin("Ruin \"[ruin.name]\" placed at ([choice.x], [choice.y], [choice.z])") + log_admin("Ruin \"[ruin.name]\" placed at ([choice.x], [choice.y], [choice.z])!") load_ruin(choice, ruin) selected += ruin - if (ruin.cost > 0) - remaining -= ruin.cost + if (ruin.spawn_cost > 0) + remaining -= ruin.spawn_cost if (!(ruin.template_flags & TEMPLATE_FLAG_ALLOW_DUPLICATES)) banned_ruin_ids += ruin.id available -= ruin @@ -78,7 +78,7 @@ var/list/banned_ruin_ids = list() var/turf/T = i for(var/mob/living/simple_animal/monster in T) qdel(monster) - template.load(central_turf,centered = TRUE) + template.load(central_turf, TRUE) var/datum/map_template/ruin = template if(istype(ruin)) new /obj/effect/landmark/ruin(central_turf, ruin) diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 9106b17a498..d52df23d5e9 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -446,7 +446,7 @@ anchored = TRUE /obj/item/stack/flag/red/planted/Initialize() - ..() + . = ..() base_state = "redflag" set_light(2) diff --git a/code/modules/mob/abstract/freelook/chunk.dm b/code/modules/mob/abstract/freelook/chunk.dm index 011e7cbdda7..3821895a8e1 100644 --- a/code/modules/mob/abstract/freelook/chunk.dm +++ b/code/modules/mob/abstract/freelook/chunk.dm @@ -24,6 +24,7 @@ if(!obfuscation) obfuscation = image(icon, T, icon_state) obfuscation.layer = OBFUSCATION_LAYER + obfuscation.plane = PLANE_DEFAULT if(!obfuscation_underlay) // Creating a new icon of a fairly common icon state, adding some random color to prevent address searching, and hoping being static kills memory locality var/turf/floor = /turf/simulated/floor/tiled diff --git a/code/modules/mob/abstract/new_player/menu.dm b/code/modules/mob/abstract/new_player/menu.dm index 5564feb3a4a..2a79ec03958 100644 --- a/code/modules/mob/abstract/new_player/menu.dm +++ b/code/modules/mob/abstract/new_player/menu.dm @@ -271,7 +271,7 @@ announce_ghost_joinleave(src) var/mob/living/carbon/human/dummy/mannequin/mannequin = new client.prefs.dress_preview_mob(mannequin) - observer.appearance = mannequin + observer.appearance = mannequin.appearance observer.appearance_flags = KEEP_TOGETHER observer.alpha = 127 observer.layer = initial(observer.layer) diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm index 9690a5ac945..647b85ab148 100644 --- a/code/modules/mob/language/language.dm +++ b/code/modules/mob/language/language.dm @@ -12,7 +12,7 @@ var/list/ask_verb = list("asks") // Used when sentence ends in a ? var/list/exclaim_verb = list("exclaims") // Used when sentence ends in a ! var/list/shout_verb = list("shouts", "yells", "screams") //Used when a sentence ends in !! - var/list/whisper_verb = list("says quietly", "says softly", "whispers") // Optional. When not specified speech_verb + quietly/softly is used instead. + var/list/whisper_verb = null // Optional. When not specified speech_verb + quietly/softly is used instead. var/list/signlang_verb = list("signs") // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags var/list/sing_verb = list("sings") var/list/sign_adv_length = list(" briefly", " a short message", " a message", " a lengthy message", " a very lengthy message") // 5 messages changing depending on the length of the signed language. A space should be added before the sentence as shown diff --git a/code/modules/mob/living/carbon/alien/diona/progression.dm b/code/modules/mob/living/carbon/alien/diona/progression.dm index 20f830ab581..04b95fcd13d 100644 --- a/code/modules/mob/living/carbon/alien/diona/progression.dm +++ b/code/modules/mob/living/carbon/alien/diona/progression.dm @@ -1,5 +1,5 @@ /mob/living/carbon/alien/diona/confirm_evolution() - var/response = alert(src, "A worker gestalt is a large, slow, and durable humanoid form. You will lose the ability to ventcrawl and devour animals, but you will gain hand-like tendrils and the ability to wear things. You have enough biomass, are you certain you're ready to form a new gestalt?", "Confirm Gestalt", "Growth!", "Patience...") + var/response = alert(src, "Are you sure you wish to grow into a gestalt? Instead of being an individual nymph you'll become a group of them, for formed together to work as a more humanoid entity. As a gestalt you'll have hands and the ability to do most actions humans can such as opening doors and using tools, but you'll be unable to ventcrawl. If you've not already done so it's highly suggested you read over some of the dionae wiki to get a better understanding of the species before advancing further.", "Confirm Gestalt", "Growth!", "Patience...") if(response != "Growth!") return @@ -89,4 +89,4 @@ to_chat(src, SPAN_WARNING("You didn't have enough biomass to grow your [O.name]!")) O.droplimb(1, DROPLIMB_EDGE) qdel(O) - limbs_to_remove -= 1 \ No newline at end of file + limbs_to_remove -= 1 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index b2692cf7fa1..b62a6ed8ade 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1295,6 +1295,7 @@ if(clean_feet && !shoes) footprint_color = null feet_blood_DNA = null + track_footprint = 0 update_inv_shoes(1) if(blood_color) diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index b4ab24eb1f1..9247ce18d79 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -161,7 +161,7 @@ return headsets[headsets[1]] return null -/mob/living/carbon/human/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name, successful_radio, whisper) +/mob/living/carbon/human/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name, successful_radio, whisper, var/is_singing = FALSE) if(!whisper && (paralysis || InStasis())) whisper(message, speaking) return TRUE @@ -218,12 +218,12 @@ if(R.talk_into(src,message,null,verb,speaking)) successful_radio += R if("whisper") - whisper(message, speaking) + whisper(message, speaking, is_singing) return TRUE else if(message_mode) var/obj/item/device/radio/R = get_radio() if(R) - used_radios += l_ear + used_radios += R if(R.talk_into(src, message, message_mode, verb, speaking)) successful_radio += R diff --git a/code/modules/mob/living/carbon/human/species/station/diona/diona.dm b/code/modules/mob/living/carbon/human/species/station/diona/diona.dm index 3d130c82d5f..3d00104fa5b 100644 --- a/code/modules/mob/living/carbon/human/species/station/diona/diona.dm +++ b/code/modules/mob/living/carbon/human/species/station/diona/diona.dm @@ -111,7 +111,7 @@ max_hydration_factor = -1 allowed_citizenships = list(CITIZENSHIP_BIESEL, CITIZENSHIP_JARGON, CITIZENSHIP_SOL, CITIZENSHIP_COALITION, CITIZENSHIP_DOMINIA, CITIZENSHIP_IZWESKI, CITIZENSHIP_EUM, CITIZENSHIP_NONE) - allowed_religions = list(RELIGION_QEBLAK, RELIGION_WEISHII, RELIGION_MOROZ, RELIGION_THAKH, RELIGION_SKAKH, RELIGION_ETERNAL, RELIGION_NONE, RELIGION_OTHER) + allowed_religions = list(RELIGION_QEBLAK, RELIGION_WEISHII, RELIGION_MOROZ, RELIGION_THAKH, RELIGION_SKAKH, RELIGION_ETERNAL, RELIGION_KSSHR, RELIGION_SHRKH, RELIGION_NONE, RELIGION_OTHER) allowed_accents = list(ACCENT_ROOTSONG, ACCENT_VOIDSONG) default_accent = ACCENT_ROOTSONG diff --git a/code/modules/mob/living/carbon/human/species/station/human/human_subspecies.dm b/code/modules/mob/living/carbon/human/species/station/human/human_subspecies.dm index c884bbf29e5..b7457c28ed0 100644 --- a/code/modules/mob/living/carbon/human/species/station/human/human_subspecies.dm +++ b/code/modules/mob/living/carbon/human/species/station/human/human_subspecies.dm @@ -21,7 +21,12 @@ hazard_low_pressure = 10 examine_color = "#C2AE95" - allowed_accents = list(ACCENT_SCARAB, ACCENT_CETI, ACCENT_GIBSON, ACCENT_SOL, ACCENT_MARTIAN, ACCENT_JUPITER, ACCENT_COC, ACCENT_ELYRA, ACCENT_PERSEPOLIS, ACCENT_MEDINA, ACCENT_AEMAQ, ACCENT_NEWSUEZ, ACCENT_DAMASCUS, ACCENT_ERIDANI, ACCENT_ERIDANIREINSTATED, ACCENT_HIMEO, ACCENT_ERIDANIDREG, ACCENT_DOMINIA_HIGH, ACCENT_DOMINIA_VULGAR, ACCENT_NCF, ACCENT_ASSUNZIONE, ACCENT_VALKYRIE) + +/datum/species/human/offworlder/New() + var/list/offworlder_accents = list(ACCENT_SCARAB) + var/list/disallowed_accents = list(ACCENT_SILVERSUN_EXPATRIATE, ACCENT_SILVERSUN_ORIGINAL, ACCENT_PLUTO, ACCENT_EUROPA, ACCENT_VENUS, ACCENT_VENUSJIN, ACCENT_GADPATHUR, ACCENT_PHONG, ACCENT_VYSOKA, ACCENT_FISANDUH, ACCENT_MICTLAN, ACCENT_KONYAN, ACCENT_VISEGRAD) + allowed_accents = offworlder_accents + allowed_accents - disallowed_accents + ..() /datum/species/human/offworlder/equip_later_gear(var/mob/living/carbon/human/H) if(istype(H.get_equipped_item(slot_back), /obj/item/storage/backpack) && H.equip_to_slot_or_del(new /obj/item/storage/pill_bottle/rmt(H.back), slot_in_backpack)) diff --git a/code/modules/mob/living/carbon/human/species/station/vaurca/vaurca_subspecies.dm b/code/modules/mob/living/carbon/human/species/station/vaurca/vaurca_subspecies.dm index 02aec4845e7..117e37589ce 100644 --- a/code/modules/mob/living/carbon/human/species/station/vaurca/vaurca_subspecies.dm +++ b/code/modules/mob/living/carbon/human/species/station/vaurca/vaurca_subspecies.dm @@ -211,7 +211,7 @@ eyes_icons = 'icons/mob/human_face/eyes48x48.dmi' eyes = "bulwark_eyes" - slowdown = 6 + slowdown = 2 unarmed_types = list(/datum/unarmed_attack/claws/vaurca_bulwark) @@ -240,6 +240,7 @@ Bulwarks are much larger and have significantly thicker carapaces than most Vaur heat_level_3 = 800 //Default 1000 sprint_speed_factor = 1.4 + stamina = 50 /datum/species/bug/type_e/New() ..() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 27ecece7d59..2b411ed85b6 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -10,29 +10,16 @@ //mob verbs are faster than object verbs. See above. var/mob/living/next_point_time = 0 -/mob/living/pointed(atom/movable/A as mob|obj|turf in view()) - if(!isturf(src.loc) || !(A in range(world.view, get_turf(src)))) - return FALSE +/mob/living/pointed(atom/A as mob|obj|turf in view()) if(src.stat || !src.canmove || src.restrained()) return FALSE if(src.status_flags & FAKEDEATH) return FALSE - if(next_point_time >= world.time) - return FALSE + + . = ..() - next_point_time = world.time + 25 - face_atom(A) - if(isturf(A)) - if(pointing_effect) - QDEL_NULL(pointing_effect) - pointing_effect = new /obj/effect/decal/point(A) - pointing_effect.invisibility = invisibility - addtimer(CALLBACK(GLOBAL_PROC, /proc/qdel, pointing_effect), 2 SECONDS) - else - A.add_filter("pointglow", 1, list(type = "drop_shadow", x = 0, y = -1, offset = 1, size = 1, color = "#F00")) - addtimer(CALLBACK(A, /atom/movable.proc/remove_filter, "pointglow"), 2 SECONDS) - visible_message("\The [src] points to \the [A].") - return TRUE + if(.) + visible_message("\The [src] points to \the [A].") /*one proc, four uses swapping: if it's 1, the mobs are trying to switch, if 0, non-passive is pushing passive diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 2929c382b1d..a5fd76a6271 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -156,7 +156,7 @@ proc/get_radio_key_from_channel(var/channel) return FONT_SIZE_LARGE return null -/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE) +/mob/living/say(var/message, var/datum/language/speaking = null, var/verb, var/alt_name="", var/ghost_hearing = GHOSTS_ALL_HEAR, var/whisper = FALSE) if(stat) if(stat == DEAD) return say_dead(message) @@ -209,8 +209,9 @@ proc/get_radio_key_from_channel(var/channel) return speaking.broadcast(src,trim(message)) return 1 - - verb = say_quote(message, speaking, is_singing, whisper) + + if(!verb) + verb = say_quote(message, speaking, is_singing, whisper) if(is_muzzled()) to_chat(src, "You're muzzled and cannot speak!") @@ -245,7 +246,7 @@ proc/get_radio_key_from_channel(var/channel) var/list/obj/item/used_radios = new var/list/successful_radio = new // passes a list because standard vars don't work when passed - if(handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name, successful_radio, whisper)) + if(handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name, successful_radio, whisper, is_singing)) return 1 var/list/handle_v = handle_speech_sound() diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index e0e387b975e..8de63709457 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -76,18 +76,6 @@ if (!movement_target) walk_to(src,0) - if(prob(2)) //spooky - var/mob/abstract/observer/spook = locate() in range(src,5) - if(spook) - var/turf/T = spook.loc - var/list/visible = list() - for(var/obj/O in T.contents) - if(!O.invisibility && O.name) - visible += O - if(visible.len) - var/atom/A = pick(visible) - visible_emote("suddenly stops and stares at something unseen[istype(A) ? " near [A]":""].",0) - /mob/living/simple_animal/cat/proc/attack_mice() if((src.loc) && isturf(src.loc)) if(!stat && !resting && !buckled_to) diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 95853540301..b9cd2c959cb 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -276,14 +276,12 @@ . =..() if(!.) return - if(!stat && prob(3) && eggsleft > 0) + if(!stat && prob(3) && eggsleft > 0 && chicken_count < MAX_CHICKENS) visible_message("[src] [pick("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.")]") eggsleft-- var/obj/item/reagent_containers/food/snacks/egg/E = new(get_turf(src)) E.pixel_x = rand(-6,6) E.pixel_y = rand(-6,6) - if(chicken_count < MAX_CHICKENS && prob(10)) - START_PROCESSING(SSprocessing, E) // Penguins diff --git a/code/modules/mob/living/whisper.dm b/code/modules/mob/living/whisper.dm index 23b3550ce35..4d2c7602d7b 100644 --- a/code/modules/mob/living/whisper.dm +++ b/code/modules/mob/living/whisper.dm @@ -16,13 +16,24 @@ whisper(message) -/mob/living/proc/whisper(var/message, var/datum/language/speaking) +/mob/living/proc/whisper(var/message, var/datum/language/speaking, var/is_singing = FALSE) if(is_muzzled()) to_chat(src, SPAN_DANGER("You're muzzled and cannot speak!")) return + var/had_speaking = !!speaking speaking = speaking ? speaking : parse_language(message) + if(!had_speaking) + if(speaking) + message = copytext(message,2+length(speaking.key)) + else + speaking = get_default_language() + + if(length(message) >= 1 && copytext(message, 1, 2) == "%") + if(speaking?.sing_verb) + is_singing = TRUE + var/message_range = 1 var/eavesdropping_range = 2 var/watching_range = 5 @@ -35,8 +46,11 @@ not_heard = "[whisper_text] something" else var/adverb = pick("quietly", "softly") - whisper_text = "[speaking.speech_verb] [adverb]" - not_heard = "[speaking.speech_verb] something [adverb]" + var/speak_text = pick(speaking.speech_verb) + if(is_singing && speaking?.sing_verb) + speak_text = pick(speaking.sing_verb) + whisper_text = "[speak_text] [adverb]" + not_heard = "[speak_text] something [adverb]" var/list/listening = list(src) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 3aa9b56f353..14689b72af0 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -333,21 +333,27 @@ set name = "Point To" set category = "Object" - if(!src || !isturf(src.loc) || !(A in range(world.view, get_turf(src)))) - return 0 - if(istype(A, /obj/effect/decal/point) || pointing_effect) - return 0 - - var/tile = get_turf(A) - if (!tile) - return 0 - - pointing_effect = new /obj/effect/decal/point(tile) - pointing_effect.invisibility = invisibility - addtimer(CALLBACK(GLOBAL_PROC, /proc/qdel, pointing_effect), 2 SECONDS) + if(!isturf(src.loc) || !(A in range(world.view, get_turf(src)))) + return FALSE + if(next_point_time >= world.time) + return FALSE + next_point_time = world.time + 25 face_atom(A) - return 1 + if(isturf(A)) + if(pointing_effect) + end_pointing_effect() + pointing_effect = new /obj/effect/decal/point(A) + pointing_effect.invisibility = invisibility + addtimer(CALLBACK(src, .proc/end_pointing_effect, pointing_effect), 2 SECONDS) + else + var/atom/movable/M = A + M.add_filter("pointglow", 1, list(type = "drop_shadow", x = 0, y = -1, offset = 1, size = 1, color = "#F00")) + addtimer(CALLBACK(M, /atom/movable.proc/remove_filter, "pointglow"), 2 SECONDS) + return TRUE + +/mob/proc/end_pointing_effect() + QDEL_NULL(pointing_effect) /mob/verb/mode() set name = "Activate Held Object" diff --git a/code/modules/multiz/zmimic/mimic_movable.dm b/code/modules/multiz/zmimic/mimic_movable.dm index 0f5e465c45c..3f67b197031 100644 --- a/code/modules/multiz/zmimic/mimic_movable.dm +++ b/code/modules/multiz/zmimic/mimic_movable.dm @@ -26,7 +26,8 @@ if (!bound_overlay) return - if (TURF_IS_MIMICING(loc)) + var/turf/T = loc + if (TURF_IS_MIMICING(T.above)) if (!bound_overlay.queued) SSzcopy.queued_overlays += bound_overlay bound_overlay.queued = TRUE diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm index 5f4992b55d9..f00288ab3a7 100644 --- a/code/modules/organs/internal/brain.dm +++ b/code/modules/organs/internal/brain.dm @@ -117,7 +117,7 @@ damage = max(damage-1, 0) if(BLOOD_VOLUME_OKAY to BLOOD_VOLUME_SAFE) if(prob(1)) - to_chat(owner, "You feel [pick("dizzy","woozy","faint")]...") + to_chat(owner, SPAN_WARNING("You feel a bit [pick("lightheaded","dizzy","pale")]...")) damprob = owner.chem_effects[CE_STABLE] ? 30 : 60 if(!past_damage_threshold(2) && prob(damprob)) take_internal_damage(1) @@ -128,7 +128,7 @@ take_internal_damage(1) if(!owner.paralysis && prob(10)) owner.Paralyse(rand(1,3)) - to_chat(owner, "You feel extremely [pick("dizzy","woozy","faint")]...") + to_chat(owner, SPAN_WARNING("You feel [pick("weak","disoriented","faint","cold")].")) if(BLOOD_VOLUME_SURVIVE to BLOOD_VOLUME_BAD) owner.eye_blurry = max(owner.eye_blurry,6) damprob = owner.chem_effects[CE_STABLE] ? 60 : 100 @@ -136,7 +136,7 @@ take_internal_damage(1) if(!owner.paralysis && prob(15)) owner.Paralyse(rand(3, 5)) - to_chat(owner, "You feel extremely [pick("dizzy","woozy","faint")]...") + to_chat(owner, SPAN_WARNING("You feel extremely [pick("cold","woozy","faint","weak","confused","tired","lethargic")].")) if(-(INFINITY) to BLOOD_VOLUME_SURVIVE) // Also see heart.dm, being below this point puts you into cardiac arrest. owner.eye_blurry = max(owner.eye_blurry,6) damprob = owner.chem_effects[CE_STABLE] ? 80 : 100 @@ -240,4 +240,4 @@ else to_chat(user, SPAN_WARNING("The brain has already been prepared!")) return - return ..() \ No newline at end of file + return ..() diff --git a/code/modules/organs/subtypes/augment.dm b/code/modules/organs/subtypes/augment.dm index cda11e6161f..3b6783c084b 100644 --- a/code/modules/organs/subtypes/augment.dm +++ b/code/modules/organs/subtypes/augment.dm @@ -570,10 +570,6 @@ cooldown = 30 activable = TRUE -/obj/item/organ/internal/augment/enhanced_vision/Initialize() - . = ..() - set_light(3, 2, LIGHT_COLOR_TUNGSTEN, uv = 0, angle = LIGHT_WIDE) - /obj/item/organ/internal/augment/enhanced_vision/attack_self(var/mob/user) . = ..() diff --git a/code/modules/organs/subtypes/machine.dm b/code/modules/organs/subtypes/machine.dm index 96df91868f7..cae90902ec6 100644 --- a/code/modules/organs/subtypes/machine.dm +++ b/code/modules/organs/subtypes/machine.dm @@ -66,6 +66,7 @@ parent_organ = BP_CHEST max_damage = 80 relative_size = 80 + robotic_sprite = FALSE var/open = FALSE var/obj/item/cell/cell = /obj/item/cell/super var/move_charge_factor = 1 @@ -164,6 +165,7 @@ organ_tag = "surge" parent_organ = BP_CHEST vital = FALSE + robotic_sprite = FALSE var/surge_left = 0 var/broken = 0 @@ -202,6 +204,7 @@ icon = 'icons/obj/robot_component.dmi' icon_state = "camera" dead_icon = "camera_broken" + robotic_sprite = FALSE /obj/item/organ/internal/eyes/optical_sensor/Initialize() robotize() @@ -216,6 +219,7 @@ item_state = "ipc_tag" dead_icon = "ipc_tag_dead" contained_sprite = TRUE + robotic_sprite = FALSE var/auto_generate = TRUE var/serial_number = "" var/ownership_info = IPC_OWNERSHIP_COMPANY @@ -285,6 +289,7 @@ organ_tag = BP_BRAIN parent_organ = BP_HEAD vital = TRUE + robotic_sprite = FALSE var/obj/item/device/mmi/stored_mmi /obj/item/organ/internal/mmi_holder/proc/update_from_mmi() @@ -360,6 +365,7 @@ icon_state = "harddisk" vital = FALSE emp_coeff = 0.1 + robotic_sprite = FALSE /obj/item/organ/internal/data/Initialize() robotize() diff --git a/code/modules/overmap/exoplanets/turfs.dm b/code/modules/overmap/exoplanets/turfs.dm index 7d169505134..ddbc0fcceac 100644 --- a/code/modules/overmap/exoplanets/turfs.dm +++ b/code/modules/overmap/exoplanets/turfs.dm @@ -152,7 +152,7 @@ /turf/simulated/floor/exoplanet/desert/Initialize() . = ..() - icon_state = "desert[rand(0,5)]" + icon_state = "desert[rand(0,4)]" //Concrete /turf/simulated/floor/exoplanet/concrete diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index e93f83c89d4..35b432c5dbf 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -8,6 +8,7 @@ gender = NEUTER icon = 'icons/obj/bureaucracy.dmi' icon_state = "paper" + var/base_state = "paper" item_state = "paper" contained_sprite = 1 throwforce = 0 @@ -42,8 +43,11 @@ drop_sound = 'sound/items/drop/paper.ogg' pickup_sound = 'sound/items/pickup/paper.ogg' + var/can_change_icon_state = TRUE + /obj/item/paper/Initialize(mapload, text, title) . = ..() + base_state = initial(icon_state) if (text || title) set_content(title, text ? text : info) else @@ -79,12 +83,12 @@ updateinfolinks() /obj/item/paper/update_icon() - if(icon_state == "paper_talisman") + if(!can_change_icon_state) return else if (info && length(trim(info))) - icon_state = "[initial(icon_state)]_words" + icon_state = "[base_state]_words" else - icon_state = "[initial(icon_state)]" + icon_state = "[base_state]" /obj/item/paper/proc/update_space(var/new_text) if(new_text) @@ -131,7 +135,7 @@ return var/n_name = sanitizeSafe(input(usr, "What would you like to label the paper?", "Paper Labelling", null) as text, MAX_NAME_LEN) - + if(use_check_and_message(usr, USE_ALLOW_NON_ADJACENT)) return @@ -184,7 +188,7 @@ if (user.a_intent == I_HELP && old_name && (icon_state == "paper_plane" || icon_state == "paper_swan")) user.visible_message(SPAN_NOTICE("\The [user] unfolds \the [src]."), SPAN_NOTICE("You unfold \the [src]."), "You hear paper rustling.") playsound(src, 'sound/bureaucracy/paperfold.ogg', 50, 1) - icon_state = initial(icon_state) + icon_state = base_state throw_range = initial(throw_range) name = old_name old_name = null @@ -409,7 +413,7 @@ . = replacetext(., written_lang_regex.match, "") else content = L.scramble(content) - + if(!language_check) // Refer to paper/proc/show_content to edit the spans here. . = replacetext(., written_lang_regex.match, "[L.short && reader_understands ? "([L.short]) [content]" : content]") @@ -679,3 +683,6 @@ Please note: Cell timers will \[b\]NOT\[/b\] function without a valid incident f /obj/item/paper/nka_pledge name = "imperial volunteer Alam'ardii corps pledge" info = "
Imperial Volunteer Alam'ardii Corps Pledge

May the Gods bless his Kingdom and Dynasty

I, , hereby declare, under a vow of loyalty and compromise, that I shall serve as a volunteer in the Imperial Volunteer Alam'ardii Corps, for the mininum duration of three years or until discharge. I accept the duty of aiding the New Kingdom of Adhomai and His Majesty, King Vahzirthaamro Azunja, in this struggle and I shall not relinquish this pledge.
Volunteer Signature:
Recruiting Officer Stamp:" + +/obj/item/paper/medscan + icon_state = "medscan" diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index ed8e2320b40..1cf9929478b 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1431,6 +1431,10 @@ charge_mode = CHARGE_MODE_STABLE last_time = world.time +/obj/machinery/power/apc/proc/manage_emergency(var/new_security_level) + for(var/obj/machinery/M in area) + M.set_emergency_state(new_security_level) + #undef UPDATE_CELL_IN #undef UPDATE_OPENED1 #undef UPDATE_OPENED2 diff --git a/code/modules/power/lights/bulbs.dm b/code/modules/power/lights/bulbs.dm index 14d2da5347a..6c84287a1eb 100644 --- a/code/modules/power/lights/bulbs.dm +++ b/code/modules/power/lights/bulbs.dm @@ -9,106 +9,18 @@ throwforce = 5 w_class = ITEMSIZE_TINY matter = list(DEFAULT_WALL_MATERIAL = 60) + drop_sound = 'sound/items/drop/drinkglass.ogg' + pickup_sound = 'sound/items/pickup/drinkglass.ogg' var/status = 0 // LIGHT_OK, LIGHT_BURNED or LIGHT_BROKEN var/switchcount = 0 // number of times switched var/rigged = 0 // true if rigged to explode var/brightness_range = 2 //how much light it gives off - var/brightness_power = 1 + var/brightness_power = 0.45 var/brightness_color = LIGHT_COLOR_HALOGEN var/lighttype = null var/randomize_range = TRUE - drop_sound = 'sound/items/drop/drinkglass.ogg' - pickup_sound = 'sound/items/pickup/drinkglass.ogg' - -/obj/item/light/tube - name = "light tube" - desc = "A replacement light tube." - icon_state = "ltube_preset"//preset state for mapping - item_state = "c_tube" - matter = list(MATERIAL_GLASS = 100) - brightness_range = 8 - brightness_power = 0.8 - lighttype = "tube" - -/obj/item/light/tube/colored/red - name = "red light tube" - brightness_color = LIGHT_COLOR_SCARLET - -/obj/item/light/tube/colored/green - name = "green light tube" - brightness_color = LIGHT_COLOR_GREEN - -/obj/item/light/tube/colored/blue - name = "blue light tube" - brightness_color = LIGHT_COLOR_BLUE - -/obj/item/light/tube/colored/magenta - name = "magenta light tube" - brightness_color = LIGHT_COLOR_VIOLET - -/obj/item/light/tube/colored/yellow - name = "yellow light tube" - brightness_color = LIGHT_COLOR_YELLOW - -/obj/item/light/tube/colored/cyan - name = "cyan light tube" - brightness_color = LIGHT_COLOR_CYAN - -/obj/item/light/tube/large - w_class = ITEMSIZE_SMALL - name = "large light tube" - brightness_range = 15 - brightness_power = 6 - randomize_range = FALSE - -/obj/item/light/bulb - name = "light bulb" - desc = "A replacement light bulb." - icon_state = "lbulb_preset"//preset state for mapping - item_state = "egg" - matter = list(MATERIAL_GLASS = 100) - brightness_range = 5 - brightness_power = 0.75 - brightness_color = LIGHT_COLOR_TUNGSTEN - lighttype = "bulb" - -/obj/item/light/bulb/colored/red - name = "red light bulb" - brightness_color = LIGHT_COLOR_SCARLET - -/obj/item/light/bulb/colored/green - name = "green light bulb" - brightness_color = LIGHT_COLOR_GREEN - -/obj/item/light/bulb/colored/blue - name = "blue light bulb" - brightness_color = LIGHT_COLOR_BLUE - -/obj/item/light/bulb/colored/magenta - name = "magenta light bulb" - brightness_color = LIGHT_COLOR_VIOLET - -/obj/item/light/bulb/colored/yellow - name = "yellow light bulb" - brightness_color = LIGHT_COLOR_YELLOW - -/obj/item/light/bulb/colored/cyan - name = "cyan light bulb" - brightness_color = LIGHT_COLOR_CYAN - -/obj/item/light/throw_impact(atom/hit_atom) - ..() - shatter() - -/obj/item/light/bulb/fire - name = "fire bulb" - desc = "A replacement fire bulb." - icon_state = "flight" - item_state = "egg_red" - matter = list(MATERIAL_GLASS = 100) - brightness_range = 8 - brightness_power = 0.8 - randomize_range = FALSE + var/randomize_color = TRUE + var/list/randomized_colors = LIGHT_STANDARD_COLORS /obj/item/light/Initialize() . = ..() @@ -118,6 +30,8 @@ brightness_range = rand(6,9) if("bulb") brightness_range = rand(4,6) + if(randomize_color) + brightness_color = pick(randomized_colors) update() // update the icon state and description of the light @@ -187,3 +101,93 @@ playsound(get_turf(src), 'sound/effects/glass_hit.ogg', 75, TRUE) new /obj/item/material/shard(get_turf(src)) update() + +/obj/item/light/tube + name = "light tube" + desc = "A replacement light tube." + icon_state = "ltube_preset"//preset state for mapping + item_state = "c_tube" + matter = list(MATERIAL_GLASS = 100) + brightness_range = 8 + brightness_power = 0.4 + lighttype = "tube" + +/obj/item/light/tube/colored/red + name = "red light tube" + brightness_color = LIGHT_COLOR_SCARLET + +/obj/item/light/tube/colored/green + name = "green light tube" + brightness_color = LIGHT_COLOR_GREEN + +/obj/item/light/tube/colored/blue + name = "blue light tube" + brightness_color = LIGHT_COLOR_BLUE + +/obj/item/light/tube/colored/magenta + name = "magenta light tube" + brightness_color = LIGHT_COLOR_VIOLET + +/obj/item/light/tube/colored/yellow + name = "yellow light tube" + brightness_color = LIGHT_COLOR_YELLOW + +/obj/item/light/tube/colored/cyan + name = "cyan light tube" + brightness_color = LIGHT_COLOR_CYAN + +/obj/item/light/tube/large + w_class = ITEMSIZE_SMALL + name = "large light tube" + brightness_range = 15 + brightness_power = 0.75 + randomize_range = FALSE + +/obj/item/light/bulb + name = "light bulb" + desc = "A replacement light bulb." + icon_state = "lbulb_preset"//preset state for mapping + item_state = "egg" + matter = list(MATERIAL_GLASS = 100) + brightness_range = 5 + brightness_power = 0.4 + brightness_color = LIGHT_COLOR_TUNGSTEN + lighttype = "bulb" + +/obj/item/light/bulb/colored/red + name = "red light bulb" + brightness_color = LIGHT_COLOR_SCARLET + +/obj/item/light/bulb/colored/green + name = "green light bulb" + brightness_color = LIGHT_COLOR_GREEN + +/obj/item/light/bulb/colored/blue + name = "blue light bulb" + brightness_color = LIGHT_COLOR_BLUE + +/obj/item/light/bulb/colored/magenta + name = "magenta light bulb" + brightness_color = LIGHT_COLOR_VIOLET + +/obj/item/light/bulb/colored/yellow + name = "yellow light bulb" + brightness_color = LIGHT_COLOR_YELLOW + +/obj/item/light/bulb/colored/cyan + name = "cyan light bulb" + brightness_color = LIGHT_COLOR_CYAN + +/obj/item/light/throw_impact(atom/hit_atom) + ..() + shatter() + +/obj/item/light/bulb/fire + name = "fire bulb" + desc = "A replacement fire bulb." + icon_state = "flight" + item_state = "egg_red" + matter = list(MATERIAL_GLASS = 100) + brightness_range = 8 + brightness_power = 0.45 + randomize_range = FALSE diff --git a/code/modules/power/lights/fixtures.dm b/code/modules/power/lights/fixtures.dm index b8060647d30..17665f9a162 100644 --- a/code/modules/power/lights/fixtures.dm +++ b/code/modules/power/lights/fixtures.dm @@ -19,9 +19,9 @@ power_channel = LIGHT //Lights are calc'd via area so they dont need to be in the machine list gfi_layer_rotation = GFI_ROTATION_DEFDIR var/brightness_range = 8 // luminosity when on, also used in power calculation - var/brightness_power = 0.8 + var/brightness_power = 0.45 var/night_brightness_range = 6 - var/night_brightness_power = 0.6 + var/night_brightness_power = 0.4 var/supports_nightmode = TRUE var/nightmode = FALSE var/brightness_color = LIGHT_COLOR_HALOGEN @@ -47,6 +47,13 @@ var/bulb_is_noisy = TRUE var/previous_stat + var/randomize_color = TRUE + var/default_color + var/static/list/randomized_colors = LIGHT_STANDARD_COLORS + var/static/list/emergency_lights = list( + LIGHT_MODE_RED = LIGHT_COLOR_EMERGENCY, + LIGHT_MODE_DELTA = LIGHT_COLOR_ORANGE + ) /obj/machinery/light/skrell base_state = "skrell" @@ -56,7 +63,7 @@ bulb_is_noisy = FALSE light_type = /obj/item/light/tube inserted_light = /obj/item/light/tube - brightness_power = 1 + brightness_power = 0.45 brightness_color = LIGHT_COLOR_PURPLE // the smaller bulb light fixture @@ -66,7 +73,7 @@ base_state = "bulb" fitting = "bulb" brightness_range = 5 - brightness_power = 0.75 + brightness_power = 0.45 brightness_color = LIGHT_COLOR_TUNGSTEN desc = "A small lighting fixture." light_type = /obj/item/light/bulb @@ -76,12 +83,12 @@ /obj/machinery/light/small/emergency brightness_range = 6 - brightness_power = 1 + brightness_power = 0.45 brightness_color = LIGHT_COLOR_EMERGENCY_SOFT /obj/machinery/light/small/red brightness_range = 2.5 - brightness_power = 1 + brightness_power = 0.45 brightness_color = LIGHT_COLOR_RED /obj/machinery/light/colored/blue @@ -96,7 +103,7 @@ light_type = /obj/item/light/tube/large inserted_light = /obj/item/light/tube/large brightness_range = 12 - brightness_power = 4 + brightness_power = 3.5 supports_nightmode = FALSE /obj/machinery/light/spot/weak @@ -134,6 +141,9 @@ if(prob(5)) broken(1) + if(randomize_color) + brightness_color = pick(randomized_colors) + default_color = brightness_color // We need a different var so the new color doesn't get wiped away. Initial() wouldn't work since brightness_color is overridden. update(0) /obj/machinery/light/Destroy() @@ -620,3 +630,14 @@ explosion(T, 0, 0, 2, 2) sleep(1) qdel(src) + +/obj/machinery/light/set_emergency_state(var/new_security_level) + var/area/A = get_area(src) + if(new_security_level in emergency_lights) + if(A.emergency_lights) + brightness_color = emergency_lights[new_security_level] + update(0) + else + if(brightness_color != default_color) + brightness_color = default_color + update(0) \ No newline at end of file diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm index 612f2b9341e..a50abf6432d 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Other.dm @@ -364,7 +364,7 @@ /decl/reagent/nitroglycerin/on_heat_change(var/added_energy, var/datum/reagents/holder) . = ..() - if(added_energy > (specific_heat * 5 / REAGENT_VOLUME(holder, type))) // heat shock + if(added_energy > (specific_heat * 5 * REAGENT_VOLUME(holder, type))) // heat shock explode(holder) /decl/reagent/nitroglycerin/apply_force(var/force, var/datum/reagents/holder) diff --git a/code/modules/reagents/reagent_containers/glass/bottle.dm b/code/modules/reagents/reagent_containers/glass/bottle.dm index 7f9cd87b7b6..3ab7986427b 100644 --- a/code/modules/reagents/reagent_containers/glass/bottle.dm +++ b/code/modules/reagents/reagent_containers/glass/bottle.dm @@ -126,6 +126,12 @@ icon_state = "bottle-4" reagents_to_add = list(/decl/reagent/acid/polyacid = 60) +/obj/item/reagent_containers/glass/bottle/nitroglycerin + name = "nitroglycerin bottle" + desc = "A small bottle. Contains a small amount of Nitroglycerin." + icon_state = "bottle-4" + reagents_to_add = list(/decl/reagent/nitroglycerin = 60) + /obj/item/reagent_containers/glass/bottle/adminordrazine name = "adminordrazine bottle" desc = "A small bottle. Contains the liquid essence of the gods." diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index f974d21e454..e7bd4ac648c 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -31,6 +31,9 @@ . = ..() update_icon() +/obj/item/reagent_containers/hypospray/AltClick(var/mob/user) + set_APTFT() + /obj/item/reagent_containers/hypospray/on_reagent_change() update_icon() return diff --git a/code/modules/reagents/reagent_containers/inhaler.dm b/code/modules/reagents/reagent_containers/inhaler.dm index 7263801a1f4..9f54672a765 100644 --- a/code/modules/reagents/reagent_containers/inhaler.dm +++ b/code/modules/reagents/reagent_containers/inhaler.dm @@ -5,9 +5,8 @@ desc = "A rapid and safe way to administer small amounts of drugs into the lungs by untrained or trained personnel." icon = 'icons/obj/syringe.dmi' item_state = "autoinjector" - icon_state = "inhaler1" + icon_state = "autoinhaler" center_of_mass = list("x" = 16,"y" = 11) - var/empty_state = "inhaler0" unacidable = 1 amount_per_transfer_from_this = 5 volume = 5 @@ -16,20 +15,27 @@ flags = OPENCONTAINER slot_flags = SLOT_BELT center_of_mass = null - var/used = FALSE + var/name_label + var/spent = FALSE matter = list(MATERIAL_GLASS = 400, DEFAULT_WALL_MATERIAL = 200) /obj/item/reagent_containers/inhaler/Initialize() . =..() - icon_state = empty_state + if(name_label) + name_unlabel = name + name = "[name] ([name_label])" + verbs += /atom/proc/remove_label + if(reagents_to_add) + flags = 0 + spent = FALSE update_icon() -/obj/item/reagent_containers/inhaler/afterattack(var/mob/living/carbon/human/H, var/mob/user, var/proximity) +/obj/item/reagent_containers/inhaler/on_reagent_change() + update_icon() + return - if (!istype(H)) - return ..() - - if(!proximity) +/obj/item/reagent_containers/inhaler/proc/inject(var/mob/living/carbon/human/H, var/mob/user, var/proximity) + if (!istype(H) || !proximity) return if(!reagents.total_volume) @@ -47,7 +53,7 @@ playsound(src.loc, 'sound/items/stimpack.ogg', 50, 1) user.visible_message("[user] accidentally sticks the [src] in [H]'s eyes!","You accidentally stick the [src] in [H]'s eyes!") to_chat(user,"[trans] units injected. [reagents.total_volume] units remaining in \the [src].") - used = TRUE + spent = TRUE update_icon() return @@ -82,16 +88,25 @@ admin_inject_log(user, H, src, contained, temp, trans) playsound(src.loc, 'sound/items/stimpack.ogg', 50, 1) to_chat(user,"[trans] units injected. [reagents.total_volume] units remaining in \the [src].") - used = TRUE + spent = TRUE update_icon() - return TRUE +/obj/item/reagent_containers/inhaler/afterattack(var/mob/living/carbon/human/H, var/mob/user, proximity) + if (!istype(H)) + return ..() + + if(!proximity) + return + /obj/item/reagent_containers/inhaler/attack(mob/M as mob, mob/user as mob) if(is_open_container()) to_chat(user,"You must secure the reagents inside \the [src] before using it!") return FALSE + + else + inject(M, user, M.Adjacent(user)) . = ..() /obj/item/reagent_containers/inhaler/attack_self(mob/user as mob) @@ -99,6 +114,7 @@ if(LAZYLEN(reagents.reagent_volumes)) to_chat(user,"With a quick twist of \the [src]'s lid, you secure the reagents inside.") flags &= ~OPENCONTAINER + spent = FALSE update_icon() else to_chat(user,"You can't secure \the [src] without putting reagents in!") @@ -115,10 +131,18 @@ . = ..() /obj/item/reagent_containers/inhaler/update_icon() - if(reagents.total_volume > 0 && !is_open_container()) - icon_state = initial(icon_state) - else - icon_state = empty_state + cut_overlays() + if(!is_open_container()) + var/mutable_appearance/backing_overlay = mutable_appearance(icon, "autoinhaler_secured") + add_overlay(backing_overlay) + + icon_state = "[initial(icon_state)][spent]" + item_state = "[initial(item_state)][spent]" + + if(reagents.total_volume) + var/mutable_appearance/reagent_overlay = mutable_appearance(icon, "autoinhaler_reagents") + reagent_overlay.color = reagents.get_color() + add_overlay(reagent_overlay) /obj/item/reagent_containers/inhaler/examine(mob/user) ..(user) @@ -128,7 +152,7 @@ to_chat(user, "It is spent.") /obj/item/reagent_containers/inhaler/dexalin - name = "autoinhaler (dexalin)" + name_label = "dexalin" desc = "A rapid and safe way to administer small amounts of drugs into the lungs by untrained or trained personnel. This one contains dexalin." Initialize() @@ -138,7 +162,7 @@ return /obj/item/reagent_containers/inhaler/peridaxon - name = "autoinhaler (peridaxon)" + name_label = "peridaxon" desc = "A rapid and safe way to administer small amounts of drugs into the lungs by untrained or trained personnel. This one contains peridaxon." Initialize() @@ -148,7 +172,7 @@ return /obj/item/reagent_containers/inhaler/hyperzine - name = "autoinhaler (hyperzine)" + name_label = "hyperzine" desc = "A rapid and safe way to administer small amounts of drugs into the lungs by untrained or trained personnel. This one contains hyperzine." Initialize() @@ -158,7 +182,7 @@ return /obj/item/reagent_containers/inhaler/phoron - name = "autoinhaler (phoron)" + name_label = "phoron" desc = "A rapid and safe way to administer small amounts of drugs into the lungs by untrained or trained personnel. This one contains phoron." Initialize() @@ -171,7 +195,7 @@ name = "vaurca autoinhaler (phoron)" desc = "A strange device that contains some sort of heavy-duty bag and mouthpiece combo." icon_state = "anthaler1" - empty_state = "anthaler0" + var/empty_state = "anthaler0" volume = 10 Initialize() . =..() @@ -180,10 +204,8 @@ return /obj/item/reagent_containers/inhaler/soporific - name = "autoinhaler (soporific)" + name_label = "soporific" desc = "A rapid and safe way to administer small amounts of drugs into the lungs by untrained or trained personnel. This one contains soporific." - icon_state = "so_inhaler1" - empty_state = "so_inhaler0" volume = 10 Initialize() @@ -193,7 +215,7 @@ return /obj/item/reagent_containers/inhaler/space_drugs - name = "autoinhaler (space drugs)" + name_label = "space drugs" desc = "A rapid and safe way to administer small amounts of drugs into the lungs by untrained or trained personnel. This one contains space drugs." Initialize() @@ -203,7 +225,7 @@ return /obj/item/reagent_containers/inhaler/ammonia - name = "autoinhaler (ammonia)" + name_label = "ammonia" desc = "A rapid and safe way to administer small amounts of drugs into the lungs by untrained or trained personnel. This one contains ammonia." Initialize() @@ -213,7 +235,7 @@ return /obj/item/reagent_containers/inhaler/pulmodeiectionem - name = "autoinhaler (pulmodeiectionem)" + name_label = "pulmodeiectionem" desc = "A rapid and safe way to administer small amounts of drugs into the lungs by untrained or trained personnel. This one contains pulmodeiectionem." Initialize() @@ -223,10 +245,8 @@ return /obj/item/reagent_containers/inhaler/pneumalin - name = "autoinhaler (pneumalin)" + name_label = "pneumalin" desc = "A rapid and safe way to administer small amounts of drugs into the lungs by untrained or trained personnel. This one contains pneumalin." - icon_state = "so_inhaler1" - empty_state = "so_inhaler0" volume = 10 Initialize() diff --git a/code/modules/reagents/reagent_containers/inhaler_advanced.dm b/code/modules/reagents/reagent_containers/inhaler_advanced.dm index 481a0a5167e..8f18df6f413 100644 --- a/code/modules/reagents/reagent_containers/inhaler_advanced.dm +++ b/code/modules/reagents/reagent_containers/inhaler_advanced.dm @@ -5,7 +5,7 @@ name = "small inhaler cartridge" desc = "Fill this when chemicals and attach this to personal inhalers. Contains enough aerosol for 15u of reagents. The container must be activated for aerosol reagents to mix for the use in inhalers." icon = 'icons/obj/syringe.dmi' - item_state = "buildpipe" + item_state = "pi_cart_small" icon_state = "pi_cart_small" volume = 15 w_class = ITEMSIZE_TINY @@ -18,6 +18,19 @@ matter = list(DEFAULT_WALL_MATERIAL = 250) center_of_mass = null +/obj/item/reagent_containers/personal_inhaler_cartridge/on_reagent_change() + update_icon() + return + +/obj/item/reagent_containers/personal_inhaler_cartridge/update_icon() + cut_overlays() + var/rounded_vol = round(reagents.total_volume, round(reagents.maximum_volume / (volume / 5))) + + if(reagents.total_volume) + var/mutable_appearance/filling = mutable_appearance('icons/obj/syringe.dmi', "[initial(icon_state)][rounded_vol]") + filling.color = reagents.get_color() + add_overlay(filling) + /obj/item/reagent_containers/personal_inhaler_cartridge/examine(var/mob/user) if(!..(user, 2)) return @@ -75,7 +88,7 @@ name = "inhaler" desc = "A safe way to administer small amounts of drugs into the lungs by trained personnel." icon = 'icons/obj/syringe.dmi' - item_state = "buildpipe" + item_state = "pi" icon_state = "pi" w_class = ITEMSIZE_SMALL slot_flags = SLOT_BELT @@ -94,6 +107,11 @@ cut_overlays() if(stored_cartridge) add_overlay(stored_cartridge.icon_state) + if(stored_cartridge.reagents.total_volume) + var/rounded_vol = round(stored_cartridge.reagents.total_volume, round(stored_cartridge.reagents.maximum_volume / (stored_cartridge.volume / 5))) + var/image/filling = image(icon, "[stored_cartridge.icon_state][rounded_vol]") + filling.color = stored_cartridge.reagents.get_color() + add_overlay(filling) /obj/item/personal_inhaler/attack_self(mob/user as mob) if(stored_cartridge) @@ -150,8 +168,9 @@ if(M.reagents) var/contained = stored_cartridge.reagentlist() + var/temp = stored_cartridge.reagents.get_temperature() var/trans = stored_cartridge.reagents.trans_to_mob(M, transfer_amount, CHEM_BREATHE, bypass_checks = TRUE) - admin_inject_log(user, M, src, contained, reagents.get_temperature(), trans) + admin_inject_log(user, M, src, contained, temp, trans) playsound(M.loc, 'sound/items/stimpack.ogg', 50, 1) if(eject_when_empty) to_chat(user,"\The [stored_cartridge] automatically ejects from \the [src].") @@ -162,6 +181,7 @@ else to_chat(user,"Nothing happens!") + update_icon() return /obj/item/personal_inhaler/attackby(var/obj/item/reagent_containers/personal_inhaler_cartridge/cartridge as obj, var/mob/user as mob) diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 1a676b02203..f648b206574 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -20,7 +20,7 @@ center_of_mass = list("x" = 16,"y" = 14) matter = list(MATERIAL_GLASS = 150) amount_per_transfer_from_this = 5 - possible_transfer_amounts = list(1, 2, 5, 15) + possible_transfer_amounts = list(1, 2, 5, 10, 15) volume = 15 w_class = ITEMSIZE_TINY slot_flags = SLOT_EARS @@ -35,6 +35,7 @@ var/image/filling //holds a reference to the current filling overlay var/visible_name = "a syringe" var/time = 30 + var/last_jab = 0 //Spam prevention center_of_mass = null drop_sound = 'sound/items/drop/glass_small.ogg' pickup_sound = 'sound/items/pickup/glass_small.ogg' @@ -55,6 +56,9 @@ STOP_PROCESSING(SSprocessing, src) return 1 +/obj/item/reagent_containers/syringe/AltClick(var/mob/user) + set_APTFT() + /obj/item/reagent_containers/syringe/proc/infect_limb(var/obj/item/organ/external/eo) eo.germ_level += dirtiness // only 75% of the way to an infection at max @@ -106,6 +110,10 @@ return /obj/item/reagent_containers/syringe/afterattack(obj/target, mob/user, proximity) + if(last_jab + time > world.time) + to_chat(usr, SPAN_WARNING("You're already using \the [src]!")) + return + if(!proximity || !target.reagents) return @@ -119,10 +127,19 @@ if(user.a_intent == I_GRAB && ishuman(user) && ishuman(target)) // we could add other things here eventually. trepanation maybe var/mob/living/carbon/human/H = target if (check_zone(user.zone_sel.selecting) == BP_CHEST) // impromptu needle thoracostomy, re-inflate a collapsed lung + var/obj/item/organ/internal/lungs/L = H.internal_organs_by_name[BP_LUNGS] var/P = (user == target) ? "their" : (target.name + "\'s") var/SM = (user == target) ? "your" : (target.name + "\'s") + if(!L) + return + if(L.rescued == TRUE) + to_chat(usr, SPAN_NOTICE("[H]'s ribs are already punctured!")) + return + last_jab = world.time user.visible_message("[user] aims \the [src] between [P] ribs!", SPAN_NOTICE("You aim \the [src] between [SM] ribs!")) if(!do_mob(user, target, 1.5 SECONDS)) + last_jab = 0 //Resets to try again immediately + user.visible_message("[user] fumbles with \the [src]!", SPAN_NOTICE("You fumble with \the [src]!")) return var/blocked = H.get_blocked_ratio(BP_CHEST, BRUTE, DAM_SHARP, damage = 5) if(blocked > 20) @@ -130,10 +147,8 @@ return user.visible_message("[user] jabs \the [src] between [P] ribs!", SPAN_NOTICE("You jab \the [src] between [SM] ribs!")) H.apply_damage(3, BRUTE, BP_CHEST) - H.custom_pain("The pain in your chest is living hell!", 75, affecting = H.organs_by_name[BP_CHEST]) - var/obj/item/organ/internal/lungs/L = H.internal_organs_by_name[BP_LUNGS] - if(!L) - return + H.custom_pain("The pain in your chest is living hell!", 50, affecting = H.organs_by_name[BP_CHEST]) + L.oxygen_deprivation = 0 L.rescued = TRUE return @@ -221,6 +236,7 @@ if(ismob(target) && target != user) var/inject_time = time if(isliving(target)) + last_jab = world.time var/mob/living/L = target var/inject_mod = L.can_inject(user, TRUE, user.zone_sel.selecting) if(!inject_mod) @@ -231,6 +247,8 @@ user.do_attack_animation(target) if(!do_mob(user, target, inject_time)) + last_jab = 0 + user.visible_message("[user] fumbles with \the [src]!", SPAN_NOTICE("You fumble with \the [src]!")) return user.visible_message(SPAN_WARNING("[user] injects [target] with the syringe!")) diff --git a/code/modules/security levels/security levels.dm b/code/modules/security levels/security levels.dm index 0f775045b0d..f4fdbf22d02 100644 --- a/code/modules/security levels/security levels.dm +++ b/code/modules/security levels/security levels.dm @@ -54,10 +54,9 @@ SSnightlight.temp_disable() var/newlevel = get_security_level() - for(var/obj/machinery/firealarm/FA in SSmachinery.processing_machines) - if(isContactLevel(FA.z)) - FA.set_security_level(newlevel) - + for(var/obj/machinery/power/apc/powercontrol in SSmachinery.processing_machines) + if(isContactLevel(powercontrol.z)) + powercontrol.manage_emergency(newlevel) /proc/get_security_level() switch(security_level) diff --git a/code/modules/shieldgen/shield_gen_external.dm b/code/modules/shieldgen/shield_gen_external.dm index e65a4e9aa9e..4710b5b0dd8 100644 --- a/code/modules/shieldgen/shield_gen_external.dm +++ b/code/modules/shieldgen/shield_gen_external.dm @@ -29,7 +29,7 @@ if (T == U) continue - if (the_station_areas[U.loc]) + if (the_station_areas[U.loc] || istype(U, /turf/simulated/mineral/surface)) out += T break diff --git a/code/modules/submaps/_submap.dm b/code/modules/submaps/_submap.dm new file mode 100644 index 00000000000..e5ccd981157 --- /dev/null +++ b/code/modules/submaps/_submap.dm @@ -0,0 +1,46 @@ +/datum/submap + var/name + var/pref_name + var/decl/submap_archetype/archetype + var/associated_z + +/datum/submap/New(var/existing_z) + SSmapping.submaps[src] = TRUE + associated_z = existing_z + +/datum/submap/Destroy() + SSmapping.submaps -= src + . = ..() + +/datum/submap/proc/setup_submap(var/decl/submap_archetype/_archetype) + + if(!istype(_archetype)) + log_game( "Submap error - [name] - null or invalid archetype supplied ([_archetype]).") + qdel(src) + return + + // Not much point doing this when it has presumably been done already. + if(_archetype == archetype) + log_game( "Submap error - [name] - submap already set up.") + return + + archetype = _archetype + if(!pref_name) + pref_name = archetype.descriptor + + log_game("Starting submap setup - '[name]', [archetype], [associated_z]z.") + + if(!associated_z) + log_game( "Submap error - [name]/[archetype ? archetype.descriptor : "NO ARCHETYPE"] could not find an associated z-level for spawnpoint placement.") + qdel(src) + return + + var/obj/effect/overmap/visitable/cell = map_sectors["[associated_z]"] + if(istype(cell)) + sync_cell(cell) + +/datum/submap/proc/sync_cell(var/obj/effect/overmap/visitable/cell) + name = cell.name + +/datum/submap/proc/available() + return TRUE diff --git a/code/modules/submaps/submap_archetype.dm b/code/modules/submaps/submap_archetype.dm new file mode 100644 index 00000000000..4df8169e914 --- /dev/null +++ b/code/modules/submaps/submap_archetype.dm @@ -0,0 +1,15 @@ +/decl/submap_archetype + var/map + var/descriptor = "generic ship archetype" + +/decl/submap_archetype/Destroy() + if(SSmapping.submap_archetypes[descriptor] == src) + SSmapping.submap_archetypes -= descriptor + . = ..() + +// Generic ships to populate the list. +/decl/submap_archetype/derelict + descriptor = "drifting wreck" + +/decl/submap_archetype/abandoned_ship + descriptor = "abandoned ship" diff --git a/code/modules/submaps/submap_landmark.dm b/code/modules/submaps/submap_landmark.dm new file mode 100644 index 00000000000..245c8a299d8 --- /dev/null +++ b/code/modules/submaps/submap_landmark.dm @@ -0,0 +1,25 @@ +/obj/effect/submap_landmark + icon = 'icons/misc/mark.dmi' + invisibility = INVISIBILITY_MAXIMUM + anchored = TRUE + simulated = FALSE + density = FALSE + opacity = FALSE + +/obj/effect/submap_landmark/joinable_submap + icon_state = "x4" + var/archetype + var/submap_datum_type = /datum/submap + +/obj/effect/submap_landmark/joinable_submap/Initialize(var/mapload) + . = ..(mapload) + if(!SSmapping.submaps[name] && SSmapping.submap_archetypes[archetype]) + var/datum/submap/submap = new submap_datum_type(z) + submap.name = name + submap.setup_submap(SSmapping.submap_archetypes[archetype]) + else + if(SSmapping.submaps[name]) + log_debug( "Submap error - mapped landmark is duplicate of existing.") + else + log_debug( "Submap error - mapped landmark had invalid archetype.") + return INITIALIZE_HINT_QDEL \ No newline at end of file diff --git a/config/example/away_site_blacklist.txt b/config/example/away_site_blacklist.txt new file mode 100644 index 00000000000..c07f6f9167b --- /dev/null +++ b/config/example/away_site_blacklist.txt @@ -0,0 +1,5 @@ +#Listing maps here will blacklist them from generating as away sites. +#Maps must be the full path to them +#SPECIFYING AN INVALID MAP WILL RESULT IN RUNTIMES ON GAME START + +#maps/random_ruins/away_sites/example.dmm \ No newline at end of file diff --git a/config/example/exoplanet_ruin_blacklist.txt b/config/example/exoplanet_ruin_blacklist.txt new file mode 100644 index 00000000000..456fd76e4e1 --- /dev/null +++ b/config/example/exoplanet_ruin_blacklist.txt @@ -0,0 +1,5 @@ +#Listing maps here will blacklist them from generating on exoplanets. +#Maps must be the full path to them +#SPECIFYING AN INVALID MAP WILL RESULT IN RUNTIMES ON GAME START + +#maps/random_ruins/exoplanet_ruins/example.dmm \ No newline at end of file diff --git a/config/example/space_ruin_blacklist.txt b/config/example/space_ruin_blacklist.txt new file mode 100644 index 00000000000..3b1d80f20b9 --- /dev/null +++ b/config/example/space_ruin_blacklist.txt @@ -0,0 +1,6 @@ +#Listing maps here will blacklist them from generating in space. +#Maps must be the full path to them +#SPECIFYING AN INVALID MAP WILL RESULT IN RUNTIMES ON GAME START + +#maps/random_ruins/space_ruins/example.dmm +maps/random_ruins/exoplanets/crashed_pod/crashed_pod.dmm \ No newline at end of file diff --git a/html/changelog.html b/html/changelog.html index e89ad7de3e0..a8552e38058 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -35,6 +35,194 @@ -->
+

19 February 2022

+

TheGreyWolf updated:

+
    +
  • The hull shield generator now also create shields around the rock walls found on the asteroid to guarantee station safety.
  • +
+

Vrow updated:

+
    +
  • You can now shove in IPCs via grabs or drag and drop into the rechargers.
  • +
  • Shoving them in via grabs/drag and drop doesn't take as long as stationbounds, but it does take around 5 seconds.
  • +
  • Autoinhaler sprites tweaked and subtly easier to click.
  • +
  • Inhaler sprites refreshened and sligthyly larger and subtly easier to click.
  • +
  • Autoinhalers that spawn with reagents can have their labels removed properly
  • +
  • Inhaler Cartridge sprites revamped with the ability to show how much stuff there is inside of them, like hyposprays!
  • +
  • Fixed autoinhalers letting you inject people without being twisted closed.
  • +
  • Fixed inhalers not properly making the sound or giving adminlogs.
  • +
+

mikomyazaki updated:

+
    +
  • Can now throw objects over railings.
  • +
  • ID card photos will now face the correct directions instead of both being of the direction your character was facing when your ID card spawned.
  • +
+ +

18 February 2022

+

MattAtlas updated:

+
    +
  • Ported Baystation's improvements to the maploader.
  • +
  • Ported Baystation's system for Overmap away sites and exoplanet ruin generation.
  • +
+

Sparky_hotdog updated:

+
    +
  • Added colourable shorts to the loadout.
  • +
+

TheGreyWolf updated:

+
    +
  • Changed how hoods works slightly. Shouldn't be any player-facing changes.
  • +
+

Vrow updated:

+
    +
  • Lung rescue properly clears the built up OxyLoss (but doesn't prevent it from increasing).
  • +
  • Decreased pain caused by lung rescue from 75 to 50.
  • +
  • Added a spam prevention to the syringes.
  • +
+

mikomyazaki updated:

+
    +
  • Being assigned a special role now clears 'role_alt_title', which could lead to you getting an ID with your previous job on it when spawning as an antagonist.
  • +
  • Atmospherics consoles linked to injector outlets (e.g. Supermatter coolant control console) will no longer require you to click 'Search for input port' the first time you open it in a round, they will instead start with their mapped injector already linked properly.
  • +
  • Crew Arrival Announcement/Records will now include a faction tag for valid factions, so your crew manifest listing can match everyone else's.
  • +
  • The Agent ID can now have a faction name set.
  • +
  • It is now possible to safely heat nitroglycerin without explosions. Use a large volume and heat it in small increments.
  • +
  • Chem heaters now have a 'slow mode' option that will heat your chemical in very small steps.
  • +
  • Fixes pressure regulators not creating the right underlays when connecting to universal adapters in some cases.
  • +
+ +

17 February 2022

+

Geeves updated:

+
    +
  • Bulwarks now move faster, a bit slower than their other vaurca brethren. In exchange, their stamina has been halved.
  • +
+

SierraKomodo updated:

+
    +
  • Replaced the windows between the kitchen and bar counter areas with walls, to reduce the spam of conversational text on both sides.
  • +
+ +

16 February 2022

+

Sparky_hotdog updated:

+
    +
  • Fixed the Zeng-Hu Responder Coat having the wrong description.
  • +
+

Vrow updated:

+
    +
  • Fixes the operating table's neural suppressors occasionally not working.
  • +
  • Added a set transfer amount AltClick function for Hyposprays and Syringes.
  • +
  • Syringes also have a set transfer amount of 10u. Finally the 1, 2, 5, 10, 15 train is complete.
  • +
+

Yonnimer updated:

+
    +
  • Adds two new dionae religions as options in the setup, Ksshr and Shrkh
  • +
  • Updates the old message nymphs got one growing up into a full gestalt
  • +
+

listerla updated:

+
    +
  • Removed the ability of cats to see observers.
  • +
+

mikomyazaki updated:

+
    +
  • Z-mimic will now update properly when something changes on the bottom visible turf.
  • +
  • Pointing arrows should now delete themselves properly.
  • +
+ +

15 February 2022

+

TheGreyWolf updated:

+
    +
  • Using the whisper verb with a language should now show the message properly.
  • +
  • Radios now properly show what is spoken into rather than always picking the item on the left ear slot.
  • +
  • Language specific whisper verbs will now be used again.
  • +
  • PDAs should no longer show up as 'unknown' on roundstart.
  • +
+

Wowzewow (Wezzy), monster860 updated:

+
    +
  • Adds animation to opening and closing lockers and body bags.
  • +
+ +

14 February 2022

+

MattAtlas updated:

+
    +
  • The loadout will now substitute job clothing in the preview.
  • +
+

Vrow updated:

+
    +
  • Vision Enhanced Retinas no longer has lights like the sightlights.
  • +
  • Fixed Icelance Icon disappearing when it has 2/3 shots remaining.
  • +
+

listerla updated:

+
    +
  • Dominian suits are no longer assless.
  • +
+

mikomyazaki updated:

+
    +
  • Space turfs will now properly display the camera static image when they are not visible from a camera, to an AI or camera view.
  • +
+ +

13 February 2022

+

Geeves updated:

+
    +
  • Offworlders now have access to all human accents plus scarab fleets, minus the silversun, pluto, europan, cytherean and gadpathurian accents.
  • +
+

Ramke updated:

+
    +
  • Adjusted the gruff tajara cloak's hooded side sprites.
  • +
+

TheGreyWolf updated:

+
    +
  • Added a verb to remove yarn on knitting needles.
  • +
  • Fixed animations on knitting needles.
  • +
  • Knitting needles no longer try to produce something when the selection is cancelled.
  • +
+

Vrow updated:

+
    +
  • Operating console is now more responsive, with alarms for some specific conditions.
  • +
  • Inserting a Medical Scan into the Operating console now displays it accordingly, which you can update whenever you want or need.
  • +
  • Operating console also shows Blood Volume
  • +
  • Added a new paper type: Medscan papers.
  • +
  • Medscan papers sprites added.
  • +
  • Relevant machines and device print out the Medscan paper type.
  • +
  • The Operating Table pulse display now has a flatlined state!
  • +
+

mikomyazaki updated:

+
    +
  • Fixed issue where trying to load a lathe with <1 of a sheet of something didn't delete the sheet item.
  • +
  • Fixed issue where loading a lathe with an object consisting of >1 materials could provide incorrect messages about how full it is.
  • +
+ +

12 February 2022

+

Alberyk updated:

+
    +
  • Fixed some robotic internal organs not having sprites.
  • +
+

MattAtlas updated:

+
    +
  • Station lighting is moodier overall.
  • +
  • Lights now spawn with a random color between halogen, warm white and white.
  • +
  • Hallway lights now become red in code red, and reset on code green.
  • +
+

SierraKomodo updated:

+
    +
  • Fixed spelling of 'Burzsia' in the passcard loadout item.
  • +
+

SleepyGem updated:

+
    +
  • Re-added lighters and dice as valid wallet items.
  • +
  • Adds keys as valid wallet items.
  • +
+

The Stryker updated:

+
    +
  • The accent tag of Konyang has been changed to reflect the current flag in lore.
  • +
+

TheGreyWolf updated:

+
    +
  • Fixed blood overlays on clothes.
  • +
  • Fixed tracks still being left after cleaning shoes.
  • +
  • Held mob sprites should now work again.
  • +
  • The adhomian lighter can now be opened by alt clicking it.
  • +
+

Vrow updated:

+
    +
  • Tweaked the messages you get from blood loss. Now it's not just the same dizzy, faint, and woozy for all blood loss levels.
  • +
+

09 February 2022

Geeves updated:

    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index d29499b5d94..62e71435c94 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -22587,3 +22587,146 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. volume is full. readthisnameplz: - rscadd: Added a white version of the Captains dress. +2022-02-12: + Alberyk: + - bugfix: Fixed some robotic internal organs not having sprites. + MattAtlas: + - tweak: Station lighting is moodier overall. + - tweak: Lights now spawn with a random color between halogen, warm white and white. + - rscadd: Hallway lights now become red in code red, and reset on code green. + SierraKomodo: + - spellcheck: Fixed spelling of 'Burzsia' in the passcard loadout item. + SleepyGem: + - rscadd: Re-added lighters and dice as valid wallet items. + - rscadd: Adds keys as valid wallet items. + The Stryker: + - tweak: The accent tag of Konyang has been changed to reflect the current flag + in lore. + TheGreyWolf: + - bugfix: Fixed blood overlays on clothes. + - bugfix: Fixed tracks still being left after cleaning shoes. + - bugfix: Held mob sprites should now work again. + - rscadd: The adhomian lighter can now be opened by alt clicking it. + Vrow: + - tweak: Tweaked the messages you get from blood loss. Now it's not just the + same dizzy, faint, and woozy for all blood loss levels. +2022-02-13: + Geeves: + - rscadd: Offworlders now have access to all human accents plus scarab fleets, minus + the silversun, pluto, europan, cytherean and gadpathurian accents. + Ramke: + - tweak: Adjusted the gruff tajara cloak's hooded side sprites. + TheGreyWolf: + - rscadd: Added a verb to remove yarn on knitting needles. + - bugfix: Fixed animations on knitting needles. + - bugfix: Knitting needles no longer try to produce something when the selection + is cancelled. + Vrow: + - rscadd: Operating console is now more responsive, with alarms for some specific + conditions. + - rscadd: Inserting a Medical Scan into the Operating console now displays it accordingly, + which you can update whenever you want or need. + - tweak: Operating console also shows Blood Volume + - rscadd: 'Added a new paper type: Medscan papers.' + - imageadd: Medscan papers sprites added. + - tweak: Relevant machines and device print out the Medscan paper type. + - imageadd: The Operating Table pulse display now has a flatlined state! + mikomyazaki: + - bugfix: Fixed issue where trying to load a lathe with <1 of a sheet of something + didn't delete the sheet item. + - bugfix: Fixed issue where loading a lathe with an object consisting of >1 materials + could provide incorrect messages about how full it is. +2022-02-14: + MattAtlas: + - bugfix: The loadout will now substitute job clothing in the preview. + Vrow: + - bugfix: Vision Enhanced Retinas no longer has lights like the sightlights. + - bugfix: Fixed Icelance Icon disappearing when it has 2/3 shots remaining. + listerla: + - bugfix: Dominian suits are no longer assless. + mikomyazaki: + - bugfix: Space turfs will now properly display the camera static image when they + are not visible from a camera, to an AI or camera view. +2022-02-15: + TheGreyWolf: + - bugfix: Using the whisper verb with a language should now show the message properly. + - bugfix: Radios now properly show what is spoken into rather than always picking + the item on the left ear slot. + - bugfix: Language specific whisper verbs will now be used again. + - bugfix: PDAs should no longer show up as 'unknown' on roundstart. + Wowzewow (Wezzy), monster860: + - rscadd: Adds animation to opening and closing lockers and body bags. +2022-02-16: + Sparky_hotdog: + - tweak: Fixed the Zeng-Hu Responder Coat having the wrong description. + Vrow: + - bugfix: Fixes the operating table's neural suppressors occasionally not working. + - rscadd: Added a set transfer amount AltClick function for Hyposprays and Syringes. + - tweak: Syringes also have a set transfer amount of 10u. Finally the 1, 2, 5, 10, + 15 train is complete. + Yonnimer: + - rscadd: Adds two new dionae religions as options in the setup, Ksshr and Shrkh + - tweak: Updates the old message nymphs got one growing up into a full gestalt + listerla: + - rscdel: Removed the ability of cats to see observers. + mikomyazaki: + - bugfix: Z-mimic will now update properly when something changes on the bottom + visible turf. + - bugfix: Pointing arrows should now delete themselves properly. +2022-02-17: + Geeves: + - tweak: Bulwarks now move faster, a bit slower than their other vaurca brethren. + In exchange, their stamina has been halved. + SierraKomodo: + - maptweak: Replaced the windows between the kitchen and bar counter areas with + walls, to reduce the spam of conversational text on both sides. +2022-02-18: + MattAtlas: + - experiment: Ported Baystation's improvements to the maploader. + - experiment: Ported Baystation's system for Overmap away sites and exoplanet + ruin generation. + Sparky_hotdog: + - rscadd: Added colourable shorts to the loadout. + TheGreyWolf: + - tweak: Changed how hoods works slightly. Shouldn't be any player-facing changes. + Vrow: + - bugfix: Lung rescue properly clears the built up OxyLoss (but doesn't prevent + it from increasing). + - tweak: Decreased pain caused by lung rescue from 75 to 50. + - rscadd: Added a spam prevention to the syringes. + mikomyazaki: + - bugfix: Being assigned a special role now clears 'role_alt_title', which + could lead to you getting an ID with your previous job on it when spawning as + an antagonist. + - bugfix: Atmospherics consoles linked to injector outlets (e.g. Supermatter coolant + control console) will no longer require you to click 'Search for input + port' the first time you open it in a round, they will instead start with + their mapped injector already linked properly. + - bugfix: Crew Arrival Announcement/Records will now include a faction tag for valid + factions, so your crew manifest listing can match everyone else's. + - tweak: The Agent ID can now have a faction name set. + - bugfix: It is now possible to safely heat nitroglycerin without explosions. Use + a large volume and heat it in small increments. + - rscadd: Chem heaters now have a 'slow mode' option that will heat your + chemical in very small steps. + - bugfix: Fixes pressure regulators not creating the right underlays when connecting + to universal adapters in some cases. +2022-02-19: + TheGreyWolf: + - tweak: The hull shield generator now also create shields around the rock walls + found on the asteroid to guarantee station safety. + Vrow: + - rscadd: You can now shove in IPCs via grabs or drag and drop into the rechargers. + - tweak: Shoving them in via grabs/drag and drop doesn't take as long as stationbounds, + but it does take around 5 seconds. + - tweak: Autoinhaler sprites tweaked and subtly easier to click. + - tweak: Inhaler sprites refreshened and sligthyly larger and subtly easier to click. + - rscadd: Autoinhalers that spawn with reagents can have their labels removed properly + - rscadd: Inhaler Cartridge sprites revamped with the ability to show how much stuff + there is inside of them, like hyposprays! + - bugfix: Fixed autoinhalers letting you inject people without being twisted closed. + - bugfix: Fixed inhalers not properly making the sound or giving adminlogs. + mikomyazaki: + - bugfix: Can now throw objects over railings. + - bugfix: ID card photos will now face the correct directions instead of both being + of the direction your character was facing when your ID card spawned. diff --git a/html/changelogs/HeldFix.yml b/html/changelogs/HeldFix.yml deleted file mode 100644 index 2124706c4c0..00000000000 --- a/html/changelogs/HeldFix.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: TheGreyWolf - -delete-after: True - -changes: - - bugfix: "Held mob sprites should now work again." diff --git a/icons/accent_tags.dmi b/icons/accent_tags.dmi index 3237e2680d5..6c94ed1f7f9 100644 Binary files a/icons/accent_tags.dmi and b/icons/accent_tags.dmi differ diff --git a/icons/clothing/under/uniforms/dominia_uniform_black.dmi b/icons/clothing/under/uniforms/dominia_uniform_black.dmi index 80190c751c1..10046a0abd5 100644 Binary files a/icons/clothing/under/uniforms/dominia_uniform_black.dmi and b/icons/clothing/under/uniforms/dominia_uniform_black.dmi differ diff --git a/icons/clothing/under/uniforms/dominia_uniform_red.dmi b/icons/clothing/under/uniforms/dominia_uniform_red.dmi index 2fa3436bef1..eb0b22d015c 100644 Binary files a/icons/clothing/under/uniforms/dominia_uniform_red.dmi and b/icons/clothing/under/uniforms/dominia_uniform_red.dmi differ diff --git a/icons/effects/landmarks.dmi b/icons/effects/landmarks.dmi new file mode 100644 index 00000000000..356074d148f Binary files /dev/null and b/icons/effects/landmarks.dmi differ diff --git a/icons/mob/uniform.dmi b/icons/mob/uniform.dmi index 2ff3368e369..5ed115a66d7 100644 Binary files a/icons/mob/uniform.dmi and b/icons/mob/uniform.dmi differ diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi index d5ccf6140cc..57548444046 100644 Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ diff --git a/icons/obj/clothing/uniforms.dmi b/icons/obj/clothing/uniforms.dmi index b1f991a9544..f805103f909 100644 Binary files a/icons/obj/clothing/uniforms.dmi and b/icons/obj/clothing/uniforms.dmi differ diff --git a/icons/obj/custom_items/kathira_cloak.dmi b/icons/obj/custom_items/kathira_cloak.dmi index fe5579a9592..da74247145a 100644 Binary files a/icons/obj/custom_items/kathira_cloak.dmi and b/icons/obj/custom_items/kathira_cloak.dmi differ diff --git a/icons/obj/custom_items/mekesatis_holocoat.dmi b/icons/obj/custom_items/mekesatis_holocoat.dmi index 8a58041563e..bba68df4b77 100644 Binary files a/icons/obj/custom_items/mekesatis_holocoat.dmi and b/icons/obj/custom_items/mekesatis_holocoat.dmi differ diff --git a/icons/obj/custom_items/mrakiizar_book.dmi b/icons/obj/custom_items/mrakiizar_book.dmi index e9af53007d3..5c589e46512 100644 Binary files a/icons/obj/custom_items/mrakiizar_book.dmi and b/icons/obj/custom_items/mrakiizar_book.dmi differ diff --git a/icons/obj/guns/icelance.dmi b/icons/obj/guns/icelance.dmi index 8288db7e8af..f3eb3cad1d1 100644 Binary files a/icons/obj/guns/icelance.dmi and b/icons/obj/guns/icelance.dmi differ diff --git a/icons/obj/organs/organs.dmi b/icons/obj/organs/organs.dmi index dd284ef7d63..5df992f277c 100644 Binary files a/icons/obj/organs/organs.dmi and b/icons/obj/organs/organs.dmi differ diff --git a/icons/obj/surgery.dmi b/icons/obj/surgery.dmi index 2f5c688cf38..08bdbfbc210 100644 Binary files a/icons/obj/surgery.dmi and b/icons/obj/surgery.dmi differ diff --git a/icons/obj/syringe.dmi b/icons/obj/syringe.dmi index c86945dad1a..e9d02a4a28b 100644 Binary files a/icons/obj/syringe.dmi and b/icons/obj/syringe.dmi differ diff --git a/icons/obj/tajara_items.dmi b/icons/obj/tajara_items.dmi index 8736dea1b77..c754fa34957 100644 Binary files a/icons/obj/tajara_items.dmi and b/icons/obj/tajara_items.dmi differ diff --git a/maps/_common/areas/station/hallways.dm b/maps/_common/areas/station/hallways.dm index 13eee4095f3..f1386b0afbf 100644 --- a/maps/_common/areas/station/hallways.dm +++ b/maps/_common/areas/station/hallways.dm @@ -7,6 +7,7 @@ station_area = TRUE lightswitch = TRUE holomap_color = HOLOMAP_AREACOLOR_HALLWAYS + emergency_lights = TRUE /area/hallway/primary/fore name = "Fore Primary Hallway" diff --git a/maps/_common/mapsystem/map.dm b/maps/_common/mapsystem/map.dm index 49efce82905..b047fdd80e3 100644 --- a/maps/_common/mapsystem/map.dm +++ b/maps/_common/mapsystem/map.dm @@ -107,6 +107,9 @@ var/num_exoplanets = 0 var/list/planet_size //dimensions of planet zlevel, defaults to world size. Due to how maps are generated, must be (2^n+1) e.g. 17,33,65,129 etc. Map will just round up to those if set to anything other. + var/min_offmap_players = 0 + var/away_site_budget = 0 + var/allow_borgs_to_leave = FALSE //this controls if borgs can leave the station or ship without exploding /datum/map/New() @@ -162,3 +165,93 @@ log_debug("Building new exoplanet with type: [exoplanet_type] and size: [planet_size[1]] [planet_size[2]]") var/obj/effect/overmap/visitable/sector/exoplanet/new_planet = new exoplanet_type(null, planet_size[1], planet_size[2]) new_planet.build_level() + +/* It is perfectly possible to create loops with TEMPLATE_FLAG_ALLOW_DUPLICATES and force/allow. Don't. */ +/proc/resolve_site_selection(datum/map_template/ruin/away_site/site, list/selected, list/available, list/unavailable, list/by_type) + var/spawn_cost = 0 + var/player_cost = 0 + if (site in selected) + if (!(site.template_flags & TEMPLATE_FLAG_ALLOW_DUPLICATES)) + return list(spawn_cost, player_cost) + if (!(site.template_flags & TEMPLATE_FLAG_ALLOW_DUPLICATES)) + available -= site + spawn_cost += site.spawn_cost + player_cost += site.player_cost + selected += site + + for (var/forced_type in site.force_ruins) + var/list/costs = resolve_site_selection(by_type[forced_type], selected, available, unavailable, by_type) + spawn_cost += costs[1] + player_cost += costs[2] + + for (var/banned_type in site.ban_ruins) + var/datum/map_template/ruin/away_site/banned = by_type[banned_type] + if (banned in unavailable) + continue + unavailable += banned + available -= banned + + for (var/allowed_type in site.allow_ruins) + var/datum/map_template/ruin/away_site/allowed = by_type[allowed_type] + if (allowed in available) + continue + if (allowed in unavailable) + continue + if (allowed in selected) + if (!(allowed.template_flags & TEMPLATE_FLAG_ALLOW_DUPLICATES)) + continue + available[allowed] = allowed.spawn_weight + + return list(spawn_cost, player_cost) + +/datum/map/proc/build_away_sites() +#ifdef UNIT_TEST + log_admin("Unit testing, so not loading away sites") + return // don't build away sites during unit testing +#else + log_admin("Loading away sites...") + + var/list/guaranteed = list() + var/list/selected = list() + var/list/available = list() + var/list/unavailable = list() + var/list/by_type = list() + + for (var/site_name in SSmapping.away_sites_templates) + var/datum/map_template/ruin/away_site/site = SSmapping.away_sites_templates[site_name] + if (site.template_flags & TEMPLATE_FLAG_SPAWN_GUARANTEED) + guaranteed += site + if ((site.template_flags & TEMPLATE_FLAG_ALLOW_DUPLICATES) && !(site.template_flags & TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED)) + available[site] = site.spawn_weight + else if (!(site.template_flags & TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED)) + available[site] = site.spawn_weight + by_type[site.type] = site + + var/points = away_site_budget + var/players = -min_offmap_players + for (var/client/C) + ++players + + for (var/datum/map_template/ruin/away_site/site in guaranteed) + var/list/costs = resolve_site_selection(site, selected, available, unavailable, by_type) + points -= costs[1] + players -= costs[2] + + while (points > 0 && length(available)) + var/datum/map_template/ruin/away_site/site = pickweight(available) + if (site.spawn_cost && site.spawn_cost > points || site.player_cost && site.player_cost > players) + unavailable += site + available -= site + continue + var/list/costs = resolve_site_selection(site, selected, available, unavailable, by_type) + points -= costs[1] + players -= costs[2] + + log_admin("Finished selecting away sites ([english_list(selected)]) for [away_site_budget - points] cost of [away_site_budget] budget.") + + for (var/datum/map_template/template in selected) + if (template.load_new_z()) + log_admin("Loaded away site [template]!") + else + log_admin("Failed loading away site [template]!") +#endif \ No newline at end of file diff --git a/maps/aurora/aurora-4_mainlevel.dmm b/maps/aurora/aurora-4_mainlevel.dmm index 080f795525f..b8aac24a1e2 100644 --- a/maps/aurora/aurora-4_mainlevel.dmm +++ b/maps/aurora/aurora-4_mainlevel.dmm @@ -101403,7 +101403,7 @@ bQZ bOR bRQ bSq -bSN +bOt bTq bTZ bUF @@ -101660,7 +101660,7 @@ wtZ bOX gjz uea -bSO +bOt bko bUa bUG diff --git a/maps/away/README.md b/maps/away/README.md new file mode 100644 index 00000000000..d1ad767013c --- /dev/null +++ b/maps/away/README.md @@ -0,0 +1,53 @@ +# Away sites + +## What exactly is an away site? + +It's a kind of map template which: +* is placed in its own zlevel (or collection of zlevels), +* should only get placed once per round, +* can be randomly picked to be placed automatically during round setup, +* normally has an overmap presence and shuttle landmarks so ships can fly to it. + +### Er, what's a map template? + +It's a datum you can define in the code (`/datum/map_template`) which points at one or more .dmm map files, and allows the game (or admins) to spawn those map files when and where they please, whether that's into an existing zlevel (like decorating exoplanets with ruins), or on a totally fresh one (like an away site!). + +## How do I make away sites? + +tl;dr you make your .dmm files, then you write a new map template datum (`/datum/map_template/ruin/away_site/insert_your_away_site_name_here`). + +BUT HEED MY RUMINATIONS + +## While mapping + +### Don't use map-specific types + +Away maps are expected to work whether you're on the main map, Runtime, or anything else you might want to load as the server's main map. That means your map mustn't use areas, turfs, objects, mobs or datums that are specific to any main map. + +e.g. you can use `/area/space`, or `/turf/simulated/wall`, because neither are specific to a certain map. They live out in the main codebase, are always compiled in, and are available to all maps. But you can't use items that may only be compiled with a certain map, because they only exists when said map is compiled. + +### Don't re-use area types from other maps + +Except for, like, `/area/space`. That one's probably fine. + +(Now that's just areas! Other stuff might be ok. Except very map-specific stuff as noted!) + +Re-using areas is a shortcut, but it's bad for testability, and you can't guarantee that the area you re-use isn't loaded up and in active use on the server - in which case it'll hideously merge together with its brother in terms of stuff like air alarms, APCs, etc. Suddenly your derelict starship is randomly receiving power from another zlevel. Not good. Avoid. Make your own area types! + +### If you're doing multi-z, make a different .dmm file for each zlevel + +Not exactly a technical requirement, but it makes things easier in terms of collaboration. See how it's done with `runtime-1.dmm`, `runtime-2.dmm`, etc. + +## Afterwards (or during, I'm not a cop) + +### Make sure you've got a .dm file for all your stuff + +It's a pretty good place to put all your new types! #include other files here too. This file's going to be the hub of your map's wheel, to cack-hand a metaphor. + +### Make a map template datum there + +The game will read this to learn about your new shiny away sites, including what .dmm files it needs to load, how much it 'costs' to spawn (usually 1, increase for more performance-heavy away sites). Ask devs or read code if unsure.. + +### Some of the stuff I put in my map isn't behaving properly! + +The map loader works best when everything it's spawning does all its initialisation work in `Initialize`, instead of in `New`. Most likely your misbehaving thing is doing more initialisation than is healthy in `New`. It's fixable! Often not even that hard. Go talk to a dev. diff --git a/maps/away/away_sites.dm b/maps/away/away_sites.dm new file mode 100644 index 00000000000..3ad2b60acea --- /dev/null +++ b/maps/away/away_sites.dm @@ -0,0 +1,5 @@ +// Hey! Listen! Update \config\away_site_blacklist.txt with your new ruins! + +/datum/map_template/ruin/away_site + var/list/generate_mining_by_z + prefix = "maps/away/" \ No newline at end of file diff --git a/maps/random_ruins/exoplanet_ruins/asteroid/asteroid.dm b/maps/random_ruins/exoplanets/asteroid/asteroid.dm similarity index 90% rename from maps/random_ruins/exoplanet_ruins/asteroid/asteroid.dm rename to maps/random_ruins/exoplanets/asteroid/asteroid.dm index 6de10627c6c..d67eb44112c 100644 --- a/maps/random_ruins/exoplanet_ruins/asteroid/asteroid.dm +++ b/maps/random_ruins/exoplanets/asteroid/asteroid.dm @@ -4,7 +4,7 @@ description = "An abandoned mining site. Some tools and materials were left behind." spawn_weight = 1 - cost = 2 + spawn_cost = 2 sectors = list(SECTOR_TAU_CETI, SECTOR_ROMANOVICH, SECTOR_CORP_ZONE) suffix = "asteroid/mining_base.dmm" @@ -16,7 +16,7 @@ description = "A nest of deadly space carps." spawn_weight = 1 - cost = 2 + spawn_cost = 2 sectors = list(SECTOR_TAU_CETI, SECTOR_ROMANOVICH, SECTOR_CORP_ZONE) suffix = "asteroid/carp_nest.dmm" diff --git a/maps/random_ruins/exoplanet_ruins/asteroid/carp_nest.dmm b/maps/random_ruins/exoplanets/asteroid/carp_nest.dmm similarity index 98% rename from maps/random_ruins/exoplanet_ruins/asteroid/carp_nest.dmm rename to maps/random_ruins/exoplanets/asteroid/carp_nest.dmm index ef6dde2f4cd..690088df49d 100644 --- a/maps/random_ruins/exoplanet_ruins/asteroid/carp_nest.dmm +++ b/maps/random_ruins/exoplanets/asteroid/carp_nest.dmm @@ -10,7 +10,7 @@ /turf/unsimulated/floor/asteroid/ash, /area/exoplanet/barren/asteroid) "e" = ( -/mob/living/simple_animal/hostile/carp, +/mob/living/simple_animal/hostile/carp/asteroid, /turf/unsimulated/floor/asteroid/ash, /area/exoplanet/barren/asteroid) "f" = ( diff --git a/maps/random_ruins/exoplanet_ruins/asteroid/mining_base.dmm b/maps/random_ruins/exoplanets/asteroid/mining_base.dmm similarity index 100% rename from maps/random_ruins/exoplanet_ruins/asteroid/mining_base.dmm rename to maps/random_ruins/exoplanets/asteroid/mining_base.dmm diff --git a/maps/random_ruins/exoplanets/crashed_pod/crashed_pod.dm b/maps/random_ruins/exoplanets/crashed_pod/crashed_pod.dm new file mode 100644 index 00000000000..615a891404a --- /dev/null +++ b/maps/random_ruins/exoplanets/crashed_pod/crashed_pod.dm @@ -0,0 +1,18 @@ +/datum/map_template/ruin/exoplanet/crashed_pod + name = "crashed survival pod" //This map is not very elaborate and is meant to be an example on how to make a ruin. + id = "crashed_pod" + description = "A crashed survival pod from a destroyed ship." + suffix = "crashed_pod/crashed_pod.dmm" + template_flags = TEMPLATE_FLAG_CLEAR_CONTENTS | TEMPLATE_FLAG_NO_RUINS | TEMPLATE_FLAG_RUIN_STARTS_DISALLOWED + ruin_tags = RUIN_HUMAN|RUIN_WRECK + spawn_weight = 0.33 + +/decl/submap_archetype/crashed_pod + descriptor = "crashed survival pod" + +/datum/submap/crashed_pod/sync_cell(var/obj/effect/overmap/visitable/cell) + return + +/area/map_template/crashed_pod + name = "Crashed Pod" + icon_state = "blue" \ No newline at end of file diff --git a/maps/random_ruins/exoplanets/crashed_pod/crashed_pod.dmm b/maps/random_ruins/exoplanets/crashed_pod/crashed_pod.dmm new file mode 100644 index 00000000000..323b49bdc14 --- /dev/null +++ b/maps/random_ruins/exoplanets/crashed_pod/crashed_pod.dmm @@ -0,0 +1,26 @@ +"a" = (/turf/template_noop,/area/template_noop) +"b" = (/turf/template_noop,/area/space) +"c" = (/turf/simulated/wall/shuttle/dark,/area/map_template/crashed_pod) +"d" = (/obj/structure/bed/stool/chair/shuttle,/turf/simulated/floor/tiled,/area/map_template/crashed_pod) +"e" = (/obj/machinery/suit_storage_unit/standard_unit,/turf/simulated/floor/tiled,/area/map_template/crashed_pod) +"f" = (/turf/simulated/floor/tiled,/area/map_template/crashed_pod) +"g" = (/obj/structure/table/rack,/obj/item/storage/toolbox/emergency,/obj/item/storage/toolbox/emergency,/obj/item/storage/toolbox/emergency,/obj/item/storage/belt/utility,/obj/item/storage/belt/utility,/obj/item/storage/belt/utility,/obj/item/clothing/gloves/yellow,/obj/item/clothing/gloves/yellow,/obj/item/clothing/gloves/yellow,/turf/simulated/floor/tiled,/area/map_template/crashed_pod) +"h" = (/obj/structure/closet/toolcloset,/turf/simulated/floor/tiled,/area/map_template/crashed_pod) +"i" = (/obj/machinery/power/terminal{dir = 8},/obj/structure/cable{dir = 8},/obj/machinery/power/apc/super{pixel_x = -32},/turf/simulated/floor/tiled,/area/map_template/crashed_pod) +"k" = (/obj/structure/cable{d1 = 4; d2 = 8; icon_state = "4-8"},/turf/simulated/floor/tiled,/area/map_template/crashed_pod) +"l" = (/obj/machinery/power/smes/buildable,/obj/structure/cable{dir = 4},/turf/simulated/floor/tiled,/area/map_template/crashed_pod) +"n" = (/obj/machinery/autolathe,/turf/simulated/floor/tiled,/area/map_template/crashed_pod) +"o" = (/obj/structure/droppod_door,/turf/simulated/wall/shuttle/dark,/area/map_template/crashed_pod) + +(1,1,1) = {" +abbbbbbbbb +accccccccb +acdddeeecb +acffffffcb +acgffffhcb +acikkkklcb +achffffncb +achfffffcb +accooocccb +aaaaaaaaaa +"} diff --git a/maps/random_ruins/exoplanets/exoplanet_ruins.dm b/maps/random_ruins/exoplanets/exoplanet_ruins.dm index c8fc74e8464..6dba2e15e2a 100644 --- a/maps/random_ruins/exoplanets/exoplanet_ruins.dm +++ b/maps/random_ruins/exoplanets/exoplanet_ruins.dm @@ -1,3 +1,3 @@ /datum/map_template/ruin/exoplanet - prefix = "maps/random_ruins/exoplanet_ruins/" + prefix = "maps/random_ruins/exoplanets/" var/list/ruin_tags diff --git a/maps/random_ruins/space_ruins/multi_zas_test.dmm b/maps/random_ruins/space_ruins/multi_zas_test.dmm new file mode 100644 index 00000000000..660bcbbbd62 --- /dev/null +++ b/maps/random_ruins/space_ruins/multi_zas_test.dmm @@ -0,0 +1,131 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/simulated/wall/diamond, +/area/template_noop) +"b" = ( +/turf/simulated/floor, +/area/template_noop) +"c" = ( +/mob/living/simple_animal/passive/corgi, +/turf/simulated/floor, +/area/template_noop) +"d" = ( +/turf/simulated/open, +/area/template_noop) +"e" = ( +/turf/unsimulated/floor/shuttle_ceiling, +/area/template_noop) +"f" = ( +/obj/effect/landmark/map_data{ + height = 3 + }, +/turf/unsimulated/floor/shuttle_ceiling, +/area/template_noop) + +(1,1,1) = {" +a +a +a +a +a +"} +(2,1,1) = {" +a +b +b +b +a +"} +(3,1,1) = {" +a +b +c +b +a +"} +(4,1,1) = {" +a +b +b +b +a +"} +(5,1,1) = {" +a +a +a +a +a +"} + +(1,1,2) = {" +a +a +a +a +a +"} +(2,1,2) = {" +a +d +d +d +a +"} +(3,1,2) = {" +a +d +d +d +a +"} +(4,1,2) = {" +a +d +d +d +a +"} +(5,1,2) = {" +a +a +a +a +a +"} + +(1,1,3) = {" +e +e +e +e +f +"} +(2,1,3) = {" +e +e +e +e +e +"} +(3,1,3) = {" +e +e +e +e +e +"} +(4,1,3) = {" +e +e +e +e +e +"} +(5,1,3) = {" +e +e +e +e +e +"} diff --git a/maps/random_ruins/space_ruins/space_ruins.dm b/maps/random_ruins/space_ruins/space_ruins.dm new file mode 100644 index 00000000000..9fbcf9ab800 --- /dev/null +++ b/maps/random_ruins/space_ruins/space_ruins.dm @@ -0,0 +1,12 @@ +// Hey! Listen! Update \config\space_ruin_blacklist.txt with your new ruins! + +/datum/map_template/ruin/space + prefix = "maps/random_ruins/space_ruins/" + spawn_cost = 1 + +/datum/map_template/ruin/space/multi_zas_test + name = "Multi-ZAS Test" + id = "multi_zas_test" + description = "if this has vacuum in it, that's not good!" + suffix = "multi_zas_test.dmm" + spawn_cost = 1 \ No newline at end of file diff --git a/maps/runtime/code/runtime.dm b/maps/runtime/code/runtime.dm index 5fb9bd0388e..d7ab627d030 100644 --- a/maps/runtime/code/runtime.dm +++ b/maps/runtime/code/runtime.dm @@ -44,4 +44,6 @@ num_exoplanets = 3 planet_size = list(65, 65) + away_site_budget = 3 + map_shuttles = list(/datum/shuttle/autodock/overmap/runtime) diff --git a/maps/runtime/runtime-9.dmm b/maps/runtime/runtime-9.dmm index c5a68621157..14ae9ebf574 100644 --- a/maps/runtime/runtime-9.dmm +++ b/maps/runtime/runtime-9.dmm @@ -2,14 +2,69 @@ "b" = (/obj/effect/shuttle_landmark/runtime/transit,/turf/space,/area/space) (1,1,1) = {" -aaaaaaaaaa -aaaaaaaaaa -aaaaaaaaaa -aaaaaaaaaa -aaaaaaaaaa -aaaabaaaaa -aaaaaaaaaa -aaaaaaaaaa -aaaaaaaaaa -aaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaabaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "}