diff --git a/.github/ISSUE_TEMPLATE/issue-report.md b/.github/ISSUE_TEMPLATE/issue-report.md new file mode 100644 index 000000000000..ea0f0aa4093b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/issue-report.md @@ -0,0 +1,62 @@ +--- +name: Issue report +about: Create a report about a bug or other issue +title: '' +labels: '' +assignees: '' + +--- + + + +#### Description of issue + + + +#### Difference between expected and actual behavior + + + +#### Steps to reproduce + + + +#### Specific information for locating + + + + +#### Length of time in which bug has been known to occur + + + + +#### Client version, Server revision & Game ID + + + + +#### Issue bingo + + +- [ ] Issue could be reproduced at least once +- [ ] Issue could be reproduced by different players +- [ ] Issue could be reproduced in multiple rounds +- [ ] Issue happened in a recent (less than 7 days ago) round +- [ ] [Couldn't find an existing issue about this](https://github.com/NebulaSS13/Nebula/issues) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5c858b868b25..3940d892dd02 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,3 +30,14 @@ This is a quick and dirty set of agreed-upon standards for contributions to the - If there's a personal dislike of the PR, post about it for discussion. Maybe have an 'on hold for discussion' label. Try to reach a consensus/compromise. Failing a compromise, a majority maintainer vote will decide. - First person to review approves the PR, second person to review can merge it. If 24 hours pass with no objections, first person can merge the PR themselves. - PRs can have a 24 hour grace period applied by maintainers if it seems important for discussion and responses to be involved. Don't merge for the grace period if applied (reviews are fine). + +### Footguns +A footgun is a pattern, function, assumption etc. that stands a strong chance to shoot you in the foot. They are documented here for ease of reference by new contributors. + +#### List footguns +- Adding lists to lists will actually perform a merge, rather than inserting the list as a new record. If you want to insert a list into a list, you need to either: + - double-wrap it, ex. `my_list += list(list("some_new_data" = 25))` + - set the index directly, ex. `my_list[my_list.len] = list("some_new_data" = 25)` +- Using variables and macros as associative list keys have some notable behavior. + - If declaring an associative list using a macro as a key, in a case where the macro does not exist (due to misspelling, etc.), that macro name will be treated as a string value for the associative list. You can guard against this by wrapping the macro in parens, ex. `list( (MY_MACRO_NAME) = "some_value" )`, which will fail to compile instead in cases where the macro doesn't exist. + - If a variable is used as the associative key, it *must* be wrapped in parens, or it will be used as a string key. \ No newline at end of file diff --git a/code/__defines/_planes+layers.dm b/code/__defines/_planes+layers.dm index 335eb97ec2a6..7e207ad9f5ea 100644 --- a/code/__defines/_planes+layers.dm +++ b/code/__defines/_planes+layers.dm @@ -178,7 +178,7 @@ What is the naming convention for planes or layers? #define ABOVE_LIGHTING_PLANE 4 // laser beams, etc. that shouldn't be affected by darkness #define ABOVE_LIGHTING_LAYER 1 #define BEAM_PROJECTILE_LAYER 2 - #define SUPERMATTER_WALL_LAYER 3 + #define SUBSPACE_WALL_LAYER 3 #define OBFUSCATION_LAYER 4 #define FULLSCREEN_PLANE 5 // for fullscreen overlays that do not cover the hud. diff --git a/code/__defines/gamemode.dm b/code/__defines/gamemode.dm index 94c9d41639ae..680717a8e9ad 100644 --- a/code/__defines/gamemode.dm +++ b/code/__defines/gamemode.dm @@ -33,31 +33,6 @@ #define DEFAULT_TELECRYSTAL_AMOUNT 130 #define IMPLANT_TELECRYSTAL_AMOUNT(x) (round(x * 0.49)) // If this cost is ever greater than half of DEFAULT_TELECRYSTAL_AMOUNT then it is possible to buy more TC than you spend -// SPELL FLAGS -#define Z2NOCAST BITFLAG(0) //if this is added, the spell can't be cast at centcomm -#define INCLUDEUSER BITFLAG(1) //does the spell include the caster in its target selection? -#define IGNOREDENSE BITFLAG(2) //are dense turfs ignored in selection? - -//End split flags -#define CONSTRUCT_CHECK BITFLAG(12) //used by construct spells - checks for nullrods -#define NO_BUTTON BITFLAG(13) //spell won't show up in the HUD with this - -//invocation -#define SpI_SHOUT "shout" -#define SpI_WHISPER "whisper" -#define SpI_EMOTE "emote" -#define SpI_NONE "none" - -//upgrading -#define Sp_SPEED "speed" -#define Sp_POWER "power" -#define Sp_TOTAL "total" - -//casting costs -#define Sp_RECHARGE "recharge" -#define Sp_CHARGES "charges" -#define Sp_HOLDVAR "holdervar" - //Voting-related #define VOTE_PROCESS_ABORT 1 #define VOTE_PROCESS_COMPLETE 2 diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm index 25f2ed8c213c..d6591b17acf4 100644 --- a/code/__defines/machinery.dm +++ b/code/__defines/machinery.dm @@ -72,7 +72,6 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called #define STAGE_THREE 5 #define STAGE_FOUR 7 #define STAGE_FIVE 9 -#define STAGE_SUPER 11 // NanoUI flags #define STATUS_INTERACTIVE 2 // GREEN Visability @@ -103,21 +102,6 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called #define ATMOS_DEFAULT_VOLUME_MIXER 500 // L. #define ATMOS_DEFAULT_VOLUME_PIPE 70 // L. -// These are used by supermatter and supermatter monitor program, mostly for UI updating purposes. Higher should always be worse! -#define SUPERMATTER_ERROR -1 // Unknown status, shouldn't happen but just in case. -#define SUPERMATTER_INACTIVE 0 // No or minimal energy -#define SUPERMATTER_NORMAL 1 // Normal operation -#define SUPERMATTER_NOTIFY 2 // Ambient temp > 80% of CRITICAL_TEMPERATURE -#define SUPERMATTER_WARNING 3 // Ambient temp > CRITICAL_TEMPERATURE OR integrity damaged -#define SUPERMATTER_DANGER 4 // Integrity < 50% -#define SUPERMATTER_EMERGENCY 5 // Integrity < 25% -#define SUPERMATTER_DELAMINATING 6 // Pretty obvious. - -#define SUPERMATTER_DATA_EER "Relative EER" -#define SUPERMATTER_DATA_TEMPERATURE "Temperature" -#define SUPERMATTER_DATA_PRESSURE "Pressure" -#define SUPERMATTER_DATA_EPR "Chamber EPR" - // Scrubber modes #define SCRUBBER_SIPHON "siphon" #define SCRUBBER_SCRUB "scrub" diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 5bf9a5b371ac..55fbbecd14d4 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -370,3 +370,11 @@ #define RADIAL_LABELS_NONE 0 #define RADIAL_LABELS_OFFSET 1 #define RADIAL_LABELS_CENTERED 2 + +#define CRAYON_DRAW_RUNE "rune" +#define CRAYON_DRAW_GRAFFITI "graffiti" +#define CRAYON_DRAW_LETTER "letter" +#define CRAYON_DRAW_ARROW "arrow" + +// Default UI style applied to client prefs. +#define DEFAULT_UI_STYLE /decl/ui_style/midnight diff --git a/code/_helpers/time.dm b/code/_helpers/time.dm index f53718da51be..90210911f1ef 100644 --- a/code/_helpers/time.dm +++ b/code/_helpers/time.dm @@ -72,6 +72,35 @@ var/global/next_duration_update = 0 var/global/last_round_duration = 0 var/global/round_start_time = 0 +/proc/ticks2shortreadable(tick_time, separator = ":") + var/hours = round(tick_time / (1 HOUR)) + var/minutes = round((tick_time % (1 HOUR)) / (1 MINUTE)) + var/seconds = round((tick_time % (1 MINUTE)) / (1 SECOND)) + var/out = list() + + if(hours > 0) + out += "[hours]" + + if(minutes > 0) + if(minutes < 10 && hours > 0) + out += "0[minutes]" + else + out += "[minutes]" + else if(hours > 0) + out += "00" + + if(seconds > 0) + if(seconds < 10 && (minutes > 0 || hours > 0)) + out += "0[seconds]" + else + out += "[seconds]" + else if(minutes > 0 || hours > 0) + out += "00" + + if(length(out)) + return jointext(out, separator) + return null + /proc/ticks2readable(tick_time) var/hours = round(tick_time / (1 HOUR)) var/minutes = round((tick_time % (1 HOUR)) / (1 MINUTE)) diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 8fa2950b1b9e..6a254d2fa03a 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -282,10 +282,17 @@ return A.CtrlClick(src) /atom/proc/CtrlClick(var/mob/user) + if(loc == user) + var/decl/interaction_handler/handler = get_quick_interaction_handler(user) + if(handler) + var/using_item = user.get_active_held_item() || user.get_usable_hand_slot_organ() + if(handler.is_possible(src, user, using_item)) + return handler.invoked(src, user, using_item) return FALSE /atom/movable/CtrlClick(var/mob/living/user) - return try_make_grab(user, defer_hand = TRUE) || ..() + if(!(. = ..()) && loc != user) + return try_make_grab(user, defer_hand = TRUE) || ..() /* Alt click @@ -295,7 +302,7 @@ A.AltClick(src) /atom/proc/AltClick(var/mob/user) - if(try_handle_interactions(user, get_alt_interactions(user), user?.get_active_held_item())) + if(try_handle_interactions(user, get_alt_interactions(user), user?.get_active_held_item(), check_alt_interactions = TRUE)) return TRUE if(user?.get_preference_value(/datum/client_preference/show_turf_contents) == PREF_ALT_CLICK) . = show_atom_list_for_turf(user, get_turf(src)) diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index f13491832f42..5ac7ac42bd02 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -16,21 +16,21 @@ #define ui_entire_screen "WEST,SOUTH to EAST,NORTH" #define ui_center_fullscreen "CENTER-7,CENTER-7" -//Lower left, persistant menu +//Lower left, persistent menu #define ui_inventory "LEFT:6,BOTTOM:5" -//Lower center, persistant menu +//Lower center, persistent menu #define ui_sstore1 "LEFT+2:10,BOTTOM:5" -#define ui_id "LEFT+3:12,BOTTOM:5" -#define ui_belt "LEFT+4:14,BOTTOM:5" -#define ui_back "CENTER-2:14,BOTTOM:5" +#define ui_back "LEFT+3:22,BOTTOM:5" +#define ui_id "LEFT+4:26,BOTTOM:5" +#define ui_belt "RIGHT-5:16,BOTTOM:5" #define ui_rhand "CENTER-1:16,BOTTOM:5" #define ui_lhand "CENTER:16,BOTTOM:5" #define ui_equip "CENTER-1:16,BOTTOM+1:5" #define ui_swaphand1 "CENTER-1:16,BOTTOM+1:5" #define ui_swaphand2 "CENTER:16,BOTTOM+1:5" -#define ui_storage1 "CENTER+1:16,BOTTOM:5" -#define ui_storage2 "CENTER+2:16,BOTTOM:5" +#define ui_storage1 "RIGHT-3:16,BOTTOM:5" +#define ui_storage2 "RIGHT-4:16,BOTTOM:5" #define ui_alien_head "CENTER-3:12,BOTTOM:5" //aliens #define ui_alien_oclothing "CENTER-2:14,BOTTOM:5"//aliens @@ -48,13 +48,13 @@ #define ui_construct_fire "RIGHT-1:16,CENTER+1:13" //above health, slightly to the left #define ui_construct_pull "RIGHT-1:28,BOTTOM+1:10" //above the zone selector icon -//Lower right, persistant menu +//Lower right, persistent menu #define ui_dropbutton "RIGHT-4:22,BOTTOM:5" #define ui_drop_throw "RIGHT-1:28,BOTTOM+1:7" #define ui_pull_resist "RIGHT-2:26,BOTTOM+1:7" -#define ui_acti "RIGHT-2:26,BOTTOM:5" -#define ui_movi "RIGHT-3:24,BOTTOM:5" -#define ui_attack_selector "RIGHT-3:24,BOTTOM+1:6" +#define ui_acti "CENTER,BOTTOM:5" +#define ui_movi "RIGHT-2:24,BOTTOM:5" +#define ui_attack_selector "RIGHT-2:27,BOTTOM+2:9" #define ui_zonesel "RIGHT-1:28,BOTTOM:5" #define ui_acti_alt "RIGHT-1:28,BOTTOM:5" //alternative intent switcher for when the interface is hidden #define ui_stamina "RIGHT-3:24,BOTTOM+1:5" diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 10b3ccf93c1b..34ee968ab77c 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -13,6 +13,8 @@ hud_used = initial(hud_used) if(ispath(hud_used)) hud_used = new hud_used(src) + if(istype(hud_used)) + hud_used.refresh_hud_icons() refresh_lighting_master() /datum/hud @@ -22,7 +24,7 @@ var/inventory_shown = TRUE //the inventory var/hotkey_ui_hidden = FALSE //This is to hide the buttons that can be used via hotkeys. (hotkeybuttons list of buttons) - var/default_ui_style = /decl/ui_style/midnight + var/default_ui_style = DEFAULT_UI_STYLE var/list/alerts @@ -45,6 +47,10 @@ instantiate() ..() +/datum/hud/proc/refresh_hud_icons() + for(var/obj/screen/elem in mymob?.client?.screen) + elem.queue_icon_update() + /datum/hud/Destroy() . = ..() stamina_bar = null @@ -68,19 +74,19 @@ /datum/hud/proc/hide_inventory() inventory_shown = FALSE hidden_inventory_update() - persistant_inventory_update() + persistent_inventory_update() /datum/hud/proc/show_inventory() inventory_shown = TRUE hidden_inventory_update() - persistant_inventory_update() + persistent_inventory_update() /datum/hud/proc/hidden_inventory_update() var/decl/species/species = mymob?.get_species() if(istype(species?.species_hud)) refresh_inventory_slots(species.species_hud.hidden_slots, (inventory_shown && hud_shown)) -/datum/hud/proc/persistant_inventory_update() +/datum/hud/proc/persistent_inventory_update() var/decl/species/species = mymob?.get_species() if(istype(species?.species_hud)) refresh_inventory_slots(species.species_hud.persistent_slots, hud_shown) @@ -138,6 +144,9 @@ . = available_styles[1] /datum/hud/proc/get_ui_color() + var/decl/ui_style/ui_style = get_ui_style_data() + if(!ui_style?.use_ui_color) + return COLOR_WHITE return mymob?.client?.prefs?.UI_style_color || COLOR_WHITE /datum/hud/proc/get_ui_alpha() @@ -172,25 +181,17 @@ break if(!inv_box) - inv_box = new /obj/screen/inventory(null, mymob, ui_style, ui_color, ui_alpha, UI_ICON_HANDS) + inv_box = new /obj/screen/inventory/hand(null, mymob, ui_style, ui_color, ui_alpha, UI_ICON_HANDS) else inv_box.set_ui_style(ui_style, UI_ICON_HANDS) inv_box.color = ui_color inv_box.alpha = ui_alpha - inv_box.SetName(hand_tag) - inv_box.icon_state = "hand_base" - - inv_box.cut_overlays() - inv_box.add_overlay("hand_[inv_slot.hand_overlay || hand_tag]", TRUE) - if(inv_slot.ui_label) - inv_box.add_overlay("hand_[inv_slot.ui_label]", TRUE) - inv_box.update_icon() + LAZYDISTINCTADD(hand_hud_objects, inv_box) + inv_box.SetName(hand_tag) inv_box.slot_id = hand_tag - inv_box.appearance_flags |= KEEP_TOGETHER - - LAZYDISTINCTADD(hand_hud_objects, inv_box) + inv_box.update_icon() // Clear held item boxes with no held slot. for(var/obj/screen/inventory/inv_box in hand_hud_objects) @@ -201,7 +202,7 @@ qdel(inv_box) // Rebuild offsets for the hand elements. - var/hand_y_offset = 5 + var/hand_y_offset = 21 var/list/elements = hand_hud_objects?.Copy() while(length(elements)) var/copy_index = min(length(elements), 2)+1 @@ -363,7 +364,7 @@ client.screen += zone_sel //This one is a special snowflake hud_used.hidden_inventory_update() - hud_used.persistant_inventory_update() + hud_used.persistent_inventory_update() update_action_buttons() //Similar to minimize_hud() but keeps zone_sel, gun_setting_icon, and healths. @@ -400,7 +401,7 @@ hud_used.action_intent.screen_loc = ui_acti //Restore intent selection to the original position hud_used.hidden_inventory_update() - hud_used.persistant_inventory_update() + hud_used.persistent_inventory_update() update_action_buttons() /client/proc/reset_click_catchers() diff --git a/code/_onclick/hud/screen/_screen.dm b/code/_onclick/hud/screen/_screen.dm index fc921c67cee2..4e891170d7bd 100644 --- a/code/_onclick/hud/screen/_screen.dm +++ b/code/_onclick/hud/screen/_screen.dm @@ -24,6 +24,9 @@ var/ui_style_category /// Set to false for screen objects that do not rely on UI style to set their icon. var/requires_ui_style = TRUE + /// Whether or not we look for/draw an additional detail overlay. + var/apply_screen_overlay = TRUE + /// Reference to our last set ui_style /obj/screen/Initialize(mapload, mob/_owner, decl/ui_style/ui_style, ui_color, ui_alpha, ui_cat) @@ -52,8 +55,13 @@ color = ui_color if(!isnull(ui_alpha)) alpha = ui_alpha + return ..() +/obj/screen/proc/get_owner_ui_style() + var/mob/owner = owner_ref?.resolve() + return (istype(owner) && istype(owner.hud_used)) ? owner.hud_used.get_ui_style_data() : null + /obj/screen/get_color() return color @@ -68,18 +76,21 @@ ui_style_category = ui_cat if(istype(ui_style) && ui_style_category) icon = ui_style.get_icon(ui_style_category) + update_icon() /obj/screen/Destroy() - if(owner_ref) - var/mob/owner = owner_ref.resolve() - if(istype(owner) && owner?.client?.screen) - owner.client.screen -= src + var/mob/owner = owner_ref?.resolve() + if(istype(owner) && owner.client?.screen) + owner.client.screen -= src return ..() /obj/screen/proc/handle_click(mob/user, params) return TRUE /obj/screen/Click(location, control, params) + var/list/paramlist = params2list(params) + if(paramlist["shift"]) + return examine(usr, 0) if(ismob(usr) && usr.client && usr.canClick() && (!user_incapacitation_flags || !usr.incapacitated(user_incapacitation_flags))) return handle_click(usr, params) return FALSE @@ -89,3 +100,25 @@ /obj/screen/check_mousedrop_interactivity(var/mob/user) return user.client && (src in user.client.screen) + +/obj/screen/on_update_icon() + rebuild_screen_overlays() + compile_overlays() + +/obj/screen/proc/get_screen_overlay_state() + return icon_state + +/obj/screen/proc/rebuild_screen_overlays() + SHOULD_CALL_PARENT(TRUE) + cut_overlays() + if(!apply_screen_overlay) + return + var/check_for_state = "[get_screen_overlay_state()]-overlay" + if(!check_state_in_icon(check_for_state, icon)) + return + var/decl/ui_style/ui_style = get_owner_ui_style() + if(ui_style?.use_overlay_color) + var/mob/living/owner = owner_ref?.resolve() + add_overlay(overlay_image(icon, check_for_state, istype(owner) ? (owner?.client?.prefs.UI_style_highlight_color || COLOR_WHITE) : COLOR_WHITE, RESET_COLOR)) + else + add_overlay(check_for_state) diff --git a/code/_onclick/hud/screen/screen_abilities.dm b/code/_onclick/hud/screen/screen_abilities.dm deleted file mode 100644 index 414458af058e..000000000000 --- a/code/_onclick/hud/screen/screen_abilities.dm +++ /dev/null @@ -1,288 +0,0 @@ -/obj/screen/ability_master - name = "Abilities" - icon = 'icons/mob/screen/spells.dmi' - icon_state = "grey_spell_ready" - screen_loc = ui_ability_master - requires_ui_style = FALSE - var/list/obj/screen/ability/ability_objects = list() - var/list/obj/screen/ability/spell_objects = list() - var/showing = FALSE // If we're 'open' or not. - var/const/abilities_per_row = 7 - var/open_state = "master_open" // What the button looks like when it's 'open', showing the other buttons. - var/closed_state = "master_closed" // Button when it's 'closed', hiding everything else. - -/obj/screen/ability_master/Initialize(mapload, mob/_owner, ui_style, ui_color, ui_alpha, ui_cat) - . = ..() - if(. != INITIALIZE_HINT_QDEL) - update_abilities(0, _owner) - -/obj/screen/ability_master/Destroy() - // Get rid of the ability objects. - remove_all_abilities() - ability_objects.Cut() - // After that, remove ourselves from the mob seeing us, so we can qdel cleanly. - var/mob/owner = owner_ref?.resolve() - if(istype(owner) && owner.ability_master == src) - owner.ability_master = null - return ..() - -/obj/screen/ability_master/handle_mouse_drop(atom/over, mob/user, params) - if(showing) - return FALSE - . = ..() - -/obj/screen/ability_master/handle_click(mob/user, params) - if(length(ability_objects)) // If we're empty for some reason. - toggle_open() - -/obj/screen/ability_master/proc/toggle_open(var/forced_state = 0) - var/mob/owner = owner_ref?.resolve() - if(!istype(owner) || QDELETED(owner)) - return - if(showing && (forced_state != 2)) // We are closing the ability master, hide the abilities. - if(owner?.client) - for(var/obj/screen/ability/O in ability_objects) - owner.client.screen -= O -// O.handle_icon_updates = 0 - showing = 0 - overlays.len = 0 - overlays.Add(closed_state) - else if(forced_state != 1) // We're opening it, show the icons. - open_ability_master() - update_abilities(1) - showing = 1 - overlays.len = 0 - overlays.Add(open_state) - update_icon() - -/obj/screen/ability_master/proc/open_ability_master() - - var/client/owner_client - var/mob/owner = owner_ref?.resolve() - if(istype(owner) && !QDELETED(owner)) - owner_client = owner.client - - for(var/i = 1 to length(ability_objects)) - var/obj/screen/ability/A = ability_objects[i] - var/row = round(i/abilities_per_row) - A.screen_loc = "RIGHT-[(i-(row*abilities_per_row))+2]:16,TOP-[row+1]:16" - if(owner_client) - owner_client.screen += A - -/obj/screen/ability_master/proc/update_abilities(forced = 0, mob/user) - update_icon() - if(user && user.client) - if(!(src in user.client.screen)) - user.client.screen += src - var/i = 1 - for(var/obj/screen/ability/ability in ability_objects) - ability.update_icon(forced) - ability.maptext = "[i]" // Slot number - i++ - -/obj/screen/ability_master/on_update_icon() - if(ability_objects.len) - set_invisibility(INVISIBILITY_NONE) - else - set_invisibility(INVISIBILITY_ABSTRACT) - -/obj/screen/ability_master/proc/add_ability(var/name_given) - if(!name_given) - return - var/obj/screen/ability/new_button = new /obj/screen/ability - new_button.ability_master = src - new_button.SetName(name_given) - new_button.ability_icon_state = name_given - new_button.update_icon(1) - ability_objects.Add(new_button) - var/mob/living/owner = owner_ref?.resolve() - if(istype(owner) && !QDELETED(owner) && owner.client) - toggle_open(2) //forces the icons to refresh on screen - -/obj/screen/ability_master/proc/remove_ability(var/obj/screen/ability/ability) - if(!ability) - return - ability_objects.Remove(ability) - if(istype(ability,/obj/screen/ability/spell)) - spell_objects.Remove(ability) - qdel(ability) - - - if(ability_objects.len) - toggle_open(showing + 1) - update_icon() -// else -// qdel(src) - -/obj/screen/ability_master/proc/remove_all_abilities() - for(var/obj/screen/ability/A in ability_objects) - remove_ability(A) - -/obj/screen/ability_master/proc/get_ability_by_name(name_to_search) - for(var/obj/screen/ability/A in ability_objects) - if(A.name == name_to_search) - return A - return null - -/obj/screen/ability_master/proc/get_ability_by_instance(var/obj/instance/) - for(var/obj/screen/ability/obj_based/O in ability_objects) - if(O.object == instance) - return O - return null - -/obj/screen/ability_master/proc/get_ability_by_spell(var/spell/s) - for(var/screen in spell_objects) - var/obj/screen/ability/spell/S = screen - if(S.spell == s) - return S - return null - -/obj/screen/ability_master/proc/synch_spells_to_mind(var/datum/mind/M) - if(!M) - return - LAZYINITLIST(M.learned_spells) - for(var/obj/screen/ability/spell/screen in spell_objects) - var/spell/S = screen.spell - M.learned_spells |= S - -///////////ACTUAL ABILITIES//////////// -//This is what you click to do things// -/////////////////////////////////////// -/obj/screen/ability - icon = 'icons/mob/screen/spells.dmi' - icon_state = "grey_spell_base" - maptext_x = 3 - requires_owner = FALSE - requires_ui_style = FALSE - var/background_base_state = "grey" - var/ability_icon_state = null - var/obj/screen/ability_master/ability_master - -/obj/screen/ability/Destroy() - if(ability_master) - ability_master.ability_objects -= src - var/mob/owner = ability_master.owner_ref?.resolve() - if(istype(owner) && owner.client) - owner.client.screen -= src - if(ability_master && !ability_master.ability_objects.len) - ability_master.update_icon() -// qdel(ability_master) - ability_master = null - return ..() - -/obj/screen/ability/on_update_icon() - overlays.Cut() - icon_state = "[background_base_state]_spell_base" - - overlays += ability_icon_state - -/obj/screen/ability/handle_click(mob/user, params) - activate() - -// Makes the ability be triggered. The subclasses of this are responsible for carrying it out in whatever way it needs to. -/obj/screen/ability/proc/activate() - to_world("[src] had activate() called.") - return - -/////////Obj Abilities//////// -//Buttons to trigger objects// -////////////////////////////// - -/obj/screen/ability/obj_based - var/obj/object = null - -/obj/screen/ability/obj_based/activate() - if(object) - object.Click() - -/obj/screen/ability/spell - var/spell/spell - var/spell_base - var/last_charge = 0 - var/icon/last_charged_icon - -/obj/screen/ability/spell/Destroy() - if(spell) - spell.connected_button = null - spell = null - return ..() - -/obj/screen/ability_master/proc/add_spell(var/spell/spell) - if(!spell) return - - if(spell.spell_flags & NO_BUTTON) //no button to add if we don't get one - return - - if(get_ability_by_spell(spell)) - return - - var/obj/screen/ability/spell/A = new(null) - A.ability_master = src - A.spell = spell - A.SetName(spell.name) - - if(!spell.override_base) //if it's not set, we do basic checks - A.spell_base = "const" //construct spells - else - A.spell_base = spell.override_base - A.update_charge(1) - spell_objects.Add(A) - ability_objects.Add(A) - var/mob/owner = owner_ref?.resolve() - if(istype(owner) && !QDELETED(owner) && owner.client) - toggle_open(2) //forces the icons to refresh on screen - -/obj/screen/ability_master/proc/update_spells(var/forced = 0) - for(var/obj/screen/ability/spell/spell in spell_objects) - spell.update_charge(forced) - -/obj/screen/ability/spell/proc/update_charge(var/forced_update = 0) - if(!spell) - qdel(src) - return - - if(last_charge == spell.charge_counter && !forced_update) - return //nothing to see here - - overlays -= spell.hud_state - - if(spell.charge_type == Sp_RECHARGE || spell.charge_type == Sp_CHARGES) - if(spell.charge_counter < spell.charge_max) - icon_state = "[spell_base]_spell_base" - if(spell.charge_counter > 0) - var/icon/partial_charge = icon(src.icon, "[spell_base]_spell_ready") - partial_charge.Crop(1, 1, partial_charge.Width(), round(partial_charge.Height() * spell.charge_counter / spell.charge_max)) - overlays += partial_charge - if(last_charged_icon) - overlays -= last_charged_icon - last_charged_icon = partial_charge - else if(last_charged_icon) - overlays -= last_charged_icon - last_charged_icon = null - else - icon_state = "[spell_base]_spell_ready" - if(last_charged_icon) - overlays -= last_charged_icon - else - icon_state = "[spell_base]_spell_ready" - - overlays += spell.hud_state - - last_charge = spell.charge_counter - - overlays -= "silence" - if(spell.silenced) - overlays += "silence" - -/obj/screen/ability/spell/on_update_icon(var/forced = 0) - update_charge(forced) - return - -/obj/screen/ability/spell/activate() - spell.perform(usr) - -/obj/screen/ability_master/proc/silence_spells(var/amount) - for(var/obj/screen/ability/spell/spell in spell_objects) - spell.spell.silenced = amount - spell.spell.process() - spell.update_charge(1) diff --git a/code/_onclick/hud/screen/screen_action_button.dm b/code/_onclick/hud/screen/screen_action_button.dm index 33bf849cb9c7..df79fa29ce41 100644 --- a/code/_onclick/hud/screen/screen_action_button.dm +++ b/code/_onclick/hud/screen/screen_action_button.dm @@ -14,6 +14,7 @@ return FALSE /obj/screen/action_button/on_update_icon() + ..() if(!action) return icon = action.background_icon @@ -72,7 +73,6 @@ update_icon() user.update_action_buttons() -/obj/screen/action_button/hide_toggle/on_update_icon() - cut_overlays() +/obj/screen/action_button/hide_toggle/rebuild_screen_overlays() + ..() add_overlay(hidden ? "show" : "hide") - compile_overlays() diff --git a/code/_onclick/hud/screen/screen_attack_selector.dm b/code/_onclick/hud/screen/screen_attack_selector.dm index ea27e11ca3e9..537d2ccce389 100644 --- a/code/_onclick/hud/screen/screen_attack_selector.dm +++ b/code/_onclick/hud/screen/screen_attack_selector.dm @@ -28,6 +28,7 @@ return TRUE /obj/screen/default_attack_selector/on_update_icon() + ..() var/mob/living/human/owner = owner_ref?.resolve() var/decl/natural_attack/attack = istype(owner) && owner.default_attack icon_state = attack?.selector_icon_state || "attack_none" diff --git a/code/_onclick/hud/screen/screen_cataloguer.dm b/code/_onclick/hud/screen/screen_cataloguer.dm index 6fc95896bfa8..bb0965dac408 100644 --- a/code/_onclick/hud/screen/screen_cataloguer.dm +++ b/code/_onclick/hud/screen/screen_cataloguer.dm @@ -31,8 +31,8 @@ QDEL_NULL(holder_image) return ..() -/obj/screen/scan_radius/on_update_icon() - cut_overlays() +/obj/screen/scan_radius/rebuild_screen_overlays() + ..() if(scan_range <= 1) add_overlay("single") else @@ -79,5 +79,3 @@ I.pixel_x = world.icon_size * i I.pixel_y = pixel_bound add_overlay(I) - - compile_overlays() diff --git a/code/_onclick/hud/screen/screen_exosuit.dm b/code/_onclick/hud/screen/screen_exosuit.dm index 5677d2d93bcb..ad9171ed446d 100644 --- a/code/_onclick/hud/screen/screen_exosuit.dm +++ b/code/_onclick/hud/screen/screen_exosuit.dm @@ -3,6 +3,7 @@ icon = 'icons/mecha/mech_hud.dmi' icon_state = "base" requires_ui_style = FALSE + apply_screen_overlay = FALSE var/initial_maptext var/height = 14 @@ -317,7 +318,8 @@ var/mob/living/exosuit/owner = get_owning_exosuit() if(owner) toggled = owner.hatch_closed - . = ..() + . = ..() + if(owner) if(toggled) maptext = MECH_UI_STYLE("OPEN") maptext_x = 5 diff --git a/code/_onclick/hud/screen/screen_gun.dm b/code/_onclick/hud/screen/screen_gun.dm index fdf77245d1c4..86bba4206e74 100644 --- a/code/_onclick/hud/screen/screen_gun.dm +++ b/code/_onclick/hud/screen/screen_gun.dm @@ -2,8 +2,15 @@ icon = 'icons/mob/screen/styles/midnight/fire_intent.dmi' dir = SOUTH abstract_type = /obj/screen/gun + var/base_icon_state var/toggle_flag +/obj/screen/gun/on_update_icon() + if(toggle_flag && base_icon_state) + var/mob/living/owner = owner_ref?.resolve() + icon_state = "[base_icon_state][!!(istype(owner) && owner.aiming && (owner.aiming.target_permissions & toggle_flag))]" + ..() + /obj/screen/gun/handle_click(mob/user, params) if(isliving(user)) var/mob/living/shooter = user @@ -17,26 +24,35 @@ /obj/screen/gun/move name = "Allow Movement" icon_state = "no_walk1" + base_icon_state = "no_walk" screen_loc = ui_gun2 toggle_flag = TARGET_CAN_MOVE /obj/screen/gun/item name = "Allow Item Use" icon_state = "no_item1" + base_icon_state = "no_item" screen_loc = ui_gun1 toggle_flag = TARGET_CAN_CLICK /obj/screen/gun/radio name = "Disallow Radio Use" icon_state = "no_radio1" + base_icon_state = "no_radio" screen_loc = ui_gun4 toggle_flag = TARGET_CAN_RADIO /obj/screen/gun/mode name = "Toggle Gun Mode" icon_state = "gun0" + base_icon_state = "gun" screen_loc = ui_gun_select +/obj/screen/gun/mode/on_update_icon() + var/mob/living/owner = owner_ref?.resolve() + icon_state = "[base_icon_state][!!(istype(owner) && owner.aiming?.active)]" + ..() + /obj/screen/gun/mode/handle_click(mob/user, params) if(..()) var/mob/living/shooter = user diff --git a/code/_onclick/hud/screen/screen_intent.dm b/code/_onclick/hud/screen/screen_intent.dm index 4682cc14836c..ca75b836812a 100644 --- a/code/_onclick/hud/screen/screen_intent.dm +++ b/code/_onclick/hud/screen/screen_intent.dm @@ -1,67 +1,117 @@ -/obj/screen/intent - name = "intent" - icon = 'icons/mob/screen/styles/intents.dmi' - icon_state = "intents" - screen_loc = ui_acti +// Sub-element used for clickable intent selection. +/obj/screen/intent_button + layer = FLOAT_LAYER + plane = FLOAT_PLANE + icon = 'icons/screen/intents.dmi' + icon_state = "blank" requires_ui_style = FALSE + screen_loc = null // Technically a screen element, but we use vis_contents to draw them. + var/obj/screen/intent/parent + var/decl/intent/intent + var/selected + +/obj/screen/intent_button/Initialize(mapload, mob/_owner, decl/ui_style/ui_style, ui_color, ui_alpha, ui_cat, intent_owner) + parent = intent_owner + . = ..() + +/obj/screen/intent_button/Destroy() + parent = null + intent = null + return ..() + +/obj/screen/intent_button/proc/set_selected(decl/intent/_intent) + intent = _intent + selected = TRUE + update_icon() + +/obj/screen/intent_button/proc/set_deselected(decl/intent/_intent) + intent = _intent + selected = FALSE + update_icon() + +/obj/screen/intent_button/handle_click(mob/user, params) + . = ..() + if(. && intent && parent) + parent.set_intent(intent) + +/obj/screen/intent_button/examine(mob/user, distance) + SHOULD_CALL_PARENT(FALSE) + if(desc) + to_chat(user, desc) + +/obj/screen/intent_button/on_update_icon() + . = ..() + screen_loc = null + if(intent) + name = intent.name + desc = intent.desc + icon = intent.icon + icon_state = selected ? intent.icon_state : "[intent.icon_state]_off" + +/obj/screen/intent + name = "intent" + icon = 'icons/screen/intents.dmi' + icon_state = "blank" + screen_loc = ui_acti + requires_ui_style = FALSE + apply_screen_overlay = FALSE + var/intent_width = 16 + var/intent_height = 16 + var/list/intent_selectors /obj/screen/intent/Initialize(mapload, mob/_owner, decl/ui_style/ui_style, ui_color, ui_alpha, ui_cat) . = ..() update_icon() + // Hide from right-click. + name = "" + verbs.Cut() -/obj/screen/intent/handle_click(mob/user, params) +/obj/screen/intent/Destroy() + QDEL_NULL(intent_selectors) + vis_contents.Cut() + return ..() + +/obj/screen/intent/proc/set_intent(decl/intent/intent) var/mob/owner = owner_ref?.resolve() - if(!istype(owner) || QDELETED(owner) || user != owner || !params) - return - params = params2list(params) - if(owner.set_intent(get_intent_by_position(owner.get_available_intents(), text2num(params["icon-x"]), text2num(params["icon-y"])))) + if(istype(owner) && istype(intent)) + owner.set_intent(intent) update_icon() -/obj/screen/intent/proc/get_intent_by_position(list/intents, icon_x, icon_y) - if(icon_y <= 16) - if(icon_x <= 16) - return intents[1] - return intents[2] - else if(icon_x <= 16) - return intents[3] - return intents[4] - -/obj/screen/intent/proc/apply_intent_overlay_offset(image/overlay, index) - switch(index) - if(2) - overlay.pixel_x = 16 - if(3) - overlay.pixel_y = 16 - if(4) - overlay.pixel_x = 16 - overlay.pixel_y = 16 +/obj/screen/intent/proc/apply_intent_button_offset(atom/intent_button, index, intent_count) + intent_button.pixel_z = 0 + intent_button.pixel_w = 0 + intent_button.pixel_y = 0 + intent_button.pixel_x = -((intent_count * intent_width)/2) + ((index-1) * intent_width) + +/obj/screen/intent/proc/get_intent_button(index) + . = (index >= 1 && index <= length(intent_selectors)) ? intent_selectors[index] : null + if(!.) + . = new /obj/screen/intent_button(null, owner_ref?.resolve(), null, null, null, null, src) + LAZYADD(intent_selectors, .) /obj/screen/intent/on_update_icon() - cut_overlays() + ..() + var/mob/owner = owner_ref?.resolve() if(!istype(owner) || QDELETED(owner)) return + var/decl/intent/owner_intent = owner.get_intent() - var/i = 0 - var/image/I - for(var/decl/intent/intent as anything in owner.get_available_intents()) + var/i = 1 + var/list/all_intents = owner.get_available_intents() + for(var/decl/intent/intent as anything in all_intents) + var/obj/screen/intent_button/intent_button = get_intent_button(i) if(intent == owner_intent) - I = image(intent.icon, intent.icon_state) + intent_button.set_selected(intent) else - I = image(intent.icon, "[intent.icon_state]_off") + intent_button.set_deselected(intent) i++ - apply_intent_overlay_offset(I, i) - add_overlay(I) - compile_overlays() + apply_intent_button_offset(intent_button, i, length(all_intents)) + add_vis_contents(intent_button) -/obj/screen/intent/binary - icon = 'icons/mob/screen/styles/intents_wide.dmi' + if(i < length(intent_selectors)) + for(var/index = i+1 to length(intent_selectors)) + remove_vis_contents(intent_selectors[index]) -/obj/screen/intent/binary/get_intent_by_position(list/intents, icon_x, icon_y) - if(icon_y <= 16) - return intents[1] - return intents[2] - -/obj/screen/intent/binary/apply_intent_overlay_offset(image/overlay, index) - if(index == 2) - overlay.pixel_y = 16 +/obj/screen/intent/binary + intent_width = 32 diff --git a/code/_onclick/hud/screen/screen_inventory.dm b/code/_onclick/hud/screen/screen_inventory.dm index 5bacceaeef04..cc4a4835b826 100644 --- a/code/_onclick/hud/screen/screen_inventory.dm +++ b/code/_onclick/hud/screen/screen_inventory.dm @@ -40,19 +40,15 @@ mouse_over_atom_ref = null update_icon() -/obj/screen/inventory/on_update_icon() +/obj/screen/inventory/rebuild_screen_overlays() - cut_overlays() + ..() // Validate our owner still exists. var/mob/owner = owner_ref?.resolve() if(!istype(owner) || QDELETED(owner) || !(src in owner.client?.screen)) return - // Mark our selected hand. - if(owner.get_active_held_item_slot() == slot_id) - add_overlay("hand_selected") - // Mark anything we're potentially trying to equip. var/obj/item/mouse_over_atom = mouse_over_atom_ref?.resolve() if(istype(mouse_over_atom) && !QDELETED(mouse_over_atom) && !owner.get_equipped_item(slot_id)) @@ -65,9 +61,7 @@ MA.pixel_y = mouse_over_atom.default_pixel_y MA.pixel_w = mouse_over_atom.default_pixel_w MA.pixel_z = mouse_over_atom.default_pixel_z + MA.appearance_flags |= (KEEP_TOGETHER | RESET_COLOR) add_overlay(MA) else mouse_over_atom_ref = null - - // UI needs to be responsive so avoid the subsecond update delay. - compile_overlays() diff --git a/code/_onclick/hud/screen/screen_inventory_hands.dm b/code/_onclick/hud/screen/screen_inventory_hands.dm new file mode 100644 index 000000000000..df5784067418 --- /dev/null +++ b/code/_onclick/hud/screen/screen_inventory_hands.dm @@ -0,0 +1,31 @@ +/obj/screen/inventory/hand + icon_state = "hand_base" + +/obj/screen/inventory/hand/on_update_icon() + + ..() + + // Validate our owner still exists. + var/mob/owner = owner_ref?.resolve() + if(!istype(owner) || QDELETED(owner) || !(src in owner.client?.screen)) + return + + var/overlay_color = owner?.client?.prefs.UI_style_highlight_color || COLOR_WHITE + var/decl/ui_style/ui_style = get_owner_ui_style() + if(owner.get_active_held_item_slot() == slot_id) + if(ui_style?.use_overlay_color) + add_overlay(overlay_image(icon, "hand_selected", overlay_color, RESET_COLOR)) + else + add_overlay("hand_selected") + + var/datum/inventory_slot/gripper/inv_slot = owner.get_inventory_slot_datum(slot_id) + if(istype(inv_slot)) + if(ui_style?.use_overlay_color) + add_overlay(overlay_image(icon, "hand_[inv_slot.hand_overlay || slot_id]", overlay_color, RESET_COLOR)) + else + add_overlay("hand_[inv_slot.hand_overlay || slot_id]", TRUE) + if(inv_slot.ui_label) + if(ui_style?.use_overlay_color) + add_overlay(overlay_image(icon, "hand_[inv_slot.ui_label]", overlay_color, RESET_COLOR)) + else + add_overlay("hand_[inv_slot.ui_label]", TRUE) diff --git a/code/_onclick/hud/screen/screen_maneuver.dm b/code/_onclick/hud/screen/screen_maneuver.dm index 203bffc6943f..1a66910e8d51 100644 --- a/code/_onclick/hud/screen/screen_maneuver.dm +++ b/code/_onclick/hud/screen/screen_maneuver.dm @@ -9,7 +9,7 @@ user_living.prepare_maneuver() /obj/screen/maneuver/examine(mob/user, distance) - . = ..() + SHOULD_CALL_PARENT(FALSE) if(!isliving(user)) return var/mob/living/user_living = user @@ -17,3 +17,8 @@ to_chat(src, SPAN_NOTICE("You are prepared to [user_living.prepared_maneuver.name].")) else to_chat(src, SPAN_NOTICE("You are not prepared to perform a maneuver.")) + +/obj/screen/maneuver/on_update_icon() + var/mob/living/owner = owner_ref?.resolve() + icon_state = (istype(owner) && owner.prepared_maneuver) ? "maneuver_on" : "maneuver_off" + ..() diff --git a/code/_onclick/hud/screen/screen_movement.dm b/code/_onclick/hud/screen/screen_movement.dm index e389e554cc59..674882295dda 100644 --- a/code/_onclick/hud/screen/screen_movement.dm +++ b/code/_onclick/hud/screen/screen_movement.dm @@ -1,7 +1,14 @@ /obj/screen/movement name = "movement method" screen_loc = ui_movi + icon_state = "creeping" /obj/screen/movement/handle_click(mob/user, params) if(istype(user)) user.set_next_usable_move_intent() + +/obj/screen/movement/on_update_icon() + var/mob/living/owner = owner_ref?.resolve() + if(istype(owner) && istype(owner.move_intent)) + icon_state = owner.move_intent.hud_icon_state + . = ..() diff --git a/code/_onclick/hud/screen/screen_throw.dm b/code/_onclick/hud/screen/screen_throw.dm index 679018fba8dd..1b4de10e6e87 100644 --- a/code/_onclick/hud/screen/screen_throw.dm +++ b/code/_onclick/hud/screen/screen_throw.dm @@ -6,3 +6,9 @@ /obj/screen/throw_toggle/handle_click(mob/user, params) if(!user.stat && isturf(user.loc) && !user.restrained()) user.toggle_throw_mode() + +/obj/screen/throw_toggle/on_update_icon() + var/mob/living/owner = owner_ref?.resolve() + if(istype(owner)) + icon_state = "act_throw_[owner.in_throw_mode ? "on" : "off"]" + . = ..() diff --git a/code/_onclick/hud/screen/screen_up_hint.dm b/code/_onclick/hud/screen/screen_up_hint.dm index a6e45820115c..5a1a2b796fc1 100644 --- a/code/_onclick/hud/screen/screen_up_hint.dm +++ b/code/_onclick/hud/screen/screen_up_hint.dm @@ -7,3 +7,9 @@ if(isliving(user)) var/mob/living/L = user L.lookup() + +/obj/screen/up_hint/on_update_icon() + var/mob/owner = owner_ref?.resolve() + var/turf/above = istype(owner) ? GetAbove(get_turf(owner)) : null + icon_state = "uphint[!!(istype(above) && TURF_IS_MIMICKING(above))]" + ..() diff --git a/code/_onclick/hud/screen/screen_zone_selector.dm b/code/_onclick/hud/screen/screen_zone_selector.dm index 008d2b902624..0850498b7f2a 100644 --- a/code/_onclick/hud/screen/screen_zone_selector.dm +++ b/code/_onclick/hud/screen/screen_zone_selector.dm @@ -64,10 +64,6 @@ set_selected_zone(new_selecting) return TRUE -/obj/screen/zone_selector/Initialize(mapload, mob/_owner, ui_style, ui_color, ui_alpha) - . = ..() - update_icon() - /obj/screen/zone_selector/proc/set_selected_zone(bodypart) var/old_selecting = selecting selecting = bodypart @@ -75,5 +71,6 @@ update_icon() return TRUE -/obj/screen/zone_selector/on_update_icon() - set_overlays(image('icons/mob/zone_sel.dmi', "[selecting]")) +/obj/screen/zone_selector/rebuild_screen_overlays() + ..() + add_overlay(image('icons/mob/zone_sel.dmi', "[selecting]")) diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 1dbed7ab122e..075995076d43 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -32,6 +32,10 @@ avoid code duplication. This includes items that may sometimes act as a standard // If TRUE, prevent afterattack from running. /atom/proc/attackby(obj/item/used_item, mob/user, var/click_params) + + if(try_handle_interactions(user, get_standard_interactions(user), user?.get_active_held_item(), check_alt_interactions = FALSE)) + return TRUE + if(storage) if(isrobot(user) && (used_item == user.get_active_held_item())) return FALSE //Robots can't store their modules. @@ -39,6 +43,7 @@ avoid code duplication. This includes items that may sometimes act as a standard return FALSE used_item.add_fingerprint(user) return storage.handle_item_insertion(user, used_item, click_params = click_params) + return FALSE /atom/movable/attackby(obj/item/W, mob/user) diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index de135d672c0d..f3d74569b41b 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -25,6 +25,9 @@ if(handle_grab_interaction(user)) return TRUE + if(try_handle_interactions(user, get_standard_interactions(user), user?.get_active_held_item(), check_alt_interactions = FALSE)) + return TRUE + if(!LAZYLEN(climbers) || (user in climbers) || !user.check_dexterity(DEXTERITY_HOLD_ITEM, silent = TRUE)) return FALSE diff --git a/code/controllers/subsystems/jobs.dm b/code/controllers/subsystems/jobs.dm index 58e71e52d0d1..28244f810e9d 100644 --- a/code/controllers/subsystems/jobs.dm +++ b/code/controllers/subsystems/jobs.dm @@ -413,7 +413,7 @@ SUBSYSTEM_DEF(jobs) /decl/loadout_option/proc/is_permitted(mob/living/wearer, datum/job/job) if(!istype(wearer)) return FALSE - if(allowed_roles && !(job.type in allowed_roles)) + if(allowed_roles && (!job || !(job.type in allowed_roles))) return FALSE if(allowed_branches) if(!ishuman(wearer)) @@ -441,7 +441,7 @@ SUBSYSTEM_DEF(jobs) var/decl/loadout_option/G = decls_repository.get_decl_by_id_or_var(thing, /decl/loadout_option) if(!istype(G)) continue - if(!G.is_permitted(H)) + if(!G.is_permitted(H, job)) to_chat(H, SPAN_WARNING("Your current species, job, branch, skills or whitelist status does not permit you to spawn with [thing]!")) continue if(!G.slot || !G.spawn_on_mob(H, H.client.prefs.Gear()[G.uid])) diff --git a/code/datums/extensions/abilities/abilities.dm b/code/datums/extensions/abilities/abilities.dm index 3995c524dc4a..21e02b0126b5 100644 --- a/code/datums/extensions/abilities/abilities.dm +++ b/code/datums/extensions/abilities/abilities.dm @@ -26,7 +26,7 @@ /// Clicking a grab on the currently grabbed mob. /datum/extension/abilities/proc/do_grabbed_invocation(atom/target) - if(isliving(holder) && istype(target) && LAZYLEN(ability_handlers)) + if(isliving(holder) && istype(target) && LAZYLEN(ability_handlers) && !istype(target, /obj/screen)) for(var/datum/ability_handler/handler in ability_handlers) if(handler.can_do_grabbed_invocation(holder, target) && handler.do_grabbed_invocation(holder, target)) return TRUE @@ -34,7 +34,7 @@ /// Clicking an adjacent target (UnarmedAttack()) /datum/extension/abilities/proc/do_melee_invocation(atom/target) - if(isliving(holder) && istype(target) && LAZYLEN(ability_handlers)) + if(isliving(holder) && istype(target) && LAZYLEN(ability_handlers) && !istype(target, /obj/screen)) for(var/datum/ability_handler/handler in ability_handlers) if(handler.can_do_melee_invocation(holder, target) && handler.do_melee_invocation(holder, target)) return TRUE @@ -42,7 +42,7 @@ /// Clicking a distant target (RangedAttack()) /datum/extension/abilities/proc/do_ranged_invocation(atom/target) - if(isliving(holder) && istype(target) && LAZYLEN(ability_handlers)) + if(isliving(holder) && istype(target) && LAZYLEN(ability_handlers) && !istype(target, /obj/screen)) for(var/datum/ability_handler/handler in ability_handlers) if(handler.can_do_ranged_invocation(holder, target) && handler.do_ranged_invocation(holder, target)) return TRUE @@ -54,3 +54,8 @@ for(var/datum/ability_handler/handler in ability_handlers) handler.refresh_login() +/datum/extension/abilities/proc/refresh_element_positioning() + var/row = 0 + for(var/datum/ability_handler/handler in ability_handlers) + if(length(handler.screen_elements)) + row += handler.refresh_element_positioning(row) diff --git a/code/datums/extensions/abilities/abilities_mob.dm b/code/datums/extensions/abilities/abilities_mob.dm index b72d0ac2c5f0..4879b2d05c46 100644 --- a/code/datums/extensions/abilities/abilities_mob.dm +++ b/code/datums/extensions/abilities/abilities_mob.dm @@ -18,6 +18,7 @@ return FALSE handler = new handler_type(abilities, src) LAZYADD(abilities.ability_handlers, handler) + handler.finalize_ability_handler() return handler /mob/proc/remove_ability_handler(handler_type) @@ -28,6 +29,75 @@ if(!handler) return FALSE LAZYREMOVE(abilities.ability_handlers, handler) + qdel(handler) if(!LAZYLEN(abilities.ability_handlers)) remove_extension(src, /datum/extension/abilities) return TRUE + +/mob/living/proc/copy_abilities_from(mob/living/donor) + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + if(!abilities) + return FALSE + . = FALSE + for(var/datum/ability_handler/handler in abilities.ability_handlers) + if(handler.copy_abilities_to(src)) + . = TRUE + +/mob/living/proc/disable_abilities(var/amount = 0) + if(amount < 0) + return + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + for(var/datum/ability_handler/handler in abilities?.ability_handlers) + handler.disable_abilities(amount) + +/mob/living/proc/copy_abilities_to(mob/living/target) + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + for(var/datum/ability_handler/handler in abilities?.ability_handlers) + handler.copy_abilities_to(target) + +/mob/proc/add_ability(ability_type, list/metadata) + var/decl/ability/ability = GET_DECL(ability_type) + if(!istype(ability) || !ability.associated_handler_type) + return FALSE + var/datum/ability_handler/handler = get_ability_handler(ability.associated_handler_type, create_if_missing = TRUE) + return handler.add_ability(ability_type, metadata) + +/mob/proc/remove_ability(ability_type) + var/decl/ability/ability = GET_DECL(ability_type) + if(!istype(ability) || !ability.associated_handler_type) + return FALSE + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + var/datum/ability_handler/handler = locate(ability.associated_handler_type) in abilities?.ability_handlers + return handler?.remove_ability(ability_type) + +/mob/proc/get_ability_metadata(ability_type) + var/decl/ability/ability = GET_DECL(ability_type) + if(!istype(ability) || !ability.associated_handler_type) + return null + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + var/datum/ability_handler/handler = locate(ability.associated_handler_type) in abilities?.ability_handlers + return handler?.get_metadata(ability_type, create_if_missing = TRUE) + +/mob/proc/has_ability(ability_type) + var/decl/ability/ability = GET_DECL(ability_type) + if(!istype(ability) || !ability.associated_handler_type) + return null + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + var/datum/ability_handler/handler = locate(ability.associated_handler_type) in abilities?.ability_handlers + return handler?.provides_ability(ability_type) + +/mob/Stat() + if((. = ..()) && client) + var/datum/extension/abilities/abilities = get_extension(src, /datum/extension/abilities) + for(var/datum/ability_handler/handler in abilities?.ability_handlers) + handler.show_stat_string(src) + +/mob/proc/get_all_abilities() + var/datum/extension/abilities/abilities_extension = get_extension(src, /datum/extension/abilities) + if(!istype(abilities_extension)) + return + for(var/datum/ability_handler/handler as anything in abilities_extension.ability_handlers) + for(var/ability_type in handler.known_abilities) + var/decl/ability/ability = GET_DECL(ability_type) + if(istype(ability)) + LAZYDISTINCTADD(., ability) diff --git a/code/datums/extensions/abilities/abilities_predator.dm b/code/datums/extensions/abilities/abilities_predator.dm index 066a3feac920..4fc37d4a8281 100644 --- a/code/datums/extensions/abilities/abilities_predator.dm +++ b/code/datums/extensions/abilities/abilities_predator.dm @@ -1,11 +1,16 @@ /datum/ability_handler/predator + category_toggle_type = null var/max_dismember_size = MOB_SIZE_SMALL /datum/ability_handler/predator/can_do_melee_invocation(mob/user, atom/target) - return istype(user) && !user.incapacitated() && isatom(target) && target.Adjacent(user) + return ..() || (istype(user) && !user.incapacitated() && isatom(target) && target.Adjacent(user)) /datum/ability_handler/predator/do_melee_invocation(mob/user, atom/target) + . = ..() + if(.) + return + // Nibbles! if(user.check_intent(I_FLAG_HARM)) if(isliving(target)) diff --git a/code/datums/extensions/abilities/ability_button.dm b/code/datums/extensions/abilities/ability_button.dm new file mode 100644 index 000000000000..5ab2d44e66b8 --- /dev/null +++ b/code/datums/extensions/abilities/ability_button.dm @@ -0,0 +1,108 @@ +/obj/screen/ability + requires_ui_style = FALSE + requires_owner = FALSE + icon_state = "ability" + icon = 'icons/mob/screen/abilities.dmi' + abstract_type = /obj/screen/ability + var/datum/ability_handler/owning_handler + +/obj/screen/ability/Destroy() + remove_from_handler() + return ..() + +/obj/screen/ability/proc/remove_from_handler() + owning_handler = null + +/obj/screen/ability/on_update_icon() + invisibility = (isnull(owning_handler) || owning_handler.showing_abilities) ? 0 : INVISIBILITY_ABSTRACT + +/obj/screen/ability/handle_click(mob/user, params) + to_chat(user, "Click!") + +/obj/screen/ability/button + icon_state = "button" + requires_owner = TRUE + maptext_y = -3 + var/decl/ability/ability + +/obj/screen/ability/button/Initialize(mapload, mob/_owner, decl/ui_style/ui_style, ui_color, ui_alpha, ui_cat) + . = ..() + START_PROCESSING(SSfastprocess, src) + on_update_icon() + +/obj/screen/ability/button/Destroy() + if(is_processing) + STOP_PROCESSING(SSfastprocess, src) + return ..() + +/obj/screen/ability/button/Process() + // We've been broken or deleted. + if(QDELETED(src) || !ability || !owning_handler) + return PROCESS_KILL + // No reason to run periodic updates. + if(!ability.ability_cooldown_time && !ability.max_charge) + return PROCESS_KILL + // Something is broken. + var/list/metadata = owning_handler.get_metadata(ability.type, create_if_missing = FALSE) + if(!metadata) + return PROCESS_KILL + maptext = "" + if(ability.ability_cooldown_time) + var/next_cast = metadata["next_cast"] + if(world.time < next_cast) + maptext = ticks2shortreadable(next_cast - world.time) + if(ability.max_charge) + maptext += "
" + if(ability.max_charge) + maptext += "x[max(0, metadata["charges"])]" + if(maptext) + maptext = STYLE_SMALLFONTS_OUTLINE("
[maptext]
", 7, COLOR_WHITE, COLOR_BLACK) + +/obj/screen/ability/button/remove_from_handler() + owning_handler?.remove_screen_element(src, ability) + return ..() + +/obj/screen/ability/button/handle_click(mob/user, params) + if(owning_handler.prepared_ability == ability) + owning_handler.cancel_prepared_ability() + else if(ability.use_ability(user, get_turf(user), owning_handler)) // tmp, needs better/multi-step target selection + update_icon() + addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_icon)), ability.get_cooldown_time(ability.get_metadata_for_user(user)) + 1) + +/obj/screen/ability/button/proc/set_ability(decl/ability/_ability) + if(ability == _ability) + return + ability = _ability + if(istype(ability)) + SetName(ability.name) + else + SetName(initial(name)) + update_icon() + +/obj/screen/ability/button/on_update_icon() + . = ..() + icon_state = initial(icon_state) + cut_overlays() + if(istype(ability)) + if(owning_handler && owning_handler.prepared_ability == ability) + icon_state = "[icon_state]-active" + if(ability.ability_icon && ability.ability_icon_state) + add_overlay(overlay_image(ability.ability_icon, ability.ability_icon_state, COLOR_WHITE, (RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM))) + +/obj/screen/ability/category + name = "Toggle Ability Category" + icon_state = "category" + +/obj/screen/ability/category/remove_from_handler() + owning_handler?.remove_screen_element(src, "toggle") + return ..() + +/obj/screen/ability/category/Initialize(mapload, mob/_owner, decl/ui_style/ui_style, ui_color, ui_alpha, ui_cat) + . = ..() + update_icon() + +/obj/screen/ability/category/handle_click(mob/user, params) + owning_handler?.toggle_category_visibility() + +/obj/screen/ability/category/on_update_icon() + icon_state = owning_handler?.showing_abilities ? initial(icon_state) : "[initial(icon_state)]-off" diff --git a/code/datums/extensions/abilities/ability_decl.dm b/code/datums/extensions/abilities/ability_decl.dm new file mode 100644 index 000000000000..9f271846750d --- /dev/null +++ b/code/datums/extensions/abilities/ability_decl.dm @@ -0,0 +1,410 @@ +/decl/ability + abstract_type = /decl/ability + /// A descriptive identifier string. + var/name + /// A descriptive string about the ability. + var/desc + /// An associated handler type, used in add_ability(). + var/associated_handler_type + /// Should this ability be copied between mobs when mind is transferred? + var/copy_with_mind = FALSE + + /// If TRUE, ability is toggled on and will fire when a target is clicked, instead of instantaneously on use. + var/prep_cast = FALSE + /// Used in conjunction with prep_cast, if TRUE, ability will be untoggled after cast. + var/end_prep_on_cast = TRUE + /// Ability items invoking this ability will GC afterwards. + var/item_end_on_cast = TRUE + + /// Does this invocation trigger on a proximity click, if prepared? + var/is_melee_invocation = FALSE + /// Does this invocation trigger on a non-proximity click, if prepared? + var/is_ranged_invocation = FALSE + + // Projectile created and used to propagate this ability, if it is a ranged ability. + /// If set, this ability will create a projectile rather than applying the effect directly. + var/projectile_type + /// Sets the projectile step_delay. + var/projectile_step_delay = 1 + /// Determines the lifetime of the projectile. + var/projectile_duration = 1 SECOND + /// If not set, the ability will have documentation generated for the codex. + var/hidden_from_codex = FALSE + /// If set, this ability will be silenced by null rod and similar mechanics. + var/is_supernatural = FALSE + + // Visual/audible state for the on-turf effect of casting the spell on something. + /// If set, will attempt to draw from this icon on the turf where the ability is used. + var/overlay_icon + /// If set, will attempt to draw this icon_state on the turf where the ability is used. + var/overlay_icon_state + /// Will delete the overlay after this time. + var/overlay_lifespan = 1 SECOND + /// If set, will play a sound when used. + var/use_sound + /// Volume for above. + var/use_sound_volume = 50 + + // Visual state for the ability HUD element. + /// Type of button to use for the UI. Should be /obj/screen/ability/button or subtype. + var/ui_element_type = /obj/screen/ability/button + /// Icon to draw on the ability HUD, if any. + var/ability_icon + /// Icon state to draw on the ability HUD, if any. + var/ability_icon_state + + // Various restrictions on how and when the ability is used. + /// A decl type that handles retrieving and validating targets. + var/decl/ability_targeting/target_selector = /decl/ability_targeting + /// If set to a numeric value, the ability cannot be used before the cooldown has expired. + var/ability_cooldown_time = 5 SECONDS + /// If set, a do_after() will be applied to this spell. + var/ability_use_channel + /// Maximum charges that can be held of this item at a time. If unset, item does not accumulate charges. + var/max_charge + /// How long it takes between charges. + var/charge_delay = 1 SECOND + /// What flags to check before an ability can be used, if any. + var/check_incapacitated = (INCAPACITATION_STUNNED|INCAPACITATION_RESTRAINED|INCAPACITATION_BUCKLED_FULLY|INCAPACITATION_FORCELYING|INCAPACITATION_KNOCKOUT) + /// What type of mob is required to use this ability. + var/mob/expected_mob_type = /mob/living + /// If set, this ability can only be used while standing on a turf (not in an atom's contents or null loc). + var/requires_turf = TRUE + /// If set, this ability cannot be used on the admin z-level. + var/admin_blocked = TRUE + + // Various failure messages. + /// Failed due to purged/null rod. + var/cast_failed_purged_str = "Another power interferes with your own!" + /// Failed due to non-turf loc. + var/cast_failed_no_turf = "You must be standing on solid ground to use this ability." + /// Failed due to being on admin level + var/cast_failed_no_admin_level = "This ability cannot be used on the admin z-level." + /// Failed due to being invalid mob type + var/cast_failed_wrong_mob_type = "This ability may only be used by living creature." + /// Failed due to being downed/buckled + var/cast_failed_incapacitated = "You are in no state to use that ability." + /// Failed due to still being on cooldown from last use + var/cast_failed_on_cooldown = "You cannot use that ability again just yet." + /// Failed due to still recharging + var/cast_failed_no_charges = "You are out of charges for that ability." + /// Failed due to being silenced/disabled + var/cast_failed_disabled_str = "You are unable to use that ability for another $TIME$!" + + // Various casting messages. + /// "$USER$ begins preparing to use an ability on $TARGET$." + var/prepare_message_3p_str + /// "You begin preparing to use an ability on $TARGET$." + var/prepare_message_1p_str + /// "$USER$ uses an ability." + var/cast_message_3p_str + /// "You use an ability." + var/cast_message_1p_str + /// "You ready yourself to use an ability." + var/ready_ability_1p_str + /// "You cease readying yourself to use an ability." + var/cancel_ability_1p_str + /// "You fail to cast an ability." + var/fail_cast_1p_str + +/decl/ability/Initialize() + target_selector = GET_DECL(target_selector) + . = ..() + +/decl/ability/validate() + . = ..() + if(!istype(target_selector, /decl/ability_targeting)) + . += "null or invalid target_selector: '[target_selector || "NULL"]'" + if(!findtext(cast_failed_disabled_str, "$TIME$")) + . += "missing $TIME$ token in cast_failed_disabled_str" + if(!ispath(associated_handler_type, /datum/ability_handler)) + . += "null or invalid associated_handler_type '[associated_handler_type]'" + if(!ability_icon) + . += "null ability_icon" + else if(!istext(ability_icon_state)) + . += "null or non-text ability_icon_state" + else if(!check_state_in_icon(ability_icon_state, ability_icon)) + . += "missing ability_icon_state '[ability_icon_state]' in icon '[ability_icon]'" + +/decl/ability/proc/get_cooldown_time(list/metadata) + return ability_cooldown_time + +/decl/ability/proc/has_valid_targets(user, atom/target, list/metadata) + // Projectiles just need something to shoot at. + if(projectile_type) + return isturf(target) || isturf(target.loc) + // Abilities need at least one valid target. + return target_selector.validate_initial_target(user, target, metadata, src) + +/decl/ability/proc/get_metadata_for(mob/user) + if(!istype(user)) + CRASH("get_metadata_for() called with null or invalid user!") + var/datum/ability_handler/handler = user.get_ability_handler(associated_handler_type, create_if_missing = FALSE) + if(istype(handler)) + . = handler.get_metadata(src) + if(!islist(.)) + PRINT_STACK_TRACE("get_metadata_for() returning null or non-list metadata!") + else + PRINT_STACK_TRACE("get_metadata_for() called by mob with no handler of associated type!") + +// This is the main entrypoint for the ability use chain. +/decl/ability/proc/use_ability(mob/user, atom/target, datum/ability_handler/handler) + + if(!istype(user)) + return + + var/list/metadata = get_metadata_for(user) + if(!islist(metadata) || !can_use_ability(user, metadata)) + return + + if(prep_cast && handler.prepared_ability != src) + handler.prepare_ability(src) + return + + // Resolve our clicked target to the appropriate turf. + target = target_selector.resolve_initial_target(target) + if(!istype(target)) + to_chat(user, SPAN_WARNING("You cannot see a target for [name].")) + return + + if(!has_valid_targets(user, target, metadata)) + to_chat(user, SPAN_WARNING("You cannot use [name] on \the [target].")) + return + + if(!prepare_to_cast(user, target, metadata, handler)) + if(fail_cast_1p_str) + to_chat(user, SPAN_WARNING(capitalize(emote_replace_user_tokens(fail_cast_1p_str, user)))) + return + + if(projectile_type) + // Fire a projectile if that is how this ability works. + fire_projectile_at(user, target, metadata) + + else + // Otherwise, just apply to the target directly. + apply_effect(user, target, metadata) + + if(end_prep_on_cast && handler.prepared_ability == src) + handler.cancel_prepared_ability() + +/decl/ability/proc/fire_projectile_at(mob/user, atom/target, list/metadata) + var/obj/item/projectile/projectile = new projectile_type(get_turf(user)) + if(istype(projectile, /obj/item/projectile/ability)) + var/obj/item/projectile/ability/ability_projectile = projectile + ability_projectile.owner = user + ability_projectile.ability_metadata = metadata + ability_projectile.carried_ability = src + projectile.original = target + projectile.starting = get_turf(user) + projectile.shot_from = user + projectile.current = projectile.original + projectile.yo = target.y - user.y + projectile.xo = target.x - user.x + projectile.life_span = projectile_duration + projectile.hitscan = !projectile_step_delay + projectile.step_delay = projectile_step_delay + projectile.launch(target) + return projectile + +/decl/ability/proc/show_cast_channel_msg(mob/user, atom/target, list/metadata) + if(prepare_message_3p_str && prepare_message_1p_str) + user.visible_message( + SPAN_NOTICE(capitalize(emote_replace_target_tokens(emote_replace_user_tokens(prepare_message_3p_str, user), target))), + SPAN_NOTICE(capitalize(emote_replace_target_tokens(prepare_message_1p_str, target))) + ) + else if(prepare_message_1p_str) + user.visible_message(SPAN_NOTICE(capitalize(emote_replace_target_tokens(prepare_message_1p_str, target)))) + else if(prepare_message_3p_str) + user.visible_message(SPAN_NOTICE(capitalize(emote_replace_target_tokens(emote_replace_user_tokens(prepare_message_3p_str, user), target)))) + +/decl/ability/proc/show_ability_cast_msg(mob/user, list/targets, list/metadata) + var/atom/target = targets[1] + if(cast_message_3p_str && cast_message_1p_str) + user.visible_message( + SPAN_NOTICE(capitalize(emote_replace_target_tokens(emote_replace_user_tokens(cast_message_3p_str, user), target))), + SPAN_NOTICE(capitalize(emote_replace_target_tokens(cast_message_1p_str, target))) + ) + else if(cast_message_1p_str) + user.visible_message(SPAN_NOTICE(capitalize(emote_replace_target_tokens(cast_message_1p_str, target)))) + else if(cast_message_3p_str) + user.visible_message(SPAN_NOTICE(capitalize(emote_replace_target_tokens(emote_replace_user_tokens(cast_message_3p_str, user), target)))) + +/decl/ability/proc/prepare_to_cast(mob/user, atom/target, list/metadata, datum/ability_handler/handler) + var/use_cooldown_time = get_cooldown_time(metadata) + if(ability_use_channel) + if(world.time < handler.next_channel) + return FALSE + handler.next_channel = world.time + ability_use_channel + show_cast_channel_msg(user, target, metadata) + if(!do_after(user, ability_use_channel, target) || !can_use_ability(user, metadata)) + handler.next_channel = 0 // Don't make them sit out the entire channel period, it's just a debounce/duplicate ability preventative + return FALSE + if(use_cooldown_time > 0) + metadata["next_cast"] = world.time + use_cooldown_time + return TRUE + +/decl/ability/proc/check_equipment(mob/user, list/metadata, silent = FALSE) + return TRUE + +/decl/ability/proc/get_metadata_for_user(mob/user) + if(!user.has_ability(type)) + return null + + var/datum/ability_handler/handler = user.get_ability_handler(associated_handler_type, create_if_missing = FALSE) + if(!istype(handler)) + CRASH("get_metadata_for_user() called by mob with no handler of associated type!") + + return handler.get_metadata(src) + +/decl/ability/proc/can_use_ability(mob/user, list/metadata, silent = FALSE) + + if(!user.has_ability(type)) + error("\The [user] utilized the ability '[type]' without having access to it.") + if(!silent) + to_chat(user, SPAN_WARNING("You shouldn't have this ability! Please notify a developer or raise an issue ticket.")) + return FALSE + + var/turf/my_turf = get_turf(user) + if(requires_turf) + if(!istype(my_turf)) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_no_turf)) + return FALSE + if(admin_blocked && isAdminLevel(my_turf.z)) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_no_admin_level)) + return FALSE + + if(!istype(user, expected_mob_type)) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_wrong_mob_type)) + return FALSE + + if(!isnull(check_incapacitated) && user.incapacitated(check_incapacitated)) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_incapacitated)) + return FALSE + + if(!check_equipment(user, metadata, silent)) + return FALSE + + if(ability_cooldown_time && world.time < metadata["next_cast"]) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_on_cooldown)) + return FALSE + + if(max_charge && metadata["charges"] <= 0) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_no_charges)) + return FALSE + + if(is_supernatural) + + var/is_purged = FALSE + if(isanimal(user)) + var/mob/living/simple_animal/critter = user + is_purged = !!critter.purge + + if(!is_purged) + for(var/turf/turf in range(user, 1)) + if(turf.is_purged()) + is_purged = TRUE + break + + if(is_purged) + if(!silent) + to_chat(user, SPAN_WARNING(cast_failed_purged_str)) + return FALSE + + var/disabled_time = metadata["disabled"] + if(world.time < disabled_time) + if(!silent) + var/remaining_time = ceil((disabled_time - world.time) / 10) + to_chat(user, SPAN_WARNING(replacetext(cast_failed_disabled_str, "$TIME$", "[remaining_time] second\s"))) + return FALSE + + return TRUE + +/decl/ability/proc/apply_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) + SHOULD_CALL_PARENT(TRUE) + if(use_sound) + playsound(get_turf(user), use_sound, use_sound_volume, 1) + if(istype(projectile)) + projectile.expended = TRUE + + admin_attacker_log(user, "attempted to use ability [src] on [hit_target]") + + var/list/targets = target_selector.get_affected(user, hit_target, metadata, src, projectile) + if(length(targets)) + show_ability_cast_msg(user, targets, metadata) + while(length(targets)) + var/target = targets[1] + apply_effect_to(user, target, metadata) + targets = prune_targets(user, target, targets, metadata) + finish_casting(user, hit_target, metadata) + +/decl/ability/proc/finish_casting(mob/user, atom/hit_target, list/metadata) + return + +/decl/ability/proc/prune_targets(user, previous_target, list/targets, list/metadata) + if(!length(targets)) + return null + if(previous_target) + LAZYREMOVE(targets, previous_target) + return targets + +/decl/ability/proc/apply_visuals(mob/user, atom/target, list/metadata) + if(!overlay_icon || !overlay_lifespan) + return + var/turf/overlay_loc = get_turf(target) + if(!isturf(overlay_loc) || locate(/obj/effect/overlay) in overlay_loc) + return + var/obj/effect/overlay/ability_overlay = new(overlay_loc) + ability_overlay.icon = overlay_icon + ability_overlay.icon_state = overlay_icon_state + ability_overlay.anchored = TRUE + ability_overlay.set_density(FALSE) + QDEL_IN(ability_overlay, overlay_lifespan) + +/decl/ability/proc/apply_effect_to(mob/user, atom/target, list/metadata) + SHOULD_CALL_PARENT(TRUE) + SHOULD_NOT_SLEEP(TRUE) + apply_visuals(user, target, metadata) + +/decl/ability/proc/get_default_metadata() + . = list() + if(ability_cooldown_time) + .["next_cast"] = 0 + if(max_charge) + .["charges"] = max_charge + .["next_charge"] = 0 + +/decl/ability/proc/recharge(mob/owner, list/metadata) + if(max_charge <= 0 || metadata["charges"] >= max_charge) + return FALSE + if(world.time < metadata["next_charge"]) + return TRUE + metadata["next_charge"] = world.time + charge_delay + metadata["charges"]++ + return TRUE + +/decl/ability/proc/get_stat_strings(list/metadata) + var/use_name = metadata["ability_name"] || name + if(ability_cooldown_time) + var/on_cooldown = metadata["next_cast"] - world.time + if(on_cooldown > 0) + return list( + use_name, + "[ceil(on_cooldown/10)]s" + ) + if(max_charge) + return list( + use_name, + "[metadata["charges"]]/[max_charge]" + ) + +/decl/ability/ranged + abstract_type = /decl/ability/ranged + projectile_type = /obj/item/projectile/ability + is_ranged_invocation = TRUE + prep_cast = TRUE \ No newline at end of file diff --git a/code/datums/extensions/abilities/ability_handler.dm b/code/datums/extensions/abilities/ability_handler.dm index 8dc7ee1e5de6..d215868a4c58 100644 --- a/code/datums/extensions/abilities/ability_handler.dm +++ b/code/datums/extensions/abilities/ability_handler.dm @@ -1,8 +1,17 @@ /datum/ability_handler abstract_type = /datum/ability_handler + var/showing_abilities = FALSE var/mob/owner - var/list/ability_items var/datum/extension/abilities/master + var/list/ability_items + var/list/screen_elements + var/list/known_abilities + var/list/recharging_abilities + var/stat_panel_type = "Abilities" + /// UI element for showing or hiding this ability category. Should be /obj/screen/ability/category or subtype. + var/category_toggle_type = /obj/screen/ability/category + var/decl/ability/prepared_ability + var/next_channel = 0 /datum/ability_handler/New(_master) master = _master @@ -12,16 +21,179 @@ if(!istype(owner)) CRASH("Ability handler received invalid owner!") ..() + refresh_login() + +/datum/ability_handler/Process() + + if(!length(recharging_abilities)) + return PROCESS_KILL + + for(var/decl/ability/ability as anything in recharging_abilities) + if(!ability.recharge(owner, get_metadata(ability))) + LAZYREMOVE(recharging_abilities, ability) + +/datum/ability_handler/proc/get_metadata(decl/ability/ability, create_if_missing = TRUE) + if(istype(ability)) + . = known_abilities[ability.type] + if(!islist(.) && create_if_missing) + . = ability.get_default_metadata() + known_abilities[ability.type] = . + else if(ispath(ability, /decl/ability)) + . = known_abilities[ability] + if(!islist(.) && create_if_missing) + ability = GET_DECL(ability) + if(!istype(ability)) + return list() + . = ability.get_default_metadata() + known_abilities[ability] = . + else if(create_if_missing) + PRINT_STACK_TRACE("ability metadata retrieval passed invalid ability type: '[ability]'") + . = list() /datum/ability_handler/Destroy() + recharging_abilities = null + known_abilities = null QDEL_NULL_LIST(ability_items) + + for(var/ability in screen_elements) + var/obj/element = screen_elements[ability] + if(istype(element)) + qdel(element) + screen_elements = null + if(master) LAZYREMOVE(master.ability_handlers, src) master.update() master = null owner = null + if(is_processing) + STOP_PROCESSING(SSprocessing, src) return ..() +/datum/ability_handler/proc/add_ability(ability_type, list/metadata) + if(provides_ability(ability_type)) + return FALSE + var/decl/ability/ability = GET_DECL(ability_type) + if(!istype(ability)) + return FALSE + if(islist(metadata)) + metadata = metadata.Copy() // Prevent mutating during copy from other mobs. + else + metadata = ability.get_default_metadata() // Always unique, no copy needed. + + if(ability.ui_element_type && !istype(LAZYACCESS(screen_elements, ability), ability.ui_element_type)) + var/existing = screen_elements[ability] + if(existing) + remove_screen_element(existing, ability, FALSE) + var/obj/screen/ability/button/button = new ability.ui_element_type(null, owner, null, null, null, null, null) + button.set_ability(ability) + add_screen_element(button, ability, TRUE) + + LAZYSET(known_abilities, ability_type, metadata) + if(ability.max_charge) + LAZYDISTINCTADD(recharging_abilities, ability_type) + if(!is_processing) + START_PROCESSING(SSprocessing, src) + return TRUE + +/datum/ability_handler/proc/remove_ability(ability_type) + if(!provides_ability(ability_type)) + return FALSE + LAZYREMOVE(known_abilities, ability_type) + LAZYREMOVE(recharging_abilities, ability_type) + + var/decl/ability/ability = GET_DECL(ability_type) + if(ability?.ui_element_type) + var/obj/screen/existing_button = LAZYACCESS(screen_elements, ability) + if(istype(existing_button)) + remove_screen_element(existing_button, ability) + + if(!LAZYLEN(recharging_abilities) && is_processing) + STOP_PROCESSING(SSprocessing, src) + + if(!LAZYLEN(known_abilities)) + owner.remove_ability_handler(type) + + return TRUE + +/datum/ability_handler/proc/provides_ability(ability_type) + return (ability_type in known_abilities) + +/datum/ability_handler/proc/finalize_ability_handler() + if(category_toggle_type) + var/obj/screen/ability/category/category_toggle = new category_toggle_type(null, null, null, null, null, null, null) + add_screen_element(category_toggle, "toggle", TRUE) + toggle_category_visibility(TRUE) + +/datum/ability_handler/proc/refresh_element_positioning(row = 1, col = 1) + if(!LAZYLEN(screen_elements)) + return 0 + var/button_pos = col + var/button_row = row + . = 1 + for(var/ability in screen_elements) + var/obj/screen/element = screen_elements[ability] + if(istype(element, /obj/screen/ability/category)) + element.screen_loc = "RIGHT-[col]:-4,TOP-[row]" + else if(!element.invisibility) + button_pos++ + if((button_pos-col) > 5) + button_row++ + .++ + button_pos = col+1 + element.screen_loc = "RIGHT-[button_pos]:-4,TOP-[button_row]" + +/datum/ability_handler/proc/toggle_category_visibility(force_state) + showing_abilities = isnull(force_state) ? !showing_abilities : force_state + update_screen_elements() + if(master) + master.refresh_element_positioning() + +/datum/ability_handler/proc/update_screen_elements() + for(var/ability in screen_elements) + var/obj/screen/ability/ability_button = screen_elements[ability] + ability_button.update_icon() + +/datum/ability_handler/proc/copy_abilities_to(mob/living/target) + for(var/decl/ability/ability as anything in known_abilities) + if(!ability.copy_with_mind) + continue + if(target.add_ability(ability, get_metadata(ability, create_if_missing = FALSE))) + . = TRUE + +/datum/ability_handler/proc/disable_abilities(amount) + for(var/ability in known_abilities) + var/list/metadata = get_metadata(ability) + metadata["disabled"] = max(metadata["disabled"], (world.time + amount)) + +/datum/ability_handler/proc/enable_abilities(amount) + for(var/ability in known_abilities) + var/list/metadata = get_metadata(ability) + metadata["disabled"] = 0 + +/datum/ability_handler/proc/add_screen_element(atom/element, decl/ability/ability, update_positions = TRUE) + if(isnull(ability) || isnum(ability)) + return + LAZYSET(screen_elements, ability, element) + owner?.client?.screen |= element + if(istype(element, /obj/screen/ability)) + var/obj/screen/ability/ability_button = element + ability_button.owning_handler = src + if(update_positions && master && length(screen_elements)) + master.refresh_element_positioning() + +/datum/ability_handler/proc/remove_screen_element(atom/element, decl/ability/ability, update_positions = TRUE) + if(isnull(ability) || isnum(ability)) + return + LAZYREMOVE(screen_elements, ability) + owner?.client?.screen -= element + if(istype(element, /obj/screen/ability)) + var/obj/screen/ability/ability_button = element + if(ability_button.owning_handler == src) + ability_button.owning_handler = null + if(update_positions && master && LAZYLEN(screen_elements)) + master.refresh_element_positioning() + /datum/ability_handler/proc/cancel() if(LAZYLEN(ability_items)) for(var/thing in ability_items) @@ -29,9 +201,48 @@ qdel(thing) ability_items = null +/datum/ability_handler/proc/show_stat_string(mob/user) + if(!stat_panel_type || !statpanel(stat_panel_type)) + return + for(var/ability_type in known_abilities) + var/decl/ability/ability = GET_DECL(ability_type) + var/list/stat_strings = ability.get_stat_strings(get_metadata(ability)) + if(length(stat_strings) >= 2) + stat(stat_strings[1], stat_strings[2]) + /// Individual ability methods/disciplines (psioncs, etc.) so that mobs can have multiple. /datum/ability_handler/proc/refresh_login() - return + SHOULD_CALL_PARENT(TRUE) + if(LAZYLEN(screen_elements)) + var/list/add_elements = list() + for(var/ability in screen_elements) + var/atom/element = screen_elements[ability] + if(istype(element)) + add_elements |= element + if(length(add_elements)) + owner?.client?.screen |= add_elements + +/datum/ability_handler/proc/cancel_prepared_ability() + if(!prepared_ability) + return FALSE + if(prepared_ability.cancel_ability_1p_str) + to_chat(owner, capitalize(emote_replace_user_tokens(prepared_ability.cancel_ability_1p_str), owner)) + var/obj/screen/ability/button/button = LAZYACCESS(screen_elements, prepared_ability) + prepared_ability = null + if(istype(button)) + button.update_icon() + return TRUE + +/datum/ability_handler/proc/prepare_ability(decl/ability/ability) + if(prepared_ability && !cancel_prepared_ability()) + return FALSE + prepared_ability = ability + if(ability.ready_ability_1p_str) + to_chat(owner, capitalize(emote_replace_user_tokens(ability.ready_ability_1p_str), owner)) + var/obj/screen/ability/button/button = LAZYACCESS(screen_elements, ability) + if(istype(button)) + button.update_icon() + return TRUE /datum/ability_handler/proc/can_do_self_invocation(mob/user) return FALSE @@ -46,13 +257,23 @@ return FALSE /datum/ability_handler/proc/can_do_melee_invocation(mob/user, atom/target) - return FALSE + SHOULD_CALL_PARENT(TRUE) + return prepared_ability ? prepared_ability.is_melee_invocation : FALSE /datum/ability_handler/proc/do_melee_invocation(mob/user, atom/target) + SHOULD_CALL_PARENT(TRUE) + if(prepared_ability) + prepared_ability.use_ability(user, target, src) + return TRUE return FALSE /datum/ability_handler/proc/can_do_ranged_invocation(mob/user, atom/target) - return FALSE + SHOULD_CALL_PARENT(TRUE) + return prepared_ability ? prepared_ability.is_ranged_invocation : FALSE /datum/ability_handler/proc/do_ranged_invocation(mob/user, atom/target) + SHOULD_CALL_PARENT(TRUE) + if(prepared_ability) + prepared_ability.use_ability(user, target, src) + return TRUE return FALSE diff --git a/code/datums/extensions/abilities/ability_item.dm b/code/datums/extensions/abilities/ability_item.dm index 98bb2b8d43be..b4838fd41458 100644 --- a/code/datums/extensions/abilities/ability_item.dm +++ b/code/datums/extensions/abilities/ability_item.dm @@ -1,26 +1,37 @@ /obj/item/ability - simulated = 1 - obj_flags = OBJ_FLAG_NO_STORAGE - anchored = TRUE + simulated = FALSE + icon = 'icons/mob/screen/ability_inhand.dmi' + obj_flags = OBJ_FLAG_NO_STORAGE + anchored = TRUE pickup_sound = null drop_sound = null equip_sound = null is_spawnable_type = FALSE abstract_type = /obj/item/ability - var/mob/living/owner + var/decl/ability/ability + var/weakref/owner_ref var/handler_type -/obj/item/ability/Initialize() - owner = loc - if(!istype(owner)) +/obj/item/ability/Initialize(ml, decl/ability/_ability) + var/mob/living/owner = loc + var/datum/ability_handler/handler = istype(owner) && owner.get_ability_handler(handler_type, FALSE) + if(!istype(handler)) return INITIALIZE_HINT_QDEL - return ..() + if(_ability) + ability = _ability + if(!istype(ability)) + return INITIALIZE_HINT_QDEL + owner_ref = weakref(owner) + LAZYDISTINCTADD(handler.ability_items, src) + . = ..() + owner.put_in_hands(src) /obj/item/ability/Destroy() + var/mob/living/owner = owner_ref?.resolve() var/datum/ability_handler/handler = istype(owner) && owner.get_ability_handler(handler_type, FALSE) - if(handler) + if(istype(handler)) LAZYREMOVE(handler.ability_items, src) - . = ..() + return ..() /obj/item/ability/dropped() ..() @@ -29,3 +40,23 @@ /obj/item/ability/attack_self(var/mob/user) user?.drop_from_inventory(src) return TRUE + +/obj/item/ability/use_on_mob(mob/living/target, mob/living/user, animate) + return FALSE + +/obj/item/ability/afterattack(atom/target, mob/user, proximity) + if(QDELETED(src) || !istype(ability)) + return TRUE + var/list/metadata = ability.get_metadata_for(user) + if(!islist(metadata)) + return TRUE + if(ability.projectile_type) + // Fire a projectile if that is how this ability works. + ability.fire_projectile_at(user, target, metadata) + else + // Otherwise, apply to the target. Range checking etc. will be handled in apply_effect(). + ability.apply_effect(user, target, metadata) + + // Clean up our item if needed. + if(ability.item_end_on_cast) + qdel(src) diff --git a/code/datums/extensions/abilities/ability_projectile.dm b/code/datums/extensions/abilities/ability_projectile.dm new file mode 100644 index 000000000000..896acba2e95a --- /dev/null +++ b/code/datums/extensions/abilities/ability_projectile.dm @@ -0,0 +1,31 @@ +/obj/item/projectile/ability + name = "ability" + // The projectile is functionally a tracer, the ability deals the damage. + nodamage = TRUE + penetrating = FALSE + + /// Default; can be set by the ability. + life_span = 1 SECOND + + var/expended = FALSE + var/mob/owner + var/list/ability_metadata + var/decl/ability/carried_ability + +/obj/item/projectile/ability/Destroy() + owner = null + carried_ability = null + return ..() + +/obj/item/projectile/ability/explosion_act() + SHOULD_CALL_PARENT(FALSE) + +/obj/item/projectile/ability/Bump(var/atom/A, forced=0) + if(loc && carried_ability && !expended) + carried_ability.apply_effect(owner, A, ability_metadata, src) + return TRUE + +/obj/item/projectile/ability/on_impact(var/atom/A) + if(loc && carried_ability && !expended) + carried_ability.apply_effect(owner, A, ability_metadata, src) + return TRUE diff --git a/code/datums/extensions/abilities/ability_targeting.dm b/code/datums/extensions/abilities/ability_targeting.dm new file mode 100644 index 000000000000..52f7ee8166c5 --- /dev/null +++ b/code/datums/extensions/abilities/ability_targeting.dm @@ -0,0 +1,91 @@ +/decl/ability_targeting + abstract_type = /decl/ability_targeting + /// If set, this ability is applied to a square of this radius. + var/effect_radius = 0 + /// Set to except the inner space of the spell from target checks. + var/effect_inner_radius = -1 + /// If set, user will be excepted from targets. + var/user_is_immune = FALSE + /// If set, this ability will never target our faction. + var/faction_immune = FALSE + /// If set, this ability will only target our faction. + var/faction_only = FALSE + /// If set, this ability will resolve targets to turfs before doing any assessment or targetting. + var/target_turf = TRUE + /// If set along with target turf type, will include dense turfs. + var/ignore_dense_turfs = TRUE + /// If set along target turf type, will include space turfs. + var/ignore_space_turfs = FALSE + +/decl/ability_targeting/proc/get_effect_radius(mob/user, atom/hit_target, list/metadata) + return effect_radius + +/// This proc exists so that subtypes can override it and take advantage of the speed benefits of `for(var/mob in range())` and similar optimizations. +/// It should ONLY ever be called in get_affected(). +/decl/ability_targeting/proc/get_affected_atoms(atom/center, new_effect_radius) + PROTECTED_PROC(TRUE) + . = list() + for(var/atom/target in range(center, new_effect_radius)) + . += target + +/decl/ability_targeting/proc/get_affected(mob/user, atom/hit_target, list/metadata, decl/ability/ability, obj/item/projectile/ability/projectile) + if(effect_radius <= 0) + return validate_target(user, hit_target, metadata, ability) ? list(hit_target) : null + var/atom/center = projectile || hit_target + var/new_effect_radius = get_effect_radius(user, hit_target, metadata) + var/list/except_atoms = effect_inner_radius >= 0 ? range(effect_inner_radius, center) : null + var/list/target_candidates = get_affected_atoms(center, new_effect_radius) + for(var/atom/target in except_atoms ? target_candidates - except_atoms : target_candidates) // sloooooow... + if(validate_target(user, target, metadata, ability)) + LAZYADD(., target) + +/decl/ability_targeting/proc/resolve_initial_target(atom/target) + if(target_turf) + return get_turf(target) + return target + +/decl/ability_targeting/proc/validate_initial_target(mob/user, atom/target, list/metadata, decl/ability/ability) + return validate_target(user, target, metadata, ability) + +/decl/ability_targeting/proc/validate_target(mob/user, atom/target, list/metadata, decl/ability/ability) + if(target == user && !user_is_immune) + return FALSE + if(target_turf && !isturf(target)) + return FALSE + if(user.faction) + if(faction_immune && ismob(target)) + var/mob/target_mob = target + if(target_mob.faction == user.faction) + return FALSE + if(faction_only) + if(!ismob(target)) + return FALSE + var/mob/target_mob = target + if(target_mob.faction != user.faction) + return FALSE + else if(faction_only) + return FALSE + if(isturf(target)) + if(ignore_dense_turfs && target.density) + return FALSE + if(ignore_space_turfs && istype(target, /turf/space)) + return FALSE + return TRUE + +/decl/ability_targeting/clear_turf + ignore_dense_turfs = TRUE + +/decl/ability_targeting/clear_turf/validate_target(mob/user, atom/target, list/metadata, decl/ability/ability) + . = ..() && isturf(target) + if(.) + var/turf/target_turf = target + return !target_turf.contains_dense_objects(user) + +/decl/ability_targeting/living_mob + target_turf = FALSE + +/decl/ability_targeting/living_mob/validate_target(mob/user, atom/target, list/metadata, decl/ability/ability) + . = ..() && isliving(target) + if(.) + var/mob/living/victim = target + return victim.simulated diff --git a/code/datums/extensions/abilities/readme.dm b/code/datums/extensions/abilities/readme.dm new file mode 100644 index 000000000000..b7e17f8d59e3 --- /dev/null +++ b/code/datums/extensions/abilities/readme.dm @@ -0,0 +1,26 @@ +/* + + ABILITY DECL SYSTEM NOTES + + - Mobs have an extension, /datum/extension/abilities + - This extension has a list of associated handlers, /datum/ability_handler + - The handlers have a list of associated ability decls, /decl/ability, which are indexes for associative metadata lists. + - The abilities have an associated targeting handler, /decl/ability_targeting, which handles single target, turf target, AOE, etc. + - Handlers are added/removed with mob.add_ability_handler(handler_type) and mob.remove_ability_handler(handler_type) + - The extension will be added to the mob automatically when adding a handler, and removed if the last handler is removed. + - Abilities are added/removed with mob.add_ability(ability_type, preset metadata if any) and mob.remove_ability(ability_type) + - Handlers for abilities will be inferred from the /decl and added to the mob automatically. + - Metadata is retrieved with handler.get_metadata(ability type or instance) + + - Upon invocation, an ability will: + - retrieve handler and metadata from the user mob + - validate the handler/metadata/user against whatever requirements the ability has + - resolve the initial click target to the appropriate target for the ability (turf under the clicked target for example) + - check any additional requirements like charges, cooldowns, etc. + - if a projectile ability, spawn and launch a projectile that will carry the ability and metadata to the destination target. + - apply the ability to the destination target + - while applying the ability, the targeting decl will be used to grab all applicable targets at or near the point of use (projectile hit or clicked target) + - the ability effects will then get applied (fire, ice, explosion, so on) + - the ability will then set cooldown as appropriate in metadata, deduct charges, etc + +*/ \ No newline at end of file diff --git a/code/datums/mind/mind.dm b/code/datums/mind/mind.dm index cb9ad6c9539e..1db348880015 100644 --- a/code/datums/mind/mind.dm +++ b/code/datums/mind/mind.dm @@ -75,7 +75,6 @@ /datum/mind/proc/handle_mob_deletion(mob/living/deleted_mob) if (current == deleted_mob) current = null - /datum/mind/proc/transfer_to(mob/living/new_character) if(!istype(new_character)) to_world_log("## DEBUG: transfer_to(): Some idiot has tried to transfer_to() a non mob/living mob. Please inform Carn") @@ -83,6 +82,8 @@ if(current?.mind == src) current.mind = null SSnano.user_transferred(current, new_character) // transfer active NanoUI instances to new user + if(istype(current)) // exclude new_players and observers + current.copy_abilities_to(new_character) if(new_character.mind) //remove any mind currently in our new body's mind variable new_character.mind.current = null @@ -91,9 +92,6 @@ current = new_character //link ourself to our new body new_character.mind = src //and link our new body to ourself - if(learned_spells && learned_spells.len) - restore_spells(new_character) - if(active) new_character.key = key //now transfer the key to link the client to our new body diff --git a/code/datums/repositories/follow.dm b/code/datums/repositories/follow.dm index 2a71b7b3579e..fb12909997cb 100644 --- a/code/datums/repositories/follow.dm +++ b/code/datums/repositories/follow.dm @@ -216,10 +216,6 @@ var/global/repository/follow/follow_repository = new() followed_type = /obj/effect/blob/core suffix = "Blob" -/datum/follow_holder/supermatter - sort_order = 10 - followed_type = /obj/machinery/power/supermatter - /datum/follow_holder/singularity sort_order = 10 followed_type = /obj/effect/singularity diff --git a/code/datums/supplypacks/engineering.dm b/code/datums/supplypacks/engineering.dm index 3c771acd1e42..e7ec3c1645be 100644 --- a/code/datums/supplypacks/engineering.dm +++ b/code/datums/supplypacks/engineering.dm @@ -155,13 +155,6 @@ containername = "shield generator construction kit crate" access = access_engine -/decl/hierarchy/supply_pack/engineering/smbig - name = "Power - Supermatter core" - contains = list(/obj/machinery/power/supermatter) - containertype = /obj/structure/closet/crate/secure/large/supermatter - containername = "\improper Supermatter crate (CAUTION)" - access = access_ce - /decl/hierarchy/supply_pack/engineering/robotics name = "Parts - Robotics assembly" contains = list(/obj/item/assembly/prox_sensor = 3, diff --git a/code/datums/trading/traders/misc.dm b/code/datums/trading/traders/misc.dm index dd3e0df898f1..6356be83f0d4 100644 --- a/code/datums/trading/traders/misc.dm +++ b/code/datums/trading/traders/misc.dm @@ -155,7 +155,7 @@ ) possible_trading_items = list( /obj/item/clothing/head/wizard/magus = TRADER_THIS_TYPE, - /obj/item/shield/buckler = TRADER_THIS_TYPE, + /obj/item/shield/crafted/buckler = TRADER_THIS_TYPE, /obj/item/clothing/head/redcoat = TRADER_THIS_TYPE, /obj/item/clothing/head/powdered_wig = TRADER_THIS_TYPE, /obj/item/clothing/head/hasturhood = TRADER_THIS_TYPE, diff --git a/code/datums/trading/traders/unique.dm b/code/datums/trading/traders/unique.dm index e71995049218..dd30cd3b4bec 100644 --- a/code/datums/trading/traders/unique.dm +++ b/code/datums/trading/traders/unique.dm @@ -68,7 +68,6 @@ /obj/item/stack/material/ore = TRADER_ALL ) possible_trading_items = list( - /obj/machinery/power/supermatter = TRADER_ALL, /obj/item/aiModule = TRADER_SUBTYPES_ONLY ) want_multiplier = 5000 diff --git a/code/datums/uplink/grenades.dm b/code/datums/uplink/grenades.dm index 2a20f984ebe6..c91af43ad7d9 100644 --- a/code/datums/uplink/grenades.dm +++ b/code/datums/uplink/grenades.dm @@ -80,17 +80,3 @@ item_cost = 40 antag_roles = list(/decl/special_role/mercenary) path = /obj/item/box/frags - -/datum/uplink_item/item/grenades/supermatter - name = "1x Supermatter Grenade" - desc = "This grenade contains a small supermatter shard which will delaminate upon activation and pull in nearby objects, irradiate lifeforms, and eventually explode." - item_cost = 15 - antag_roles = list(/decl/special_role/mercenary) - path = /obj/item/grenade/supermatter - -/datum/uplink_item/item/grenades/supermatters - name = "5x Supermatter Grenades" - desc = "These grenades contains a small supermatter shard which will delaminate upon activation and pull in nearby objects, irradiate lifeforms, and eventually explode." - item_cost = 60 - antag_roles = list(/decl/special_role/mercenary) - path = /obj/item/box/supermatters diff --git a/code/game/alpha_masks.dm b/code/game/alpha_masks.dm index 9c8a341a4823..3eb68a3b3435 100644 --- a/code/game/alpha_masks.dm +++ b/code/game/alpha_masks.dm @@ -54,6 +54,10 @@ var/global/list/_alpha_masks = list() /atom/movable/proc/get_turf_alpha_mask_states() return 'icons/effects/alpha_mask.dmi' +/atom/movable/proc/should_have_alpha_mask() + // Mobs and obj both need to avoid this when on structures. Looks wonky. + return simulated && isturf(loc) && !(locate(/obj/structure) in loc) + // Proc called by /turf/Entered() to update a mob's mask overlay. /atom/movable/proc/update_turf_alpha_mask() set waitfor = FALSE @@ -65,7 +69,7 @@ var/global/list/_alpha_masks = list() if(QDELETED(src)) return var/turf/our_turf = loc - var/mask_state = isturf(our_turf) && our_turf.get_movable_alpha_mask_state(src) + var/mask_state = isturf(our_turf) && should_have_alpha_mask() && our_turf.get_movable_alpha_mask_state(src) if(mask_state) var/atom/movable/alpha_mask/mask = get_or_create_alpha_mask(src) if(mask) diff --git a/code/game/antagonist/antagonist.dm b/code/game/antagonist/antagonist.dm index be291b8ac256..042a32f12ee8 100644 --- a/code/game/antagonist/antagonist.dm +++ b/code/game/antagonist/antagonist.dm @@ -19,6 +19,7 @@ // Visual references. var/antaghud_indicator = "hudsyndicate" // Used by the ghost antagHUD. var/antag_indicator // icon_state for icons/mob/mob.dm visual indicator. + var/antag_hud_icon = 'icons/screen/hud_antag.dmi' var/faction_indicator // See antag_indicator, but for factionalized people only. var/faction_invisible // Can members of the faction identify other antagonists? @@ -104,6 +105,17 @@ /decl/special_role/validate() . = ..() + + // Check for our antaghud icons. + if(faction_indicator || antag_indicator) + if(antag_hud_icon) + if(faction_indicator && !check_state_in_icon(faction_indicator, antag_hud_icon)) + . += "missing faction_indicator '[faction_indicator]' from icon 'antag_hud_icon]'" + if(antag_indicator && !check_state_in_icon(antag_indicator, antag_hud_icon)) + . += "missing antag_indicator '[antag_indicator]' from icon 'antag_hud_icon]'" + else + . += "missing antag_hud_icon" + // Grab initial in case it was already successfully loaded. var/initial_base_to_load = initial(base_to_load) if(isnull(initial_base_to_load)) diff --git a/code/game/antagonist/antagonist_update.dm b/code/game/antagonist/antagonist_update.dm index 642141255657..fcfd2c5fcdc2 100644 --- a/code/game/antagonist/antagonist_update.dm +++ b/code/game/antagonist/antagonist_update.dm @@ -31,10 +31,12 @@ qdel(I) /decl/special_role/proc/get_indicator(var/datum/mind/recipient, var/datum/mind/other) - if(!antag_indicator || !other.current || !recipient.current) + if(!other.current || !recipient.current) return var/indicator = (faction_indicator && (other in faction_members)) ? faction_indicator : antag_indicator - var/image/I = image('icons/mob/hud.dmi', loc = other.current, icon_state = indicator, layer = ABOVE_HUMAN_LAYER) + if(!indicator) + return + var/image/I = image(antag_hud_icon, loc = other.current, icon_state = indicator, layer = ABOVE_HUMAN_LAYER) var/decl/bodytype/root_bodytype = other.current.get_bodytype() if(istype(root_bodytype)) I.pixel_x = root_bodytype.antaghud_offset_x diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 39db47d4dc66..95cf7d39aee6 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -92,7 +92,15 @@ var/global/list/areas = list() area_blurb_category = type ..() +/area/proc/get_additional_fishing_results() + return + /area/Initialize() + var/list/additional_fishing_results = get_additional_fishing_results() + if(LAZYLEN(additional_fishing_results)) + LAZYINITLIST(fishing_results) + for(var/fish in additional_fishing_results) + fishing_results[fish] = additional_fishing_results[fish] . = ..() global.areas += src if(!requires_power || !apc) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index d13760956e3b..fc3e86a037a2 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -295,6 +295,17 @@ to_chat(user, "[html_icon(src)] That's [f_name] [suffix]") to_chat(user, desc) + + var/list/alt_interactions = get_alt_interactions(user) + if(LAZYLEN(alt_interactions)) + var/list/interaction_strings = list() + for(var/interaction_type as anything in alt_interactions) + var/decl/interaction_handler/interaction = GET_DECL(interaction_type) + if(interaction.examine_desc && (interaction.always_show_on_examine || interaction.is_possible(src, user, user?.get_active_held_item()))) + interaction_strings += emote_replace_target_tokens(interaction.examine_desc, src) + if(length(interaction_strings)) + to_chat(user, SPAN_INFO("Alt-click on \the [src] to [english_list(interaction_strings, and_text = " or ")].")) + RAISE_EVENT(/decl/observ/atom_examined, src, user, distance) return TRUE @@ -502,10 +513,12 @@ - Returns: `TRUE` if qdel() was called, otherwise `FALSE` */ /atom/proc/lava_act() - visible_message(SPAN_DANGER("\The [src] sizzles and melts away, consumed by the lava!")) - playsound(src, 'sound/effects/flare.ogg', 100, 3) - qdel(src) - . = TRUE + if(simulated) + visible_message(SPAN_DANGER("\The [src] sizzles and melts away, consumed by the lava!")) + playsound(src, 'sound/effects/flare.ogg', 100, 3) + qdel(src) + return TRUE + return FALSE /** Handle this atom being hit by a thrown atom @@ -894,22 +907,6 @@ return check_loc check_loc = check_loc.loc -/** - Get a list of alt interactions for a user from this atom. - - - `user`: The mob that these alt interactions are for - - Return: A list containing the alt interactions -*/ -/atom/proc/get_alt_interactions(var/mob/user) - SHOULD_CALL_PARENT(TRUE) - RETURN_TYPE(/list) - . = list() - if(storage) - . += /decl/interaction_handler/storage_open - if(reagents?.total_volume && ATOM_IS_OPEN_CONTAINER(src)) - . += /decl/interaction_handler/wash_hands - . += /decl/interaction_handler/drink - /atom/proc/can_climb_from_below(var/mob/climber) return FALSE @@ -995,7 +992,10 @@ return /atom/proc/is_watertight() - return ATOM_IS_OPEN_CONTAINER(src) + return !ATOM_IS_OPEN_CONTAINER(src) /atom/proc/can_drink_from(mob/user) return ATOM_IS_OPEN_CONTAINER(src) && reagents?.total_volume && user.check_has_mouth() + +/atom/proc/immune_to_floor_hazards() + return !simulated diff --git a/code/game/atoms_interactions.dm b/code/game/atoms_interactions.dm new file mode 100644 index 000000000000..1f8c07525c1b --- /dev/null +++ b/code/game/atoms_interactions.dm @@ -0,0 +1,44 @@ +// List of interactions used in procs below. +var/global/list/_reagent_interactions = list( + /decl/interaction_handler/wash_hands, + /decl/interaction_handler/drink, + /decl/interaction_handler/dip_item, + /decl/interaction_handler/fill_from, + /decl/interaction_handler/empty_into +) + +/** + Get a list of standard interactions (attack_hand and attackby) for a user from this atom. + At time of writing, these are really easy to have interfere with or be interfered with by + attack_hand() and attackby() overrides. Putting them on items us a bad idea due to pickup code. + + - `user`: The mob that these interactions are for + - Return: A list containing the interactions +*/ +/atom/proc/get_standard_interactions(var/mob/user) + SHOULD_CALL_PARENT(TRUE) + RETURN_TYPE(/list) + return null + +/** + Get a default interaction for a user from this atom. + + - `user`: The mob that this interaction is for + - Return: A default interaction decl, or null. +*/ +/atom/proc/get_quick_interaction_handler(mob/user) + return + +/** + Get a list of alt interactions (alt-click) for a user from this atom. + + - `user`: The mob that these alt interactions are for + - Return: A list containing the alt interactions +*/ +/atom/proc/get_alt_interactions(var/mob/user) + SHOULD_CALL_PARENT(TRUE) + RETURN_TYPE(/list) + if(storage) + LAZYADD(., /decl/interaction_handler/storage_open) + if(reagents?.maximum_volume) + LAZYADD(., global._reagent_interactions) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 4b0049e92f2c..7142d14c3828 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -591,3 +591,15 @@ if(ATOM_IS_OPEN_CONTAINER(src)) return loc?.take_vaporized_reagent(reagent, amount) return null + +/atom/movable/immune_to_floor_hazards() + return ..() || throwing + +// TODO: make everything use this. +/atom/movable/proc/set_anchored(new_anchored) + SHOULD_CALL_PARENT(TRUE) + if(anchored != new_anchored) + anchored = new_anchored + return TRUE + return FALSE + diff --git a/code/game/atoms_movable_interactions.dm b/code/game/atoms_movable_interactions.dm index 110c09afb824..8cf50ef5bc47 100644 --- a/code/game/atoms_movable_interactions.dm +++ b/code/game/atoms_movable_interactions.dm @@ -14,6 +14,7 @@ name = "Examine" expected_user_type = /mob interaction_flags = 0 + examine_desc = "examine $TARGET_THEM$" /decl/interaction_handler/look/invoked(atom/target, mob/user, obj/item/prop) target.examine(user, get_dist(user, target)) @@ -22,6 +23,7 @@ name = "Grab" expected_target_type = /atom/movable interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEEDS_TURF + examine_desc = "grab $TARGET_THEM$" /decl/interaction_handler/grab/is_possible(atom/movable/target, mob/user, obj/item/prop) return ..() && !target.anchored diff --git a/code/game/gamemodes/endgame/endgame.dm b/code/game/gamemodes/endgame/endgame.dm index 6d81b42d639f..c1c03164c55a 100644 --- a/code/game/gamemodes/endgame/endgame.dm +++ b/code/game/gamemodes/endgame/endgame.dm @@ -1,3 +1,4 @@ +var/global/universe_has_ended = 0 /********************** * ENDGAME STUFF **********************/ diff --git a/code/game/gamemodes/endgame/nuclear_explosion/nuclear_explosion.dm b/code/game/gamemodes/endgame/nuclear_explosion/nuclear_explosion.dm index e01a6995e1b5..3aa8d9d84b66 100644 --- a/code/game/gamemodes/endgame/nuclear_explosion/nuclear_explosion.dm +++ b/code/game/gamemodes/endgame/nuclear_explosion/nuclear_explosion.dm @@ -38,7 +38,7 @@ SSticker.mode.station_was_nuked = 1 SSticker.mode.station_explosion_in_progress = FALSE if(!SSticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is - universe_has_ended = 1 + universe_has_ended = TRUE /datum/universal_state/nuclear_explosion/OnExit() if(SSticker.mode) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index be38f8871efc..e6a2f45c19a4 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -283,11 +283,10 @@ var/global/list/additional_antag_types = list() for(var/decl/special_role/antag in antag_templates) antag.reset_antag_selection() -/decl/game_mode/proc/announce_ert_disabled() - if(!ert_disabled) - return - - var/list/reasons = list( +/// Gets a list of default reasons for the ERT to be disabled. +/decl/game_mode/proc/possible_ert_disabled_reasons() + // This uses a static var so that modpacks can add default reasons, e.g. "supermatter dust". + var/static/list/reasons = list( "political instability", "quantum fluctuations", "hostile raiders", @@ -300,7 +299,6 @@ var/global/list/additional_antag_types = list() "wormholes to another dimension", "a telescience mishap", "radiation flares", - "supermatter dust", "leaks into a negative reality", "antiparticle clouds", "residual exotic energy", @@ -319,7 +317,12 @@ var/global/list/additional_antag_types = list() "classified security operations", "a gargantuan glowing goat" ) - command_announcement.Announce("The presence of [pick(reasons)] in the region is tying up all available local emergency resources; emergency response teams cannot be called at this time, and post-evacuation recovery efforts will be substantially delayed.","Emergency Transmission") + return reasons + +/decl/game_mode/proc/announce_ert_disabled() + if(!ert_disabled) + return + command_announcement.Announce("The presence of [pick(possible_ert_disabled_reasons())] in the region is tying up all available local emergency resources; emergency response teams cannot be called at this time, and post-evacuation recovery efforts will be substantially delayed.","Emergency Transmission") /decl/game_mode/proc/check_finished() if(SSevac.evacuation_controller?.round_over() || station_was_nuked) diff --git a/code/game/jobs/job/_job.dm b/code/game/jobs/job/_job.dm index f5df1fe51970..06e985a8772d 100644 --- a/code/game/jobs/job/_job.dm +++ b/code/game/jobs/job/_job.dm @@ -34,7 +34,8 @@ var/announced = TRUE // If their arrival is announced on radio var/latejoin_at_spawnpoints // If this job should use roundstart spawnpoints for latejoin (offstation jobs etc) var/forced_spawnpoint // If set to a spawnpoint name, will use that spawn point for joining as this job. - var/hud_icon // icon used for Sec HUD overlay + var/hud_icon // icon used for secHUD overlay + var/hud_icon_state // icon state used for secHUD overlay // A list of string IDs for keys to grant on join. var/list/lock_keys = list() @@ -69,7 +70,7 @@ if(type == /datum/job && global.using_map.default_job_type == type) title = "Debug Job" - hud_icon = "hudblank" + hud_icon_state = "hudblank" outfit_type = /decl/outfit/job/generic/scientist autoset_department = TRUE @@ -83,7 +84,9 @@ spawn_positions = 0 if(!hud_icon) - hud_icon = "hud[ckey(title)]" + hud_icon = global.using_map.hud_icons + if(!hud_icon_state) + hud_icon_state = "hud[ckey(title)]" ..() diff --git a/code/game/machinery/_machines_base/stock_parts/card_reader.dm b/code/game/machinery/_machines_base/stock_parts/card_reader.dm index aecd5af4e4f9..3f92564a8d7e 100644 --- a/code/game/machinery/_machines_base/stock_parts/card_reader.dm +++ b/code/game/machinery/_machines_base/stock_parts/card_reader.dm @@ -73,4 +73,5 @@ name = "Eject Card" icon = 'icons/screen/radial.dmi' icon_state = "radial_eject_id" - expected_component_type = /obj/item/stock_parts/item_holder/card_reader \ No newline at end of file + expected_component_type = /obj/item/stock_parts/item_holder/card_reader + examine_desc = "eject an inserted ID card" diff --git a/code/game/machinery/_machines_base/stock_parts/cupholder.dm b/code/game/machinery/_machines_base/stock_parts/cupholder.dm index 23f56f7772cb..da49b9b5e9c1 100644 --- a/code/game/machinery/_machines_base/stock_parts/cupholder.dm +++ b/code/game/machinery/_machines_base/stock_parts/cupholder.dm @@ -47,4 +47,5 @@ /decl/interaction_handler/remove_held_item/cup name = "Remove Cup" - expected_component_type = /obj/item/stock_parts/item_holder/cupholder \ No newline at end of file + expected_component_type = /obj/item/stock_parts/item_holder/cupholder + examine_desc = "remove a cup" diff --git a/code/game/machinery/_machines_base/stock_parts/disk_reader.dm b/code/game/machinery/_machines_base/stock_parts/disk_reader.dm index e61cf6be322d..7c35679ef557 100644 --- a/code/game/machinery/_machines_base/stock_parts/disk_reader.dm +++ b/code/game/machinery/_machines_base/stock_parts/disk_reader.dm @@ -42,4 +42,5 @@ /decl/interaction_handler/remove_held_item/disk name = "Eject Disk" - expected_component_type = /obj/item/stock_parts/item_holder/disk_reader \ No newline at end of file + expected_component_type = /obj/item/stock_parts/item_holder/disk_reader + examine_desc = "remove a disk" diff --git a/code/game/machinery/_machines_base/stock_parts/item_holder.dm b/code/game/machinery/_machines_base/stock_parts/item_holder.dm index 3462f18f5605..d6404088a4c5 100644 --- a/code/game/machinery/_machines_base/stock_parts/item_holder.dm +++ b/code/game/machinery/_machines_base/stock_parts/item_holder.dm @@ -128,6 +128,7 @@ name = "Eject Item" icon = 'icons/screen/radial.dmi' icon_state = "radial_eject" + examine_desc = "eject an item" var/obj/item/stock_parts/item_holder/expected_component_type /decl/interaction_handler/remove_held_item/validate() diff --git a/code/game/machinery/ai_slipper.dm b/code/game/machinery/ai_slipper.dm index dc389cb9dec3..e571411e9730 100644 --- a/code/game/machinery/ai_slipper.dm +++ b/code/game/machinery/ai_slipper.dm @@ -7,9 +7,9 @@ var/uses = 20 var/disabled = 1 var/locked = 1 - var/cooldown_time = 0 - var/cooldown_timeleft = 0 - var/cooldown_on = 0 + var/slip_cooldown_time = 0 + var/slip_cooldown_timeleft = 0 + var/slip_cooldown_on = 0 initial_access = list(access_ai_upload) /obj/machinery/ai_slipper/on_update_icon() @@ -52,13 +52,11 @@ if(!area || !isturf(loc)) return var/t = "AI Liquid Dispenser ([area.proper_name])
" - if(src.locked && (!issilicon(user))) t += "(Swipe ID card to unlock control panel.)
" else t += text("Dispenser [] - []?
\n", src.disabled?"deactivated":"activated", src, src.disabled?"Enable":"Disable") t += text("Uses Left: [uses]. Activate the dispenser?
\n") - show_browser(user, t, "window=computer;size=575x450") onclose(user, "computer") @@ -74,30 +72,26 @@ update_icon() . = TOPIC_REFRESH if (href_list["toggleUse"]) - if(!(cooldown_on || disabled)) + if(!(slip_cooldown_on || disabled)) new /obj/effect/effect/foam(src.loc) src.uses-- - cooldown_on = 1 - cooldown_time = world.timeofday + 100 + slip_cooldown_on = 1 + slip_cooldown_time = world.timeofday + 100 slip_process() . = TOPIC_REFRESH - if(. == TOPIC_REFRESH) ui_interact(user) /obj/machinery/ai_slipper/proc/slip_process() - while(cooldown_time - world.timeofday > 0) - var/ticksleft = cooldown_time - world.timeofday - + while(slip_cooldown_time - world.timeofday > 0) + var/ticksleft = slip_cooldown_time - world.timeofday if(ticksleft > 1e5) - cooldown_time = world.timeofday + 10 // midnight rollover - - - cooldown_timeleft = (ticksleft / 10) + slip_cooldown_time = world.timeofday + 10 // midnight rollover + slip_cooldown_timeleft = (ticksleft / 10) sleep(5) if (uses <= 0) return if (uses >= 0) - cooldown_on = 0 + slip_cooldown_on = 0 src.power_change() return diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm index b9664324917c..721eddb4ad96 100644 --- a/code/game/machinery/atmo_control.dm +++ b/code/game/machinery/atmo_control.dm @@ -331,8 +331,3 @@ radio_connection.post_signal(src, signal, device_tag) ..() - -/obj/machinery/computer/air_control/supermatter_core - icon = 'icons/obj/computer.dmi' - frequency = 1438 - out_pressure_mode = 1 \ No newline at end of file diff --git a/code/game/machinery/supplybeacon.dm b/code/game/machinery/supplybeacon.dm index 550e474d0ef4..831363ce53e5 100644 --- a/code/game/machinery/supplybeacon.dm +++ b/code/game/machinery/supplybeacon.dm @@ -11,10 +11,6 @@ var/deploy_path = /obj/structure/supply_beacon var/deploy_time = 30 -/obj/item/supply_beacon/supermatter - name = "inactive supermatter supply beacon" - deploy_path = /obj/structure/supply_beacon/supermatter - /obj/item/supply_beacon/attack_self(var/mob/user) user.visible_message(SPAN_NOTICE("\The [user] begins setting up \the [src].")) if(!do_after(user, deploy_time, src)) @@ -45,10 +41,6 @@ if(!drop_type) drop_type = pick(supply_drop_random_loot_types()) -/obj/structure/supply_beacon/supermatter - name = "supermatter supply beacon" - drop_type = "supermatter" - /obj/structure/supply_beacon/attackby(var/obj/item/W, var/mob/user) if(!activated && IS_WRENCH(W)) anchored = !anchored diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index a82e80825105..bf5c37416308 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -250,6 +250,7 @@ /decl/interaction_handler/start_washer name = "Start washer" expected_target_type = /obj/machinery/washing_machine + examine_desc = "start a wash cycle" /decl/interaction_handler/start_washer/is_possible(obj/machinery/washing_machine/washer, mob/user) . = ..() @@ -263,6 +264,7 @@ /decl/interaction_handler/toggle_open/washing_machine name = "Toggle detergent port" expected_target_type = /obj/machinery/washing_machine + examine_desc = "open the detergent port" /decl/interaction_handler/toggle_open/washing_machine/invoked(atom/target, mob/user, obj/item/prop) var/obj/machinery/washing_machine/washer = target diff --git a/code/game/objects/_objs_interactions.dm b/code/game/objects/_objs_interactions.dm index b295c6fd71fc..65d143b39b36 100644 --- a/code/game/objects/_objs_interactions.dm +++ b/code/game/objects/_objs_interactions.dm @@ -8,6 +8,7 @@ /decl/interaction_handler/rotate name = "Rotate" expected_target_type = /obj + examine_desc = "rotate $TARGET_THEM$" /decl/interaction_handler/rotate/is_possible(atom/target, mob/user, obj/item/prop) . = ..() diff --git a/code/game/objects/effects/chem/chemsmoke.dm b/code/game/objects/effects/chem/chemsmoke.dm index fc4fdc8470d0..ccfd9b93b6e5 100644 --- a/code/game/objects/effects/chem/chemsmoke.dm +++ b/code/game/objects/effects/chem/chemsmoke.dm @@ -160,12 +160,6 @@ if(LAZYLEN(chemholder.reagents.reagent_volumes)) for(var/turf/T in (wallList|targetTurfs)) chemholder.reagents.touch_turf(T) - for(var/turf/T in targetTurfs) - for(var/atom/A in T.contents) - if(istype(A, /obj/effect/effect/smoke/chem) || ismob(A)) - continue - else if(isobj(A) && !A.simulated) - chemholder.reagents.touch_obj(A) var/color = chemholder.reagents.get_color() //build smoke icon var/icon/I diff --git a/code/game/objects/effects/chem/foam.dm b/code/game/objects/effects/chem/foam.dm index 5ff195477656..1e7a3685c90e 100644 --- a/code/game/objects/effects/chem/foam.dm +++ b/code/game/objects/effects/chem/foam.dm @@ -37,8 +37,6 @@ if(!metal && reagents) var/turf/T = get_turf(src) reagents.touch_turf(T) - for(var/obj/O in T) - reagents.touch_obj(O) /obj/effect/effect/foam/Process() if(--amount < 0) diff --git a/code/game/objects/effects/decals/Cleanable/tracks.dm b/code/game/objects/effects/decals/Cleanable/tracks.dm index 870df8fbbf12..9ef315bf7870 100644 --- a/code/game/objects/effects/decals/Cleanable/tracks.dm +++ b/code/game/objects/effects/decals/Cleanable/tracks.dm @@ -124,7 +124,7 @@ update_icon() /obj/effect/decal/cleanable/blood/tracks/on_update_icon() - overlays.Cut() + cut_overlays() color = "#ffffff" var/truedir=0 @@ -145,8 +145,9 @@ track.fresh=0 track.overlay=I stack[stack_idx]=track - overlays += I + add_overlay(I) updatedtracks=0 // Clear our memory of updated tracks. + compile_overlays() /obj/effect/decal/cleanable/blood/tracks/footprints name = "wet footprints" diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index b5d5d29540a0..664d7af8c8fb 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -1,27 +1,30 @@ /obj/effect/decal/cleanable/crayon - name = "rune" - desc = "A rune drawn in crayon." - icon = 'icons/obj/rune.dmi' + name = "rune" + desc = "A rune drawn in crayon." + icon = 'icons/effects/crayondecal.dmi' + icon_state = "rune1" weather_sensitive = FALSE + var/shade_color = COLOR_BLACK -/obj/effect/decal/cleanable/crayon/Initialize(mapload, main = "#ffffff", shade = "#000000", var/type = "rune") - name = type - desc = "\A [type] drawn in crayon." +/obj/effect/decal/cleanable/crayon/Initialize(mapload, _color = COLOR_WHITE, _shade_color = COLOR_BLACK, _drawtype = CRAYON_DRAW_RUNE) + . = ..() + name = _drawtype + desc = "\A [_drawtype], drawn in crayon." + color = _color + shade_color = _shade_color + switch(_drawtype) + if(CRAYON_DRAW_RUNE) + icon_state = "rune[rand(1,6)]" + if(CRAYON_DRAW_GRAFFITI) + icon_state = pick("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa") + else + icon_state = _drawtype + update_icon() - switch(type) - if("rune") - type = "rune[rand(1,6)]" - if("graffiti") - type = pick("amyjon","face","matt","revolution","engie","guy","end","dwarf","uboa") - - var/icon/mainOverlay = new/icon('icons/effects/crayondecal.dmi',"[type]",2.1) - var/icon/shadeOverlay = new/icon('icons/effects/crayondecal.dmi',"[type]s",2.1) - - mainOverlay.Blend(main,ICON_ADD) - shadeOverlay.Blend(shade,ICON_ADD) - - overlays += mainOverlay - overlays += shadeOverlay - - add_hiddenprint(usr) - . = ..() \ No newline at end of file +/obj/effect/decal/cleanable/crayon/on_update_icon() + . = ..() + if(shade_color) + var/overlay_state = "[icon_state]s" + if(check_state_in_icon(overlay_state, icon)) + add_overlay(overlay_image(icon, overlay_state, shade_color, RESET_COLOR)) + compile_overlays() diff --git a/code/game/objects/effects/dirty_floor.dm b/code/game/objects/effects/dirty_floor.dm index e67ac44b0590..8c2df8b9f8b0 100644 --- a/code/game/objects/effects/dirty_floor.dm +++ b/code/game/objects/effects/dirty_floor.dm @@ -9,6 +9,10 @@ alpha = 0 var/dirt_amount = 0 +/obj/effect/decal/cleanable/dirt/lava_act() + qdel(src) + return TRUE + // 'the dirt falls through the x' is pretty silly, dirt is generated by people walking. /obj/effect/decal/cleanable/dirt/begin_falling(lastloc, below) SHOULD_CALL_PARENT(FALSE) diff --git a/code/game/objects/effects/footprints.dm b/code/game/objects/effects/footprints.dm new file mode 100644 index 000000000000..a8af8a6112db --- /dev/null +++ b/code/game/objects/effects/footprints.dm @@ -0,0 +1,50 @@ +// Effect used to render dark spot on turfs like snow/mud. +/obj/effect/footprints + icon = 'icons/mob/footprints/footprints.dmi' + icon_state = "blank" + simulated = FALSE + anchored = TRUE + is_spawnable_type = FALSE + blend_mode = BLEND_SUBTRACT + alpha = 128 + var/list/footprints + +/obj/effect/footprints/Initialize(mapload) + . = ..() + verbs.Cut() + name = null + +/obj/effect/footprints/Destroy() + QDEL_NULL(footprints) + . = ..() + +/obj/effect/footprints/on_update_icon() + set_overlays(footprints?.Copy()) + compile_overlays() + +/obj/effect/footprints/proc/add_footprints(mob/crosser, footprint_icon, movement_dir, use_state = "coming") + var/image/update_footprint + for(var/image/footprint in footprints) + if(footprint.icon == footprint_icon && footprint.dir == movement_dir && footprint.icon_state == use_state) + update_footprint = footprint + break + if(!update_footprint) + update_footprint = image(footprint_icon, icon_state = use_state, dir = movement_dir) + update_footprint.alpha = 20 + LAZYADD(footprints, update_footprint) + if(update_footprint.alpha < 120) + update_footprint.alpha += round(crosser.get_object_size() / 5) + queue_icon_update() + return TRUE + +/mob/proc/get_footprints_icon() + if(is_floating) + return null + if(buckled || current_posture?.prone) + return 'icons/mob/footprints/footprints_trail.dmi' + if(istype(buckled, /obj/structure/bed/chair)) + return 'icons/mob/footprints/footprints_wheelchair.dmi' + var/obj/item/clothing/shoes/shoes = get_equipped_item(slot_shoes_str) + if(istype(shoes) && shoes.footprint_icon) + return shoes.footprint_icon + return get_bodytype()?.get_footprints_icon() diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index 4a78d796efd2..38cd105e6d01 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -35,11 +35,12 @@ icon = 'icons/misc/beach.dmi' icon_state = "coconuts" +// This isn't modularized because I hate modularizing layer defines. Bite me. /obj/effect/overlay/bluespacify name = "subspace" icon = 'icons/turf/space.dmi' icon_state = "bluespacify" - layer = SUPERMATTER_WALL_LAYER + layer = SUBSPACE_WALL_LAYER /obj/effect/overlay/wallrot name = "wallrot" @@ -54,3 +55,13 @@ . = ..() pixel_x += rand(-10, 10) pixel_y += rand(-10, 10) + +/// Set and cleaned up by moving projectiles for the most part. +/obj/effect/overlay/projectile_trail + var/obj/item/projectile/master + +/obj/effect/overlay/projectile_trail/Destroy() + if(master) + LAZYREMOVE(master.proj_trails, src) + master = null + return ..() diff --git a/code/game/objects/items/_item_interactions.dm b/code/game/objects/items/_item_interactions.dm index b9efb6e61dc8..6467b1d19d53 100644 --- a/code/game/objects/items/_item_interactions.dm +++ b/code/game/objects/items/_item_interactions.dm @@ -34,6 +34,7 @@ name = "Open Storage" expected_target_type = /atom incapacitation_flags = INCAPACITATION_DISRUPTED + examine_desc = "open $TARGET_THEIR$ storage" /decl/interaction_handler/storage_open/is_possible(atom/target, mob/user, obj/item/prop) . = ..() && (ishuman(user) || isrobot(user) || issmall(user)) && target?.storage diff --git a/code/game/objects/items/_item_reagents.dm b/code/game/objects/items/_item_reagents.dm index abe58d48fbf6..e664024c9520 100644 --- a/code/game/objects/items/_item_reagents.dm +++ b/code/game/objects/items/_item_reagents.dm @@ -1,4 +1,4 @@ -/obj/item/proc/standard_dispenser_refill(var/mob/user, var/obj/structure/reagent_dispensers/target, skip_container_check = FALSE) // This goes into afterattack +/obj/item/proc/standard_dispenser_refill(mob/user, obj/structure/reagent_dispensers/target, skip_container_check = FALSE) // This goes into afterattack if(!istype(target) || (!skip_container_check && (target.atom_flags & ATOM_FLAG_OPEN_CONTAINER))) return FALSE diff --git a/code/game/objects/items/artifice/chain.dm b/code/game/objects/items/artifice/chain.dm new file mode 100644 index 000000000000..3a48abad4759 --- /dev/null +++ b/code/game/objects/items/artifice/chain.dm @@ -0,0 +1,9 @@ +// Stub for forging. TODO crafting that uses chains. +/obj/item/chain + name = "chain" + name_prefix = "length of" + desc = "A flexible length of interconnected links forming a chain." + icon_state = ICON_STATE_WORLD + icon = 'icons/obj/items/chain.dmi' + material = /decl/material/solid/metal/iron + material_alteration = MAT_FLAG_ALTERATION_ALL diff --git a/code/game/objects/items/artifice/hook.dm b/code/game/objects/items/artifice/hook.dm new file mode 100644 index 000000000000..c20c77b14801 --- /dev/null +++ b/code/game/objects/items/artifice/hook.dm @@ -0,0 +1,8 @@ +// Stub for forging. TODO use for slapcrafting a fishing rod? +/obj/item/hook + name = "hook" + desc = "A small, sharp, curved object." + icon_state = ICON_STATE_WORLD + icon = 'icons/obj/items/hook.dmi' + material = /decl/material/solid/metal/iron + material_alteration = MAT_FLAG_ALTERATION_ALL diff --git a/code/game/objects/items/blades/folding.dm b/code/game/objects/items/blades/folding.dm index 029557ab3b9a..9617f3cbb84b 100644 --- a/code/game/objects/items/blades/folding.dm +++ b/code/game/objects/items/blades/folding.dm @@ -98,6 +98,7 @@ name = "Adjust Folding Knife" expected_target_type = /obj/item/bladed/folding interaction_flags = INTERACTION_NEEDS_INVENTORY | INTERACTION_NEEDS_PHYSICAL_INTERACTION + examine_desc = "adjust $TARGET_THEM$" /decl/interaction_handler/folding_knife/is_possible(atom/target, mob/user) . = ..() diff --git a/code/game/objects/items/blades/spear_improvised.dm b/code/game/objects/items/blades/spear_improvised.dm index d9846e8a1a05..9f1a1da24257 100644 --- a/code/game/objects/items/blades/spear_improvised.dm +++ b/code/game/objects/items/blades/spear_improvised.dm @@ -34,7 +34,7 @@ hilt_material = /decl/material/solid/organic/wood/oak force_binding_color = COLOR_GREEN -/obj/item/bladed/polearm/spear/improvised/supermatter +/obj/item/bladed/polearm/spear/improvised/exotic_matter material = /decl/material/solid/exotic_matter hilt_material = /decl/material/solid/organic/wood/ebony force_binding_color = COLOR_INDIGO diff --git a/code/game/objects/items/books/manuals/engineering.dm b/code/game/objects/items/books/manuals/engineering.dm index 1dccd0022d36..bad39f2562ce 100644 --- a/code/game/objects/items/books/manuals/engineering.dm +++ b/code/game/objects/items/books/manuals/engineering.dm @@ -26,13 +26,6 @@ title = "Particle Accelerator User's Guide" guide_decl = /datum/codex_entry/guide/particle_accelerator -/obj/item/book/manual/supermatter_engine - name = "supermatter engine reference manual" - icon = 'icons/obj/items/books/book_supermatter.dmi' - author = "Central Engineering Division" - title = "Supermatter Engine Operating Manual" - guide_decl = /datum/codex_entry/guide/supermatter - /obj/item/book/manual/rust_engine name = "fusion reactor reference Manual" icon_state = "bookMagazine" diff --git a/code/game/objects/items/chisel.dm b/code/game/objects/items/chisel.dm new file mode 100644 index 000000000000..8bdcf2ab1a40 --- /dev/null +++ b/code/game/objects/items/chisel.dm @@ -0,0 +1,12 @@ +// Stub for forging. TODO implement TOOL_CHISEL. +/obj/item/tool/chisel + name = "chisel" + desc = "A hard, sharpened tool used to chisel stone, wood or bone." + icon_state = ICON_STATE_WORLD + icon = 'icons/obj/items/tool/chisel.dmi' + material = /decl/material/solid/metal/steel + handle_material = /decl/material/solid/organic/plastic + binding_material = null + +/obj/item/tool/chisel/forged + handle_material = null diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm index c58b5bd7ae2f..4508758e19d3 100644 --- a/code/game/objects/items/devices/gps.dm +++ b/code/game/objects/items/devices/gps.dm @@ -377,6 +377,7 @@ var/global/list/all_gps_units = list() /decl/interaction_handler/gps_toggle name = "Toggle Tracking" expected_target_type = /obj/item/gps + examine_desc = "toggle GPS tracking" /decl/interaction_handler/gps_toggle/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/gps/G = target diff --git a/code/game/objects/items/devices/paint_sprayer.dm b/code/game/objects/items/devices/paint_sprayer.dm index 88c1e1195d73..3c6f08681458 100644 --- a/code/game/objects/items/devices/paint_sprayer.dm +++ b/code/game/objects/items/devices/paint_sprayer.dm @@ -456,6 +456,7 @@ name = "Change Color Preset" expected_target_type = /obj/item/paint_sprayer interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEEDS_INVENTORY + examine_desc = "change the color preset" /decl/interaction_handler/paint_sprayer_colour/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/paint_sprayer/sprayer = target diff --git a/code/game/objects/items/horseshoe.dm b/code/game/objects/items/horseshoe.dm new file mode 100644 index 000000000000..089d3c9cc4bf --- /dev/null +++ b/code/game/objects/items/horseshoe.dm @@ -0,0 +1,8 @@ +// Stub for forging. TODO implement shoes on honse. +/obj/item/horseshoe + name = "horseshoe" + desc = "A curved length of metal, usually nailed to a horse's hoof. May bring luck." + icon_state = ICON_STATE_WORLD + icon = 'icons/obj/items/horseshoe.dmi' + material = /decl/material/solid/metal/iron + material_alteration = MAT_FLAG_ALTERATION_ALL diff --git a/code/game/objects/items/weapons/broom.dm b/code/game/objects/items/weapons/broom.dm index b19ef3bf316d..aaa799ed5a84 100644 --- a/code/game/objects/items/weapons/broom.dm +++ b/code/game/objects/items/weapons/broom.dm @@ -43,15 +43,23 @@ // Sweep up dirt. if(isturf(A)) + var/turf/cleaning = A + var/dirty = cleaning.get_dirt() if(dirty > 10) // a small amount so that you can't sweep immediately after someone walks somewhere user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) user.visible_message(SPAN_NOTICE("\The [user] sweeps \the [A].")) playsound(A, "sweeping", 100, TRUE) cleaning.remove_dirt(min(dirty, rand(20,30))) - else - to_chat(user, SPAN_WARNING("\The [cleaning] is not in need of sweeping.")) + return TRUE + + var/obj/effect/footprints/prints = locate() in cleaning + if(prints) + user.visible_message(SPAN_NOTICE("\The [user] sweeps away the footprints.")) + return TRUE + + to_chat(user, SPAN_WARNING("\The [cleaning] is not in need of sweeping.")) return TRUE // Sweep up dry spills. diff --git a/code/game/objects/items/weapons/circuitboards/computer/air_management.dm b/code/game/objects/items/weapons/circuitboards/computer/air_management.dm index fe637a0b0dde..0498af958396 100644 --- a/code/game/objects/items/weapons/circuitboards/computer/air_management.dm +++ b/code/game/objects/items/weapons/circuitboards/computer/air_management.dm @@ -7,19 +7,6 @@ var/sensor_name var/list/sensor_information = list() -/obj/item/stock_parts/circuitboard/air_management/supermatter_core - name = "circuitboard (core control)" - build_path = /obj/machinery/computer/air_control/supermatter_core - frequency = 1438 - var/input_tag - var/output_tag - - var/list/input_info = list() - var/list/output_info = list() - - var/input_flow_setting = 700 - var/pressure_setting = 100 - /obj/item/stock_parts/circuitboard/air_management/injector_control name = "circuitboard (injector control)" build_path = /obj/machinery/computer/air_control/fuel_injection @@ -42,18 +29,6 @@ C.sensor_info = sensor_information.Copy() return 1 -/obj/item/stock_parts/circuitboard/air_management/supermatter_core/construct(var/obj/machinery/computer/air_control/supermatter_core/SC) - if(..(SC)) - SC.input_tag = input_tag - SC.output_tag = output_tag - - SC.input_info = input_info.Copy() - SC.output_info = output_info.Copy() - - SC.input_flow_setting = input_flow_setting - SC.pressure_setting = input_flow_setting - return 1 - /obj/item/stock_parts/circuitboard/air_management/injector_control/construct(var/obj/machinery/computer/air_control/fuel_injection/FI) if(..(FI)) FI.device_tag = device_tag @@ -75,18 +50,6 @@ sensor_information = C.sensor_info.Copy() return 1 -/obj/item/stock_parts/circuitboard/air_management/supermatter_core/deconstruct(var/obj/machinery/computer/air_control/supermatter_core/SC) - if(..(SC)) - input_tag = SC.input_tag - output_tag = SC.output_tag - - input_info = SC.input_info.Copy() - output_info = SC.output_info.Copy() - - input_flow_setting = SC.input_flow_setting - pressure_setting = SC.input_flow_setting - return 1 - /obj/item/stock_parts/circuitboard/air_management/injector_control/deconstruct(var/obj/machinery/computer/air_control/fuel_injection/FI) if(..(FI)) device_tag = FI.device_tag diff --git a/code/game/objects/items/weapons/circuitboards/machinery/chemistry.dm b/code/game/objects/items/weapons/circuitboards/machinery/chemistry.dm index 44377add2c09..1d9cccaf50b3 100644 --- a/code/game/objects/items/weapons/circuitboards/machinery/chemistry.dm +++ b/code/game/objects/items/weapons/circuitboards/machinery/chemistry.dm @@ -1,5 +1,5 @@ /obj/item/stock_parts/circuitboard/reagent_heater - name = "circuitboard (chemical heater)" + name = "circuitboard (hotplate)" build_path = /obj/machinery/reagent_temperature board_type = "machine" origin_tech = @'{"powerstorage":2,"engineering":1}' diff --git a/code/game/objects/items/weapons/material/shards.dm b/code/game/objects/items/weapons/material/shards.dm index 7ff92bf32ad2..4b0453f2154a 100644 --- a/code/game/objects/items/weapons/material/shards.dm +++ b/code/game/objects/items/weapons/material/shards.dm @@ -87,31 +87,33 @@ if(!isliving(AM)) return - var/mob/living/M = AM - if(M.buckled) //wheelchairs, office chairs, rollerbeds + var/mob/living/victim = AM + if(victim.buckled) //wheelchairs, office chairs, rollerbeds + return + if(victim.immune_to_floor_hazards()) return playsound(src.loc, 'sound/effects/glass_step.ogg', 50, 1) // not sure how to handle metal shards with sounds - var/decl/species/walker_species = M.get_species() - if(walker_species && (walker_species.get_shock_vulnerability(M) < 0.5 || (walker_species.species_flags & (SPECIES_FLAG_NO_EMBED|SPECIES_FLAG_NO_MINOR_CUT)))) //Thick skin. + var/decl/species/walker_species = victim.get_species() + if(walker_species && (walker_species.get_shock_vulnerability(victim) < 0.5 || (walker_species.species_flags & (SPECIES_FLAG_NO_EMBED|SPECIES_FLAG_NO_MINOR_CUT)))) //Thick skin. return - var/obj/item/shoes = M.get_equipped_item(slot_shoes_str) - var/obj/item/suit = M.get_equipped_item(slot_wear_suit_str) + var/obj/item/shoes = victim.get_equipped_item(slot_shoes_str) + var/obj/item/suit = victim.get_equipped_item(slot_wear_suit_str) if(shoes || (suit && (suit.body_parts_covered & SLOT_FEET))) return var/list/check = list(BP_L_FOOT, BP_R_FOOT) while(check.len) var/picked = pick_n_take(check) - var/obj/item/organ/external/affecting = GET_EXTERNAL_ORGAN(M, picked) + var/obj/item/organ/external/affecting = GET_EXTERNAL_ORGAN(victim, picked) if(!affecting || BP_IS_PROSTHETIC(affecting)) continue - to_chat(M, SPAN_DANGER("You step on \the [src]!")) + to_chat(victim, SPAN_DANGER("You step on \the [src]!")) affecting.take_external_damage(5, 0) if(affecting.can_feel_pain()) - SET_STATUS_MAX(M, STAT_WEAK, 3) + SET_STATUS_MAX(victim, STAT_WEAK, 3) return //Prevent the shard from being allowed to shatter diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm index 70cb57c3f479..e46bd9dddc49 100644 --- a/code/game/objects/items/weapons/mop.dm +++ b/code/game/objects/items/weapons/mop.dm @@ -12,7 +12,11 @@ /decl/material/solid/organic/cloth = MATTER_AMOUNT_SECONDARY, ) var/mopspeed = 40 - var/list/moppable_types = list( + var/static/list/moppable_types + +/obj/item/mop/proc/populate_moppable_types() + moppable_types = list( + /turf/floor, /obj/effect/decal/cleanable, /obj/structure/catwalk ) @@ -20,6 +24,8 @@ /obj/item/mop/Initialize() . = ..() initialize_reagents() + if(!moppable_types) + populate_moppable_types() /obj/item/mop/initialize_reagents(populate = TRUE) create_reagents(30) @@ -27,45 +33,40 @@ /obj/item/mop/afterattack(atom/A, mob/user, proximity) if(!proximity) - return + return ..() + var/turf/moppable_turf = get_turf(A) + if(!istype(moppable_turf)) + return ..() - var/moppable - if(isturf(A)) - var/turf/T = A - if(T?.reagents?.total_volume > 0) - if(T.reagents.total_volume > FLUID_SHALLOW) + if(moppable_turf?.reagents?.total_volume > 0) + if(moppable_turf.reagents.total_volume > FLUID_SHALLOW) + to_chat(user, SPAN_WARNING("There is too much water here to be mopped up.")) + return TRUE + user.visible_message(SPAN_NOTICE("\The [user] begins to mop up \the [moppable_turf].")) + if(do_after(user, 40, moppable_turf) && !QDELETED(moppable_turf)) + if(moppable_turf.reagents?.total_volume > FLUID_SHALLOW) to_chat(user, SPAN_WARNING("There is too much water here to be mopped up.")) else - user.visible_message(SPAN_NOTICE("\The [user] begins to mop up \the [T].")) - if(do_after(user, 40, T) && !QDELETED(T)) - if(T.reagents?.total_volume > FLUID_SHALLOW) - to_chat(user, SPAN_WARNING("There is too much water here to be mopped up.")) - else - to_chat(user, SPAN_NOTICE("You have finished mopping!")) - T.reagents?.clear_reagents() - return - moppable = TRUE - - else if(is_type_in_list(A,moppable_types)) - moppable = TRUE - - if(moppable) - if(reagents.total_volume < 1) - to_chat(user, SPAN_WARNING("Your mop is dry!")) - return - var/turf/T = get_turf(A) - if(!T) - return - - var/trans_amt = FLUID_QDEL_POINT - if(user.check_intent(I_FLAG_HARM)) - trans_amt = round(FLUID_PUDDLE * 0.25) - user.visible_message(SPAN_DANGER("\The [user] begins to aggressively mop \the [T]!")) - else - user.visible_message(SPAN_NOTICE("\The [user] begins to clean \the [T].")) - if(do_after(user, mopspeed, T) && reagents?.total_volume) - reagents.splash(T, trans_amt) - to_chat(user, SPAN_NOTICE("You have finished mopping!")) + to_chat(user, SPAN_NOTICE("You have finished mopping!")) + moppable_turf.reagents?.clear_reagents() + return TRUE + + if(!is_type_in_list(A, moppable_types)) + return ..() + + if(reagents?.total_volume < 1) + to_chat(user, SPAN_WARNING("\The [src] is dry!")) + return TRUE + + if(user.check_intent(I_FLAG_HARM)) + user.visible_message(SPAN_DANGER("\The [user] begins to aggressively mop \the [moppable_turf]!")) + else + user.visible_message(SPAN_NOTICE("\The [user] begins to clean \the [moppable_turf].")) + if(do_after(user, mopspeed, moppable_turf) && reagents?.total_volume) + reagents.touch_turf(moppable_turf) + reagents.remove_any(1) + to_chat(user, SPAN_NOTICE("You have finished mopping!")) + return TRUE /obj/effect/attackby(obj/item/I, mob/user) if(istype(I, /obj/item/mop) || istype(I, /obj/item/soap)) diff --git a/code/game/objects/items/weapons/secrets_disk.dm b/code/game/objects/items/weapons/secrets_disk.dm index ee152b86151a..ec806c4132fc 100644 --- a/code/game/objects/items/weapons/secrets_disk.dm +++ b/code/game/objects/items/weapons/secrets_disk.dm @@ -13,19 +13,39 @@ This one has a lengthy legal label on it denoting it the private, copyrighted property of the Expeditionary Corps Organisation." req_access = list(access_rd) +/obj/item/disk/secret_project/proc/get_secret_project_codenames() + var/static/list/codenames = list( + "gamma", "delta", "epsilon", "zeta", "theta", "lambda", "omicron", "sigma", "tau", + "upsilon", "omega", "echelon", "prism", "calypso", "bernoulli", "harmony", "nyx", "fresnel" + ) + +/obj/item/disk/secret_project/proc/get_secret_project_types() + var/static/list/types = list( + "an experimental design for", + "a blueprint to build", + "a long set of theoretical formulas detailing the functioning of" + ) + return types + +/obj/item/disk/secret_project/proc/get_secret_project_nouns() + var/static/list/nouns = list( + "a superluminal artillery cannon", "a fusion engine", "an atmospheric scrubber",\ + "a human cloning pod", "a microwave oven", "a wormhole generator", "a laser carbine", "an energy pistol",\ + "a wormhole", "a teleporter", "a huge mining drill", "a strange spacecraft", "a space station",\ + "a sleek-looking fighter spacecraft", "a ballistic rifle", "an energy sword", "an inanimate carbon rod" + ) + return nouns + +/obj/item/disk/secret_project/proc/get_secret_project_descriptors() + var/static/list/descriptors = list( + "that is extremely powerful", "which is highly efficient", "which is incredibly compact", "created by aliens", + "that runs off of an exotic form of matter", "that runs off of hydrogen gas", "that just looks really cool" + ) + /obj/item/disk/secret_project/Initialize() . = ..() - var/codename = pick("gamma", "delta", "epsilon", "zeta", "theta", "lambda", "omicron", "sigma", "tau",\ - "upsilon", "omega", "echelon", "prism", "calypso", "bernoulli", "harmony", "nyx", "fresnel") - name = "'[codename]' project data disk" - subject = pick("an experimental design for", "a blueprint to build",\ - "a long set of theoretical formulas detailing the functioning of") - subject += " " + pick("a superluminal artillery cannon", "a supermatter engine", "a fusion engine", "an atmospheric scrubber",\ - "a human cloning pod", "a microwave oven", "a wormhole generator", "a laser carbine", "an energy pistol",\ - "a wormhole", "a teleporter", "a huge mining drill", "a strange spacecraft", "a space station",\ - "a sleek-looking fighter spacecraft", "a ballistic rifle", "an energy sword", "an inanimate carbon rod") - subject += " " + pick("that is extremely powerful", "which is highly efficient", "which is incredibly compact",\ - "that runs off of an exotic form of matter", "that runs off of hydrogen gas", "created by aliens", "that just looks really cool") + name = "'[pick(get_secret_project_codenames())]' project data disk" + subject = "[pick(get_secret_project_types())] [pick(get_secret_project_nouns())] [pick(get_secret_project_descriptors())]" /obj/item/disk/secret_project/examine(mob/user) . = ..() diff --git a/code/game/objects/items/weapons/shields.dm b/code/game/objects/items/weapons/shields.dm deleted file mode 100644 index 8ab9f986e6b8..000000000000 --- a/code/game/objects/items/weapons/shields.dm +++ /dev/null @@ -1,223 +0,0 @@ -//** Shield Helpers -//These are shared by various items that have shield-like behaviour - -//bad_arc is the ABSOLUTE arc of directions from which we cannot block. If you want to fix it to e.g. the user's facing you will need to rotate the dirs yourself. -/proc/check_shield_arc(mob/user, var/bad_arc, atom/damage_source = null, mob/attacker = null) - //check attack direction - var/attack_dir = 0 //direction from the user to the source of the attack - if(istype(damage_source, /obj/item/projectile)) - var/obj/item/projectile/P = damage_source - attack_dir = get_dir(get_turf(user), P.starting) - else if(attacker) - attack_dir = get_dir(get_turf(user), get_turf(attacker)) - else if(damage_source) - attack_dir = get_dir(get_turf(user), get_turf(damage_source)) - - if(!(attack_dir && (attack_dir & bad_arc))) - return 1 - return 0 - -/proc/default_parry_check(mob/user, mob/attacker, atom/damage_source) - //parry only melee attacks - if(istype(damage_source, /obj/item/projectile) || (attacker && get_dist(user, attacker) > 1) || user.incapacitated()) - return 0 - - //block as long as they are not directly behind us - var/bad_arc = user.dir && global.reverse_dir[user.dir] //arc of directions from which we cannot block - if(!check_shield_arc(user, bad_arc, damage_source, attacker)) - return 0 - - return 1 - -/obj/item/shield - name = "abstract shield" - abstract_type = /obj/item/shield - var/base_block_chance = 60 - -/obj/item/shield/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") - if(user.incapacitated()) - return 0 - //block as long as they are not directly behind us - var/bad_arc = user.dir && global.reverse_dir[user.dir] //arc of directions from which we cannot block - if(check_shield_arc(user, bad_arc, damage_source, attacker)) - var/block_chance = get_block_chance(user, damage, damage_source, attacker) - if(attacker) - block_chance = max(0, block_chance - 10 * attacker.get_skill_difference(SKILL_COMBAT, user)) - if(prob(block_chance)) - user.visible_message("\The [user] blocks [attack_text] with \the [src]!") - if(max_health != ITEM_HEALTH_NO_DAMAGE) - take_damage(damage) - return 1 - return 0 - -/obj/item/shield/proc/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null) - return base_block_chance - -/obj/item/shield/riot - name = "riot shield" - desc = "A shield adept at blocking blunt objects from connecting with the torso of the shield wielder." - icon = 'icons/obj/items/shield/riot.dmi' - icon_state = ICON_STATE_WORLD - obj_flags = OBJ_FLAG_CONDUCTIBLE - slot_flags = SLOT_BACK - throw_speed = 1 - throw_range = 4 - w_class = ITEM_SIZE_HUGE - origin_tech = @'{"materials":2}' - material = /decl/material/solid/fiberglass - matter = list(/decl/material/solid/metal/steel = MATTER_AMOUNT_REINFORCEMENT) - attack_verb = list("shoved", "bashed") - var/cooldown = 0 //shield bash cooldown. based on world.time - var/max_block = 15 - var/can_block_lasers = FALSE - -/obj/item/shield/riot/handle_shield(mob/user) - . = ..() - if(.) playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1) - -/obj/item/shield/riot/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null) - if(istype(damage_source, /obj/item/projectile)) - var/obj/item/projectile/P = damage_source - //plastic shields do not stop bullets or lasers, even in space. Will block beanbags, rubber bullets, and stunshots just fine though. - if(is_sharp(P) && damage >= max_block) - return 0 - if(istype(P, /obj/item/projectile/beam) && (!can_block_lasers || (P.armor_penetration >= max_block))) - return 0 - return base_block_chance - -/obj/item/shield/riot/attackby(obj/item/W, mob/user) - if(istype(W, /obj/item/baton)) - if(cooldown < world.time - 25) - user.visible_message("[user] bashes [src] with [W]!") - playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) - cooldown = world.time - return TRUE - else - return ..() - -/obj/item/shield/riot/metal - name = "plasteel combat shield" - icon = 'icons/obj/items/shield/metal.dmi' - icon_state = ICON_STATE_WORLD - obj_flags = OBJ_FLAG_CONDUCTIBLE - slot_flags = SLOT_BACK - throw_range = 3 - w_class = ITEM_SIZE_HUGE - material = /decl/material/solid/metal/plasteel - max_block = 50 - can_block_lasers = TRUE - slowdown_general = 1.5 - _base_attack_force = 6 - -/obj/item/shield/riot/metal/security //A cosmetic difference. - icon = 'icons/obj/items/shield/metal_security.dmi' - -/obj/item/shield/buckler - name = "buckler" - desc = "A wooden buckler used to block sharp things from entering your body back in the day." - icon = 'icons/obj/items/shield/buckler.dmi' - icon_state = "buckler" - slot_flags = SLOT_BACK - base_block_chance = 60 - throw_speed = 10 - throw_range = 20 - w_class = ITEM_SIZE_HUGE - origin_tech = @'{"materials":1}' - material = /decl/material/solid/metal/steel - matter = list(/decl/material/solid/organic/wood/oak = MATTER_AMOUNT_REINFORCEMENT) - attack_verb = list("shoved", "bashed") - _base_attack_force = 8 - max_health = 250 - -/obj/item/shield/buckler/handle_shield(mob/user) - . = ..() - if(.) playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1) - -/obj/item/shield/buckler/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null) - if(istype(damage_source, /obj/item/projectile/bullet)) - return 0 //No blocking bullets, I'm afraid. - return base_block_chance - -/* - * Energy Shield - */ - -/obj/item/shield/energy - name = "energy combat shield" - desc = "A shield capable of stopping most projectile and melee attacks. It can be retracted, expanded, and stored anywhere." - icon = 'icons/obj/items/shield/e_shield.dmi' - icon_state = "eshield0" // eshield1 for expanded - obj_flags = OBJ_FLAG_CONDUCTIBLE - throw_speed = 1 - throw_range = 4 - w_class = ITEM_SIZE_SMALL - origin_tech = @'{"materials":4,"magnets":3,"esoteric":4}' - attack_verb = list("shoved", "bashed") - material = /decl/material/solid/metal/titanium - matter = list( - /decl/material/solid/fiberglass = MATTER_AMOUNT_SECONDARY, - /decl/material/solid/metal/gold = MATTER_AMOUNT_REINFORCEMENT, - /decl/material/solid/silicon = MATTER_AMOUNT_REINFORCEMENT, - /decl/material/solid/gemstone/diamond = MATTER_AMOUNT_TRACE, - ) - _base_attack_force = 3 - var/active = 0 - var/shield_light_color = "#006aff" - -/obj/item/shield/energy/Initialize() - set_extension(src, /datum/extension/base_icon_state, copytext(initial(icon_state), 1, length(initial(icon_state)))) - . = ..() - update_icon() - -/obj/item/shield/energy/handle_shield(mob/user) - if(!active) - return 0 //turn it on first! - . = ..() - - if(.) - spark_at(user.loc, amount=5) - playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1) - -/obj/item/shield/energy/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null) - if(istype(damage_source, /obj/item/projectile)) - var/obj/item/projectile/P = damage_source - if((is_sharp(P) && damage > 10) || istype(P, /obj/item/projectile/beam)) - return (base_block_chance - round(damage / 2.5)) //block bullets and beams using the old block chance - return base_block_chance - -/obj/item/shield/energy/attack_self(mob/user) - if(user.has_genetic_condition(GENE_COND_CLUMSY) && prob(50)) - to_chat(user, SPAN_DANGER("You beat yourself in the head with [src].")) - if(isliving(user)) - var/mob/living/M = user - M.take_organ_damage(5, 0) - active = !active - if (active) - set_base_attack_force(10) - update_icon() - w_class = ITEM_SIZE_HUGE - playsound(user, 'sound/weapons/saberon.ogg', 50, 1) - to_chat(user, SPAN_NOTICE("\The [src] is now active.")) - - else - set_base_attack_force(3) - update_icon() - w_class = ITEM_SIZE_SMALL - playsound(user, 'sound/weapons/saberoff.ogg', 50, 1) - to_chat(user, SPAN_NOTICE("\The [src] can now be concealed.")) - - if(ishuman(user)) - var/mob/living/human/H = user - H.update_inhand_overlays() - - add_fingerprint(user) - return - -/obj/item/shield/energy/on_update_icon() - . = ..() - var/datum/extension/base_icon_state/base_name = get_extension(src, /datum/extension/base_icon_state) - icon_state = "[base_name.base_icon_state][active]" //Replace 0 with current state - if(active) - set_light(1.5, 1.5, shield_light_color) - else - set_light(0) \ No newline at end of file diff --git a/code/game/objects/items/weapons/shields/_shield.dm b/code/game/objects/items/weapons/shields/_shield.dm new file mode 100644 index 000000000000..6da8605ec6bc --- /dev/null +++ b/code/game/objects/items/weapons/shields/_shield.dm @@ -0,0 +1,54 @@ +//** Shield Helpers +//These are shared by various items that have shield-like behaviour + +//bad_arc is the ABSOLUTE arc of directions from which we cannot block. If you want to fix it to e.g. the user's facing you will need to rotate the dirs yourself. +/proc/check_shield_arc(mob/user, var/bad_arc, atom/damage_source = null, mob/attacker = null) + //check attack direction + var/attack_dir = 0 //direction from the user to the source of the attack + if(istype(damage_source, /obj/item/projectile)) + var/obj/item/projectile/P = damage_source + attack_dir = get_dir(get_turf(user), P.starting) + else if(attacker) + attack_dir = get_dir(get_turf(user), get_turf(attacker)) + else if(damage_source) + attack_dir = get_dir(get_turf(user), get_turf(damage_source)) + + if(!(attack_dir && (attack_dir & bad_arc))) + return 1 + return 0 + +/proc/default_parry_check(mob/user, mob/attacker, atom/damage_source) + //parry only melee attacks + if(istype(damage_source, /obj/item/projectile) || (attacker && get_dist(user, attacker) > 1) || user.incapacitated()) + return 0 + + //block as long as they are not directly behind us + var/bad_arc = user.dir && global.reverse_dir[user.dir] //arc of directions from which we cannot block + if(!check_shield_arc(user, bad_arc, damage_source, attacker)) + return 0 + + return 1 + +/obj/item/shield + name = "abstract shield" + abstract_type = /obj/item/shield + var/base_block_chance = 60 + +/obj/item/shield/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack") + if(user.incapacitated()) + return 0 + //block as long as they are not directly behind us + var/bad_arc = user.dir && global.reverse_dir[user.dir] //arc of directions from which we cannot block + if(check_shield_arc(user, bad_arc, damage_source, attacker)) + var/block_chance = get_block_chance(user, damage, damage_source, attacker) + if(attacker) + block_chance = max(0, block_chance - 10 * attacker.get_skill_difference(SKILL_COMBAT, user)) + if(prob(block_chance)) + user.visible_message("\The [user] blocks [attack_text] with \the [src]!") + if(max_health != ITEM_HEALTH_NO_DAMAGE) + take_damage(damage) + return 1 + return 0 + +/obj/item/shield/proc/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null) + return base_block_chance diff --git a/code/game/objects/items/weapons/shields/shield_crafted.dm b/code/game/objects/items/weapons/shields/shield_crafted.dm new file mode 100644 index 000000000000..5d892688b0ad --- /dev/null +++ b/code/game/objects/items/weapons/shields/shield_crafted.dm @@ -0,0 +1,38 @@ +/obj/item/shield/crafted + slot_flags = SLOT_BACK + base_block_chance = 60 + throw_speed = 10 + throw_range = 20 + w_class = ITEM_SIZE_HUGE + origin_tech = @'{"materials":1}' + abstract_type = /obj/item/shield/crafted + icon_state = ICON_STATE_WORLD + attack_verb = list("shoved", "bashed") + _base_attack_force = 8 + max_health = 250 + material = /decl/material/solid/organic/wood/oak + material_alteration = MAT_FLAG_ALTERATION_ALL + var/wooden_icon + var/decl/material/reinforcement_material = /decl/material/solid/metal/iron + +/obj/item/shield/crafted/set_material(new_material) + . = ..() + if(wooden_icon) + if(istype(material, /decl/material/solid/organic/wood)) + set_icon(wooden_icon) + else + set_icon(initial(icon)) + update_icon() + +/obj/item/shield/crafted/Initialize(ml, material_key, reinf_material_key) + if(reinf_material_key) + reinforcement_material = reinf_material_key + if(ispath(reinforcement_material)) + reinforcement_material = GET_DECL(reinforcement_material) + LAZYSET(matter, reinforcement_material.type, MATTER_AMOUNT_REINFORCEMENT) + . = ..() + +/obj/item/shield/crafted/on_update_icon() + . = ..() + if(istype(reinforcement_material)) + add_overlay(overlay_image(icon, "[icon_state]-reinforcement", reinforcement_material.color, RESET_COLOR)) diff --git a/code/game/objects/items/weapons/shields/shield_crafted_buckler.dm b/code/game/objects/items/weapons/shields/shield_crafted_buckler.dm new file mode 100644 index 000000000000..6d78daef790f --- /dev/null +++ b/code/game/objects/items/weapons/shields/shield_crafted_buckler.dm @@ -0,0 +1,17 @@ +/obj/item/shield/crafted/buckler + name = "buckler" + desc = "A small, round shield used to block sharp things from entering your body." + icon = 'icons/obj/items/shield/buckler_metal.dmi' + wooden_icon = 'icons/obj/items/shield/buckler_wood.dmi' + +/obj/item/shield/crafted/buckler/improvised + name_prefix = "improvised" + +/obj/item/shield/crafted/buckler/handle_shield(mob/user) + . = ..() + if(.) playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1) + +/obj/item/shield/crafted/buckler/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null) + if(istype(damage_source, /obj/item/projectile/bullet)) + return 0 //No blocking bullets, I'm afraid. + return base_block_chance diff --git a/code/game/objects/items/weapons/shields/shield_crafting.dm b/code/game/objects/items/weapons/shields/shield_crafting.dm new file mode 100644 index 000000000000..307db9bce88b --- /dev/null +++ b/code/game/objects/items/weapons/shields/shield_crafting.dm @@ -0,0 +1,52 @@ +// General item for 'proper' shield crafting. +/obj/item/shield_fasteners + name = "shield fasteners" + desc = "A handful of shaped fasteners used to hold a buckler or shield together." + icon_state = ICON_STATE_WORLD + icon = 'icons/obj/items/shield_fasteners.dmi' + material = /decl/material/solid/metal/iron + material_alteration = MAT_FLAG_ALTERATION_ALL + +// TODO: single-step slapcrafting +/obj/item/shield_base + w_class = ITEM_SIZE_LARGE + desc = "An unfinished collection of shield bits, waiting for fastenings." + icon_state = ICON_STATE_WORLD + abstract_type = /obj/item/shield_base + material = /decl/material/solid/organic/wood/oak + material_alteration = MAT_FLAG_ALTERATION_ALL + var/wooden_icon + var/fittings_type = /obj/item/shield_fasteners + var/finished_type + var/work_skill = SKILL_CONSTRUCTION + +/obj/item/shield_base/attackby(obj/item/used_item, mob/user) + if(fittings_type && istype(used_item, fittings_type) && finished_type && user.try_unequip(used_item)) + to_chat(user, SPAN_NOTICE("You start laying out \the [src] and affixing \the [used_item].")) + if(user.do_skilled(5 SECONDS, work_skill, src, check_holding = TRUE)) + var/was_held = (loc == user) + var/obj/item/shield/crafted/shield = new finished_type(get_turf(src), material?.type, used_item.material?.type) + user.visible_message("\The [user] secures \the [src] with \the [used_item], finishing \a [shield].") + qdel(src) + qdel(used_item) + if(was_held) + user.put_in_hands(shield) + return TRUE + return ..() + +/obj/item/shield_base/set_material(new_material) + . = ..() + if(wooden_icon) + if(istype(material, /decl/material/solid/organic/wood)) + set_icon(wooden_icon) + else + set_icon(initial(icon)) + update_icon() + +// Subtypes below. +/obj/item/shield_base/buckler + name_prefix = "unfinished" + name = "buckler" + icon = 'icons/obj/items/shield/buckler_base_metal.dmi' + wooden_icon = 'icons/obj/items/shield/buckler_base_wood.dmi' + finished_type = /obj/item/shield/crafted/buckler diff --git a/code/game/objects/items/weapons/shields/shield_energy.dm b/code/game/objects/items/weapons/shields/shield_energy.dm new file mode 100644 index 000000000000..4b028ca79316 --- /dev/null +++ b/code/game/objects/items/weapons/shields/shield_energy.dm @@ -0,0 +1,83 @@ +/* + * Energy Shield + */ + +/obj/item/shield/energy + name = "energy combat shield" + desc = "A shield capable of stopping most projectile and melee attacks. It can be retracted, expanded, and stored anywhere." + icon = 'icons/obj/items/shield/e_shield.dmi' + icon_state = "eshield0" // eshield1 for expanded + obj_flags = OBJ_FLAG_CONDUCTIBLE + throw_speed = 1 + throw_range = 4 + w_class = ITEM_SIZE_SMALL + origin_tech = @'{"materials":4,"magnets":3,"esoteric":4}' + attack_verb = list("shoved", "bashed") + material = /decl/material/solid/metal/titanium + matter = list( + /decl/material/solid/fiberglass = MATTER_AMOUNT_SECONDARY, + /decl/material/solid/metal/gold = MATTER_AMOUNT_REINFORCEMENT, + /decl/material/solid/silicon = MATTER_AMOUNT_REINFORCEMENT, + /decl/material/solid/gemstone/diamond = MATTER_AMOUNT_TRACE, + ) + _base_attack_force = 3 + var/active = 0 + var/shield_light_color = "#006aff" + +/obj/item/shield/energy/Initialize() + set_extension(src, /datum/extension/base_icon_state, copytext(initial(icon_state), 1, length(initial(icon_state)))) + . = ..() + update_icon() + +/obj/item/shield/energy/handle_shield(mob/user) + if(!active) + return 0 //turn it on first! + . = ..() + + if(.) + spark_at(user.loc, amount=5) + playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1) + +/obj/item/shield/energy/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null) + if(istype(damage_source, /obj/item/projectile)) + var/obj/item/projectile/P = damage_source + if((is_sharp(P) && damage > 10) || istype(P, /obj/item/projectile/beam)) + return (base_block_chance - round(damage / 2.5)) //block bullets and beams using the old block chance + return base_block_chance + +/obj/item/shield/energy/attack_self(mob/user) + if(user.has_genetic_condition(GENE_COND_CLUMSY) && prob(50)) + to_chat(user, SPAN_DANGER("You beat yourself in the head with [src].")) + if(isliving(user)) + var/mob/living/M = user + M.take_organ_damage(5, 0) + active = !active + if (active) + set_base_attack_force(10) + update_icon() + w_class = ITEM_SIZE_HUGE + playsound(user, 'sound/weapons/saberon.ogg', 50, 1) + to_chat(user, SPAN_NOTICE("\The [src] is now active.")) + + else + set_base_attack_force(3) + update_icon() + w_class = ITEM_SIZE_SMALL + playsound(user, 'sound/weapons/saberoff.ogg', 50, 1) + to_chat(user, SPAN_NOTICE("\The [src] can now be concealed.")) + + if(ishuman(user)) + var/mob/living/human/H = user + H.update_inhand_overlays() + + add_fingerprint(user) + return + +/obj/item/shield/energy/on_update_icon() + . = ..() + var/datum/extension/base_icon_state/base_name = get_extension(src, /datum/extension/base_icon_state) + icon_state = "[base_name.base_icon_state][active]" //Replace 0 with current state + if(active) + set_light(1.5, 1.5, shield_light_color) + else + set_light(0) diff --git a/code/game/objects/items/weapons/shields/shield_riot.dm b/code/game/objects/items/weapons/shields/shield_riot.dm new file mode 100644 index 000000000000..378ae85d9f0e --- /dev/null +++ b/code/game/objects/items/weapons/shields/shield_riot.dm @@ -0,0 +1,58 @@ +/obj/item/shield/riot + name = "riot shield" + desc = "A shield adept at blocking blunt objects from connecting with the torso of the shield wielder." + icon = 'icons/obj/items/shield/riot.dmi' + icon_state = ICON_STATE_WORLD + obj_flags = OBJ_FLAG_CONDUCTIBLE + slot_flags = SLOT_BACK + throw_speed = 1 + throw_range = 4 + w_class = ITEM_SIZE_HUGE + origin_tech = @'{"materials":2}' + material = /decl/material/solid/fiberglass + matter = list(/decl/material/solid/metal/steel = MATTER_AMOUNT_REINFORCEMENT) + attack_verb = list("shoved", "bashed") + var/cooldown = 0 //shield bash cooldown. based on world.time + var/max_block = 15 + var/can_block_lasers = FALSE + +/obj/item/shield/riot/handle_shield(mob/user) + . = ..() + if(.) playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1) + +/obj/item/shield/riot/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null) + if(istype(damage_source, /obj/item/projectile)) + var/obj/item/projectile/P = damage_source + //plastic shields do not stop bullets or lasers, even in space. Will block beanbags, rubber bullets, and stunshots just fine though. + if(is_sharp(P) && damage >= max_block) + return 0 + if(istype(P, /obj/item/projectile/beam) && (!can_block_lasers || (P.armor_penetration >= max_block))) + return 0 + return base_block_chance + +/obj/item/shield/riot/attackby(obj/item/W, mob/user) + if(istype(W, /obj/item/baton)) + if(cooldown < world.time - 25) + user.visible_message("[user] bashes [src] with [W]!") + playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1) + cooldown = world.time + return TRUE + else + return ..() + +/obj/item/shield/riot/metal + name = "plasteel combat shield" + icon = 'icons/obj/items/shield/metal.dmi' + icon_state = ICON_STATE_WORLD + obj_flags = OBJ_FLAG_CONDUCTIBLE + slot_flags = SLOT_BACK + throw_range = 3 + w_class = ITEM_SIZE_HUGE + material = /decl/material/solid/metal/plasteel + max_block = 50 + can_block_lasers = TRUE + slowdown_general = 1.5 + _base_attack_force = 6 + +/obj/item/shield/riot/metal/security //A cosmetic difference. + icon = 'icons/obj/items/shield/metal_security.dmi' diff --git a/code/game/objects/items/weapons/soap.dm b/code/game/objects/items/weapons/soap.dm index 7667753288a4..99614d0fe16e 100644 --- a/code/game/objects/items/weapons/soap.dm +++ b/code/game/objects/items/weapons/soap.dm @@ -57,45 +57,42 @@ add_to_reagents(/decl/material/liquid/cleaner/soap, SOAP_CLEANER_ON_WET) /obj/item/soap/Crossed(atom/movable/AM) - if(!isliving(AM)) - return - var/mob/living/M = AM - M.slip("\the [src]", 3) + var/mob/living/victim = AM + if(istype(victim)) + victim.slip("\the [src]", 3) + return ..() /obj/item/soap/afterattack(atom/target, mob/user, proximity) - if(!proximity) return - //I couldn't feasibly fix the overlay bugs caused by cleaning items we are wearing. - //So this is a workaround. This also makes more sense from an IC standpoint. ~Carn - var/cleaned = FALSE - if(user.client && (target in user.client.screen)) - to_chat(user, SPAN_NOTICE("You need to take \the [target] off before cleaning it.")) - else if(istype(target,/obj/effect/decal/cleanable/blood)) - to_chat(user, SPAN_NOTICE("You scrub \the [target] out.")) - target.clean() //Blood is a cleanable decal, therefore needs to be accounted for before all cleanable decals. - cleaned = TRUE - else if(istype(target,/obj/effect/decal/cleanable)) - to_chat(user, SPAN_NOTICE("You scrub \the [target] out.")) - qdel(target) - cleaned = TRUE - else if(isturf(target) || istype(target, /obj/structure/catwalk)) - var/turf/T = get_turf(target) - if(!T) - return - user.visible_message(SPAN_NOTICE("\The [user] starts scrubbing \the [T].")) - if(do_after(user, 8 SECONDS, T) && reagents?.total_volume) - reagents.splash(T, FLUID_QDEL_POINT) - to_chat(user, SPAN_NOTICE("You scrub \the [target] clean.")) - cleaned = TRUE - else if(istype(target,/obj/structure/hygiene/sink)) + + if(!proximity) + return ..() + + if(istype(target,/obj/structure/hygiene/sink)) to_chat(user, SPAN_NOTICE("You wet \the [src] in the sink.")) wet() + return TRUE + + if(reagents?.total_volume < 1) + to_chat(user, SPAN_WARNING("\The [src] is too dry to clean \the [target].")) + return TRUE + + if(isturf(target) || istype(target, /obj/structure/catwalk)) + target = get_turf(target) + if(!isturf(target)) + return ..() + user.visible_message(SPAN_NOTICE("\The [user] starts scrubbing \the [target].")) + if(!do_after(user, 8 SECONDS, target) && reagents?.total_volume) + return TRUE + to_chat(user, SPAN_NOTICE("You scrub \the [target] clean.")) + else if(istype(target,/obj/effect/decal/cleanable)) + to_chat(user, SPAN_NOTICE("You scrub \the [target] out.")) else to_chat(user, SPAN_NOTICE("You clean \the [target].")) - target.clean() //Clean bloodied atoms. Blood decals themselves need to be handled above. - cleaned = TRUE - if(cleaned) - user.update_personal_goal(/datum/goal/clean, 1) + reagents.touch_atom(target) + reagents.remove_any(1) + user.update_personal_goal(/datum/goal/clean, 1) + return TRUE //attack_as_weapon /obj/item/soap/use_on_mob(mob/living/target, mob/living/user, animate = TRUE) diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 499ffb5d8589..639d83a17547 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -275,13 +275,6 @@ /obj/item/box/anti_photons/WillContain() return list(/obj/item/grenade/anti_photon = 5) -/obj/item/box/supermatters - name = "box of supermatter grenades" - desc = "A box containing 5 highly experimental supermatter grenades." - icon_state = "radbox" -/obj/item/box/supermatters/WillContain() - return list(/obj/item/grenade/supermatter = 5) - /obj/item/box/decompilers name = "box of decompiler grenades" desc = "A box containing 5 experimental decompiler grenades." diff --git a/code/game/objects/items/weapons/storage/specialized.dm b/code/game/objects/items/weapons/storage/specialized.dm index d85bd453f5c8..014814223111 100644 --- a/code/game/objects/items/weapons/storage/specialized.dm +++ b/code/game/objects/items/weapons/storage/specialized.dm @@ -12,8 +12,8 @@ /obj/item/ore name = "mining satchel" desc = "This sturdy bag can be used to store and transport ores." - icon = 'icons/obj/mining.dmi' - icon_state = "satchel" + icon = 'icons/obj/items/mining_satchel.dmi' + icon_state = ICON_STATE_WORLD slot_flags = SLOT_LOWER_BODY w_class = ITEM_SIZE_LARGE storage = /datum/storage/ore @@ -57,8 +57,8 @@ /obj/item/sheetsnatcher name = "sheet snatcher" - icon = 'icons/obj/mining.dmi' - icon_state = "sheetsnatcher" + icon = 'icons/obj/items/sheet_snatcher.dmi' + icon_state = ICON_STATE_WORLD desc = "A patented storage system designed for any kind of mineral sheet." material = /decl/material/solid/organic/plastic storage = /datum/storage/sheets diff --git a/code/game/objects/items/weapons/storage/wallets.dm b/code/game/objects/items/weapons/storage/wallets.dm index faf51ae0c59e..5fcafd398aef 100644 --- a/code/game/objects/items/weapons/storage/wallets.dm +++ b/code/game/objects/items/weapons/storage/wallets.dm @@ -89,6 +89,7 @@ /decl/interaction_handler/remove_id/wallet expected_target_type = /obj/item/wallet + examine_desc = "remove an ID card" /decl/interaction_handler/remove_id/wallet/is_possible(atom/target, mob/user, obj/item/prop) . = ..() && ishuman(user) diff --git a/code/game/objects/items/weapons/traps.dm b/code/game/objects/items/weapons/traps.dm index 07845b81c45a..397257e0d29f 100644 --- a/code/game/objects/items/weapons/traps.dm +++ b/code/game/objects/items/weapons/traps.dm @@ -1,17 +1,17 @@ /obj/item/beartrap - name = "mechanical trap" - throw_speed = 2 - throw_range = 1 - gender = PLURAL - icon = 'icons/obj/items/beartrap.dmi' - icon_state = "beartrap0" - randpixel = 0 - desc = "A mechanically activated leg trap. Low-tech, but reliable. Looks like it could really hurt if you set it off." - w_class = ITEM_SIZE_NORMAL - origin_tech = @'{"materials":1}' - material = /decl/material/solid/metal/steel - can_buckle = 0 //disallow manual un/buckling - var/deployed = 0 + name = "mechanical trap" + desc = "A mechanically activated leg trap. Low-tech, but reliable. Looks like it could really hurt if you set it off." + throw_speed = 2 + throw_range = 1 + gender = PLURAL + icon = 'icons/obj/items/beartrap.dmi' + icon_state = "beartrap0" + randpixel = 0 + w_class = ITEM_SIZE_NORMAL + origin_tech = @'{"materials":1}' + material = /decl/material/solid/metal/steel + can_buckle = FALSE //disallow manual un/buckling + var/deployed = FALSE /obj/item/beartrap/proc/can_use(mob/user) . = (user.check_dexterity(DEXTERITY_SIMPLE_MACHINES) && !issilicon(user) && !user.stat && !user.restrained()) @@ -19,12 +19,12 @@ /obj/item/beartrap/user_unbuckle_mob(mob/user) if(buckled_mob && can_use(user)) user.visible_message( - "\The [user] begins freeing \the [buckled_mob] from \the [src].", - "You carefully begin to free \the [buckled_mob] from \the [src].", - "You hear metal creaking." + SPAN_NOTICE("\The [user] begins freeing \the [buckled_mob] from \the [src]."), + SPAN_NOTICE("You carefully begin to free \the [buckled_mob] from \the [src]."), + SPAN_NOTICE("You hear metal creaking.") ) if(do_after(user, 60, src)) - user.visible_message("\The [buckled_mob] has been freed from \the [src] by \the [user].") + user.visible_message(SPAN_NOTICE("\The [buckled_mob] has been freed from \the [src] by \the [user].")) unbuckle_mob() anchored = FALSE @@ -32,19 +32,18 @@ ..() if(!deployed && can_use(user)) user.visible_message( - "[user] starts to deploy \the [src].", - "You begin deploying \the [src]!", + SPAN_DANGER("\The [user] starts to deploy \the [src]."), + SPAN_DANGER("You begin deploying \the [src]!"), "You hear the slow creaking of a spring." - ) + ) - if (do_after(user, 60, src) && user.try_unequip(src)) + if (do_after(user, 6 SECONDS, src) && user.try_unequip(src)) user.visible_message( - "\The [user] has deployed \the [src].", - "You have deployed \the [src]!", + SPAN_DANGER("\The [user] has deployed \the [src]."), + SPAN_DANGER("You have deployed \the [src]!"), "You hear a latch click loudly." - ) - - deployed = 1 + ) + deployed = TRUE update_icon() anchored = TRUE @@ -55,7 +54,7 @@ user_unbuckle_mob(user) return TRUE if(!deployed || !can_use(user)) - return FALSE + return ..() user.visible_message( SPAN_DANGER("\The [user] starts to disarm \the [src]."), SPAN_NOTICE("You begin disarming \the [src]!"), @@ -71,40 +70,45 @@ update_icon() return TRUE -/obj/item/beartrap/proc/attack_mob(mob/L) +/obj/item/beartrap/proc/attack_mob(mob/victim) + + if(victim.immune_to_floor_hazards()) + return FALSE var/target_zone - if(L.current_posture.prone) + if(victim.current_posture.prone) target_zone = ran_zone() else target_zone = pick(BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG) - if(!L.apply_damage(30, BRUTE, target_zone, used_weapon=src)) - return 0 + if(!victim.apply_damage(30, BRUTE, target_zone, used_weapon=src)) + return FALSE //trap the victim in place - set_dir(L.dir) - buckle_mob(L) - to_chat(L, "The steel jaws of \the [src] bite into you, trapping you in place!") - deployed = 0 + set_dir(victim.dir) + buckle_mob(victim) + to_chat(victim, SPAN_DANGER("The steel jaws of \the [src] bite into you, trapping you in place!")) + deployed = FALSE + return TRUE /obj/item/beartrap/Crossed(atom/movable/AM) ..() if(!deployed || !isliving(AM)) return - var/mob/living/L = AM - if(MOVING_DELIBERATELY(L)) + var/mob/living/victim = AM + if(MOVING_DELIBERATELY(victim) || victim.immune_to_floor_hazards()) return - L.visible_message( - SPAN_DANGER("\The [L] steps on \the [src]."), + victim.visible_message( + SPAN_DANGER("\The [victim] steps on \the [src]."), SPAN_DANGER("You step on \the [src]!"), - "You hear a loud metallic snap!") - attack_mob(L) + "You hear a loud metallic snap!" + ) + attack_mob(victim) if(!buckled_mob) anchored = FALSE - deployed = 0 + deployed = FALSE update_icon() /obj/item/beartrap/on_update_icon() . = ..() - icon_state = "beartrap[deployed == TRUE]" + icon_state = "beartrap[deployed]" diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index 1945ad562018..243fe2bd7e88 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -34,8 +34,7 @@ return ..() /obj/item/nullrod/proc/holy_act(mob/living/target, mob/living/user) - if(target.mind && LAZYLEN(target.mind.learned_spells)) - target.silence_spells(30 SECONDS) + if(target.disable_abilities(30 SECONDS)) to_chat(target, SPAN_DANGER("You've been silenced!")) return TRUE return FALSE diff --git a/code/game/objects/random/subtypes/misc.dm b/code/game/objects/random/subtypes/misc.dm index 4ccde91270d2..a17d209574a3 100644 --- a/code/game/objects/random/subtypes/misc.dm +++ b/code/game/objects/random/subtypes/misc.dm @@ -14,7 +14,7 @@ /obj/item/pill_bottle/happy = 2, /obj/item/pill_bottle/zoom = 2, /obj/item/chems/glass/beaker/vial/random/toxin = 1, - /obj/item/chems/glass/beaker/sulphuric = 1, + /obj/item/chems/glass/beaker/sulfuric = 1, /obj/item/poster = 5, /obj/item/butterflyblade = 3, /obj/item/butterflyhandle = 3, diff --git a/code/game/objects/structures/_structure_construction.dm b/code/game/objects/structures/_structure_construction.dm index a069498e7d86..86a88084bd35 100644 --- a/code/game/objects/structures/_structure_construction.dm +++ b/code/game/objects/structures/_structure_construction.dm @@ -2,120 +2,29 @@ var/wired var/tool_interaction_flags -/obj/structure/proc/handle_default_hammer_attackby(var/mob/user, var/obj/item/hammer) - - // Resolve ambiguous interactions. - var/can_deconstruct = (tool_interaction_flags & TOOL_INTERACTION_DECONSTRUCT) && can_dismantle(user) - var/can_unanchor = (tool_interaction_flags & TOOL_INTERACTION_ANCHOR) && can_unanchor(user) - if(can_deconstruct && can_unanchor) - var/choice = alert(user, "Do you wish to [anchored ? "unanchor" : "anchor"] or dismantle this structure?", "Tool Choice", (anchored ? "Unanchor" : "Anchor"), "Deconstruct", "Cancel") - if(!choice || choice == "Cancel" || QDELETED(src) || QDELETED(user) || QDELETED(hammer) || !CanPhysicallyInteract(user) || user.get_active_held_item() != hammer) - return TRUE - if(choice == "Deconstruct") - can_unanchor = FALSE - else - can_deconstruct = FALSE - - if(can_unanchor) - playsound(src.loc, 'sound/items/Deconstruct.ogg', 100, 1) - visible_message(SPAN_NOTICE("\The [user] begins [anchored ? "unanchoring [src]" : "anchoring [src] in place"] with \the [hammer].")) - if(!do_after(user, 4 SECONDS, src) || QDELETED(src)) - return TRUE - playsound(src.loc, 'sound/items/Deconstruct.ogg', 100, 1) - anchored = !anchored - visible_message(SPAN_NOTICE("\The [user] has [anchored ? "anchored" : "unanchored"] \the [src] with \the [hammer].")) - update_icon() - return TRUE - - if(can_deconstruct) - playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) - visible_message(SPAN_NOTICE("\The [user] starts knocking apart \the [src] with \the [hammer].")) - if(!do_after(user, 5 SECONDS, src) || QDELETED(src)) - return TRUE - playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) - visible_message(SPAN_NOTICE("\The [user] completely dismantles \the [src] with \the [hammer].")) - dismantle_structure(user) - return TRUE - - return FALSE - /obj/structure/proc/handle_default_wrench_attackby(var/mob/user, var/obj/item/wrench) if((tool_interaction_flags & TOOL_INTERACTION_ANCHOR) && can_unanchor(user)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - visible_message(SPAN_NOTICE("\The [user] begins [anchored ? "unsecuring [src]" : "securing [src] in place"] with \the [wrench].")) - if(!do_after(user, 4 SECONDS, src) || QDELETED(src)) - return TRUE - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - anchored = !anchored - visible_message(SPAN_NOTICE("\The [user] has [anchored ? "secured" : "unsecured"] \the [src] with \the [wrench].")) - update_icon() - return TRUE + return tool_toggle_anchors(user, wrench) return FALSE /obj/structure/proc/handle_default_welder_attackby(var/mob/user, var/obj/item/weldingtool/welder) if((tool_interaction_flags & TOOL_INTERACTION_DECONSTRUCT) && can_dismantle(user)) - if(material && !material.removed_by_welder) - to_chat(user, SPAN_WARNING("\The [src] is too delicate to be dismantled with \the [welder]; try a crowbar.")) - return TRUE - if(!welder.isOn()) - to_chat(user, SPAN_WARNING("Try lighting \the [welder] first.")) - return TRUE - if(welder.get_fuel() < 5) - to_chat(user, SPAN_WARNING("You need more fuel to complete this task.")) - return TRUE - playsound(loc, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) - visible_message(SPAN_NOTICE("\The [user] starts slicing apart \the [src] with \the [welder].")) - if(!do_after(user, 3 SECONDS, src) || QDELETED(src) || !welder.weld(5, user)) - return TRUE - playsound(loc, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) - visible_message(SPAN_NOTICE("\The [user] completely dismantles \the [src] with \the [welder].")) - dismantle_structure(user) - return TRUE + return welder_dismantle(user, welder) return FALSE /obj/structure/proc/handle_default_crowbar_attackby(var/mob/user, var/obj/item/crowbar) if((tool_interaction_flags & TOOL_INTERACTION_DECONSTRUCT) && can_dismantle(user)) - if(material && material.removed_by_welder) - to_chat(user, SPAN_WARNING("\The [src] is too robust to be dismantled with \the [crowbar]; try a welding tool.")) - return TRUE - playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) - visible_message(SPAN_NOTICE("\The [user] starts levering apart \the [src] with \the [crowbar].")) - if(!do_after(user, 5 SECONDS, src) || QDELETED(src)) - return TRUE - playsound(loc, 'sound/items/Crowbar.ogg', 50, 1) - visible_message(SPAN_NOTICE("\The [user] completely dismantles \the [src] with \the [crowbar].")) - dismantle_structure(user) - return TRUE + return tool_dismantle(user, crowbar) return FALSE /obj/structure/proc/handle_default_cable_attackby(var/mob/user, var/obj/item/stack/cable_coil/coil) if((tool_interaction_flags & TOOL_INTERACTION_WIRING) && anchored) - if(wired) - to_chat(user, SPAN_WARNING("\The [src] has already been wired.")) - return TRUE - var/obj/item/stack/cable_coil/cable = coil - if(cable.get_amount() < 1) - to_chat(user, SPAN_WARNING("You need one length of coil to wire \the [src].")) - else - visible_message(SPAN_NOTICE("\The [user] starts to wire \the [src].")) - if(do_after(user, 4 SECONDS, src) && !wired && anchored && !QDELETED(src) && cable.use(1)) - wired = TRUE - visible_message(SPAN_NOTICE("\The [user] finishes wiring \the [src].")) - return TRUE + return install_wiring(user, coil) return FALSE -/obj/structure/proc/handle_default_wirecutter_attackby(var/mob/user, var/obj/item/wirecutters/wirecutters) +/obj/structure/proc/handle_default_wirecutter_attackby(var/mob/user, var/obj/item/wirecutters) if((tool_interaction_flags & TOOL_INTERACTION_WIRING) && anchored) - if(!wired) - to_chat(user, SPAN_WARNING("\The [src] has not been wired.")) - return TRUE - playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) - visible_message(SPAN_NOTICE("\The [user] begins stripping the wiring out of \the [src].")) - if(do_after(user, 4 SECONDS, src) && !QDELETED(src) && wired) - visible_message(SPAN_NOTICE("\The [user] finishes stripping the wiring from \the [src].")) - new/obj/item/stack/cable_coil(src.loc, 1) - wired = FALSE - return TRUE + return strip_wiring(user, wirecutters) return FALSE /obj/structure/proc/handle_default_screwdriver_attackby(var/mob/user, var/obj/item/screwdriver) @@ -151,35 +60,41 @@ current_health = clamp(current_health + used*DOOR_REPAIR_AMOUNT, current_health, current_max_health) /obj/structure/attackby(obj/item/used_item, mob/user) + if(used_item.user_can_attack_with(user, silent = TRUE)) var/force = used_item.get_attack_force(user) if(force && user.check_intent(I_FLAG_HARM)) attack_animation(user) visible_message(SPAN_DANGER("\The [src] has been [pick(used_item.attack_verb)] with \the [used_item] by \the [user]!")) take_damage(force, used_item.atom_damage_type) - . = TRUE - - else if(IS_HAMMER(used_item)) - . = handle_default_hammer_attackby(user, used_item) - else if(IS_WRENCH(used_item)) - . = handle_default_wrench_attackby(user, used_item) - else if(IS_SCREWDRIVER(used_item)) - . = handle_default_screwdriver_attackby(user, used_item) - else if(IS_WELDER(used_item)) - . = handle_default_welder_attackby(user, used_item) - else if(IS_CROWBAR(used_item)) - . = handle_default_crowbar_attackby(user, used_item) - else if(IS_COIL(used_item)) - . = handle_default_cable_attackby(user, used_item) - else if(IS_WIRECUTTER(used_item)) - . = handle_default_wirecutter_attackby(user, used_item) - else if(can_repair_with(used_item) && can_repair(user)) - . = handle_repair(user, used_item) - if(.) user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) add_fingerprint(user) - return . - return ..() + return TRUE + + // This handles standard tool interactions (anchoring, dismantling), calls below are for legacy purposes. + . = ..() + if(.) + return + + if(IS_HAMMER(used_item)) + . = handle_default_hammer_attackby(user, used_item) + else if(IS_WRENCH(used_item)) + . = handle_default_wrench_attackby(user, used_item) + else if(IS_SCREWDRIVER(used_item)) + . = handle_default_screwdriver_attackby(user, used_item) + else if(IS_WELDER(used_item)) + . = handle_default_welder_attackby(user, used_item) + else if(IS_CROWBAR(used_item)) + . = handle_default_crowbar_attackby(user, used_item) + else if(IS_COIL(used_item)) + . = handle_default_cable_attackby(user, used_item) + else if(IS_WIRECUTTER(used_item)) + . = handle_default_wirecutter_attackby(user, used_item) + else if(can_repair_with(used_item) && can_repair(user)) + . = handle_repair(user, used_item) + if(.) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + add_fingerprint(user) /obj/structure/attack_generic(var/mob/user, var/damage, var/attack_verb, var/environment_smash) if(environment_smash >= 1) @@ -195,4 +110,96 @@ take_damage(damage) else visible_message(SPAN_NOTICE("\The [user] bonks \the [src] harmlessly.")) - return TRUE \ No newline at end of file + return TRUE + +/obj/structure/proc/strip_wiring(mob/user, obj/item/wirecutters) + if(!wired) + to_chat(user, SPAN_WARNING("\The [src] has not been wired.")) + return TRUE + playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) + visible_message(SPAN_NOTICE("\The [user] begins stripping the wiring out of \the [src].")) + if(do_after(user, 4 SECONDS, src) && !QDELETED(src) && wired) + visible_message(SPAN_NOTICE("\The [user] finishes stripping the wiring from \the [src].")) + new/obj/item/stack/cable_coil(src.loc, 1) + wired = FALSE + return TRUE + +/obj/structure/proc/install_wiring(mob/user, obj/item/stack/cable_coil/coil) + if(wired) + to_chat(user, SPAN_WARNING("\The [src] has already been wired.")) + return TRUE + var/obj/item/stack/cable_coil/cable = coil + if(cable.get_amount() < 1) + to_chat(user, SPAN_WARNING("You need one length of coil to wire \the [src].")) + else + visible_message(SPAN_NOTICE("\The [user] starts to wire \the [src].")) + if(do_after(user, 4 SECONDS, src) && !wired && anchored && !QDELETED(src) && cable.use(1)) + wired = TRUE + visible_message(SPAN_NOTICE("\The [user] finishes wiring \the [src].")) + return TRUE + + +/obj/structure/proc/handle_default_hammer_attackby(var/mob/user, var/obj/item/hammer) + + // Resolve ambiguous interactions. + var/can_deconstruct = (tool_interaction_flags & TOOL_INTERACTION_DECONSTRUCT) && can_dismantle(user) + var/can_unanchor = (tool_interaction_flags & TOOL_INTERACTION_ANCHOR) && can_unanchor(user) + if(can_deconstruct && can_unanchor) + var/choice = alert(user, "Do you wish to [anchored ? "unanchor" : "anchor"] or dismantle this structure?", "Tool Choice", (anchored ? "Unanchor" : "Anchor"), "Deconstruct", "Cancel") + if(!choice || choice == "Cancel" || QDELETED(src) || QDELETED(user) || QDELETED(hammer) || !CanPhysicallyInteract(user) || user.get_active_held_item() != hammer) + return TRUE + if(choice == "Deconstruct") + can_unanchor = FALSE + else + can_deconstruct = FALSE + + if(can_unanchor) + return tool_toggle_anchors(user, hammer, anchor_sound = 'sound/items/Deconstruct.ogg') + + if(can_deconstruct) + return tool_dismantle(user, hammer, deconstruct_string = "knocking apart") + + return FALSE + +/obj/structure/proc/tool_dismantle(mob/user, obj/item/tool, dismantle_sound = 'sound/items/Crowbar.ogg', deconstruct_string = "levering apart") + if(material && material.removed_by_welder) + to_chat(user, SPAN_WARNING("\The [src] is too robust to be dismantled with \the [tool]; try a welding tool.")) + return TRUE + playsound(loc, dismantle_sound, 50, 1) + visible_message(SPAN_NOTICE("\The [user] starts [deconstruct_string] \the [src] with \the [tool].")) + if(!do_after(user, 5 SECONDS, src) || QDELETED(src)) + return TRUE + playsound(loc, dismantle_sound, 50, 1) + visible_message(SPAN_NOTICE("\The [user] completely dismantles \the [src] with \the [tool].")) + dismantle_structure(user) + return TRUE + +/obj/structure/proc/welder_dismantle(mob/user, obj/item/weldingtool/welder) + if(material && !material.removed_by_welder) + to_chat(user, SPAN_WARNING("\The [src] is too delicate to be dismantled with \the [welder]; try a crowbar.")) + return TRUE + if(!welder.isOn()) + to_chat(user, SPAN_WARNING("Try lighting \the [welder] first.")) + return TRUE + if(welder.get_fuel() < 5) + to_chat(user, SPAN_WARNING("You need more fuel to complete this task.")) + return TRUE + playsound(loc, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) + visible_message(SPAN_NOTICE("\The [user] starts slicing apart \the [src] with \the [welder].")) + if(!do_after(user, 3 SECONDS, src) || QDELETED(src) || !welder.weld(5, user)) + return TRUE + playsound(loc, pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1) + visible_message(SPAN_NOTICE("\The [user] completely dismantles \the [src] with \the [welder].")) + dismantle_structure(user) + return TRUE + +/obj/structure/proc/tool_toggle_anchors(mob/user, obj/item/tool, anchor_sound = 'sound/items/Ratchet.ogg') + playsound(src.loc, anchor_sound, 100, 1) + visible_message(SPAN_NOTICE("\The [user] begins [anchored ? "unsecuring [src]" : "securing [src] in place"] with \the [tool].")) + if(!do_after(user, 4 SECONDS, src) || QDELETED(src)) + return TRUE + playsound(src.loc, anchor_sound, 100, 1) + anchored = !anchored + visible_message(SPAN_NOTICE("\The [user] has [anchored ? "secured" : "unsecured"] \the [src] with \the [tool].")) + update_icon() + return TRUE diff --git a/code/game/objects/structures/_structure_interactions.dm b/code/game/objects/structures/_structure_interactions.dm new file mode 100644 index 000000000000..ac17e0641db5 --- /dev/null +++ b/code/game/objects/structures/_structure_interactions.dm @@ -0,0 +1,74 @@ +// Anchoring or unanchoring with a hammer or a wrench. +/decl/interaction_handler/structure + abstract_type = /decl/interaction_handler/structure + expected_target_type = /obj/structure + +/decl/interaction_handler/structure/unanchor + name = "Toggle Anchoring" + examine_desc = "anchor or unanchor $TARGET_THEM$" + +/decl/interaction_handler/structure/unanchor/is_possible(atom/target, mob/user, obj/item/prop) + if(!(. = ..())) + return + var/obj/structure/struct = target + if(!(struct.tool_interaction_flags & TOOL_INTERACTION_ANCHOR) || !struct.can_unanchor(user)) + return FALSE + return istype(prop) && (IS_WRENCH(prop) || IS_HAMMER(prop)) + +/decl/interaction_handler/structure/unanchor/invoked(atom/target, mob/user, obj/item/prop) + . = ..() + var/obj/structure/struct = target + return struct.tool_toggle_anchors(user, prop) + +// Removing wiring with wirecutters or installing it with a cable coil. +/decl/interaction_handler/structure/wiring + name = "Modify Wiring" + examine_desc = "strip or install wiring" + +/decl/interaction_handler/structure/wiring/is_possible(atom/target, mob/user, obj/item/prop) + if(!(. = ..())) + return + var/obj/structure/struct = target + if(!(struct.tool_interaction_flags & TOOL_INTERACTION_WIRING)) + return FALSE + if(struct.wired) + return IS_WIRECUTTER(prop) + return IS_COIL(prop) + +/decl/interaction_handler/structure/wiring/invoked(atom/target, mob/user, obj/item/prop) + var/obj/structure/struct = target + if(struct.wired) + return struct.strip_wiring(user, prop) + return struct.install_wiring(user, prop) + +// Dismantling a structure. +/decl/interaction_handler/structure/dismantle + name = "Dismantle Structure" + examine_desc = "dismantle $TARGET_THEM$" + +/decl/interaction_handler/structure/dismantle/is_possible(atom/target, mob/user, obj/item/prop) + if(!(. = ..())) + return + var/obj/structure/struct = target + if(!(struct.tool_interaction_flags & TOOL_INTERACTION_DECONSTRUCT) || !struct.can_dismantle(user)) + return FALSE + return IS_WELDER(prop) || IS_CROWBAR(prop) || IS_HAMMER(prop) + +/decl/interaction_handler/structure/dismantle/invoked(atom/target, mob/user, obj/item/prop) + var/obj/structure/struct = target + if(IS_WELDER(prop)) + return struct.welder_dismantle(user, prop) + return struct.tool_dismantle(user, prop) + +/decl/interaction_handler/put_in_storage + name = "Put In Storage" + +/decl/interaction_handler/put_in_storage/is_possible(atom/target, mob/user, obj/item/prop) + return ..() && istype(prop) && target.storage + +// Boilerplate from /atom/proc/attackby(), replicated here so tool interactions can be bypassed. +/decl/interaction_handler/put_in_storage/invoked(atom/target, mob/user, obj/item/prop) + if((isrobot(user) && (prop == user.get_active_held_item())) || !target.storage.can_be_inserted(prop, user)) + return FALSE + prop.add_fingerprint(user) + return target.storage.handle_item_insertion(user, prop) diff --git a/code/game/objects/structures/structure_lock.dm b/code/game/objects/structures/_structure_lock.dm similarity index 100% rename from code/game/objects/structures/structure_lock.dm rename to code/game/objects/structures/_structure_lock.dm diff --git a/code/game/objects/structures/barrels/barrel.dm b/code/game/objects/structures/barrels/barrel.dm index b28986d55923..73424c453224 100644 --- a/code/game/objects/structures/barrels/barrel.dm +++ b/code/game/objects/structures/barrels/barrel.dm @@ -12,7 +12,6 @@ wrenchable = FALSE storage = /datum/storage/barrel amount_dispensed = 10 - possible_transfer_amounts = @"[10,25,50,100]" volume = 7500 movable_flags = MOVABLE_FLAG_WHEELED throwpass = TRUE @@ -22,31 +21,24 @@ // Rivets, bands, etc. Currently just cosmetic. var/decl/material/metal_material = /decl/material/solid/metal/iron -/obj/structure/reagent_dispensers/barrel/Initialize() - if(ispath(metal_material)) - metal_material = GET_DECL(metal_material) - if(!istype(metal_material)) - metal_material = null - . = ..() - if(. == INITIALIZE_HINT_NORMAL && storage) - return INITIALIZE_HINT_LATELOAD // we want to grab our turf contents. - // Overrides due to wonky reagent_dispeners opencontainer flag handling. /obj/structure/reagent_dispensers/barrel/can_be_poured_from(mob/user, atom/target) return (reagents?.maximum_volume > 0) /obj/structure/reagent_dispensers/barrel/can_be_poured_into(mob/user, atom/target) return (reagents?.maximum_volume > 0) + // Override to skip open container check. /obj/structure/reagent_dispensers/barrel/can_drink_from(mob/user) return reagents?.total_volume && user.check_has_mouth() -/obj/structure/reagent_dispensers/barrel/get_alt_interactions(mob/user) +/obj/structure/reagent_dispensers/barrel/Initialize() + if(ispath(metal_material)) + metal_material = GET_DECL(metal_material) + if(!istype(metal_material)) + metal_material = null . = ..() - if(reagents?.total_volume >= FLUID_PUDDLE) - LAZYADD(., /decl/interaction_handler/dip_item) - LAZYADD(., /decl/interaction_handler/fill_from) - if(user?.get_active_held_item()) - LAZYADD(., /decl/interaction_handler/empty_into) + if(. == INITIALIZE_HINT_NORMAL && storage) + return INITIALIZE_HINT_LATELOAD // we want to grab our turf contents. /obj/structure/reagent_dispensers/barrel/LateInitialize(mapload, ...) ..() @@ -92,6 +84,33 @@ if(istype(loc, /obj/structure/cask_rack)) loc.update_icon() +/obj/structure/reagent_dispensers/barrel/get_standard_interactions(var/mob/user) + . = ..() + if(reagents?.maximum_volume) + LAZYADD(., global._reagent_interactions) + + // Disambiguation actions, since barrels can have several different potential interactions for + // the same item. It would be nice to enable this on /obj/structure in general but there are a + // ton of really bespoke overrides of the standard tool methods (windows, AI core, etc.). + if(tool_interaction_flags & TOOL_INTERACTION_ANCHOR) + LAZYADD(., /decl/interaction_handler/structure/unanchor) + if(tool_interaction_flags & TOOL_INTERACTION_WIRING) + LAZYADD(., /decl/interaction_handler/structure/wiring) + if(tool_interaction_flags & TOOL_INTERACTION_DECONSTRUCT) + LAZYADD(., /decl/interaction_handler/structure/dismantle) + if(LAZYLEN(.) && storage) + LAZYADD(., /decl/interaction_handler/put_in_storage) + +// Copy of above - maybe we should just have a single 'get interactions' proc at this point? +/obj/structure/reagent_dispensers/barrel/get_alt_interactions(mob/user) + . = ..() + if(tool_interaction_flags & TOOL_INTERACTION_ANCHOR) + LAZYADD(., /decl/interaction_handler/structure/unanchor) + if(tool_interaction_flags & TOOL_INTERACTION_WIRING) + LAZYADD(., /decl/interaction_handler/structure/wiring) + if(tool_interaction_flags & TOOL_INTERACTION_DECONSTRUCT) + LAZYADD(., /decl/interaction_handler/structure/dismantle) + /obj/structure/reagent_dispensers/barrel/ebony material = /decl/material/solid/organic/wood/ebony color = /decl/material/solid/organic/wood/ebony::color diff --git a/code/game/objects/structures/crates_lockers/closets/__closet.dm b/code/game/objects/structures/crates_lockers/closets/__closet.dm index 9e717d53f973..6bfeca7cfe85 100644 --- a/code/game/objects/structures/crates_lockers/closets/__closet.dm +++ b/code/game/objects/structures/crates_lockers/closets/__closet.dm @@ -548,6 +548,7 @@ var/global/list/closets = list() /decl/interaction_handler/closet_lock_toggle name = "Toggle Lock" expected_target_type = /obj/structure/closet + examine_desc = "toggle the lock" /decl/interaction_handler/closet_lock_toggle/is_possible(atom/target, mob/user, obj/item/prop) . = ..() diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 6df0fd7eb1cb..d3aa1f21c39c 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -236,9 +236,6 @@ storage_types = CLOSET_STORAGE_ITEMS|CLOSET_STORAGE_STRUCTURES icon = 'icons/obj/closets/bases/large_crate.dmi' -/obj/structure/closet/crate/secure/large/supermatter - closet_appearance = /decl/closet_appearance/large_crate/secure/hazard - //fluff variant /obj/structure/closet/crate/secure/large/reinforced desc = "A hefty, reinforced metal crate with an electronic locking system." diff --git a/code/game/objects/structures/doors/_door.dm b/code/game/objects/structures/doors/_door.dm index 745ad4bea2d6..ff6989638376 100644 --- a/code/game/objects/structures/doors/_door.dm +++ b/code/game/objects/structures/doors/_door.dm @@ -205,12 +205,13 @@ /obj/structure/door/get_alt_interactions(var/mob/user) . = ..() if(density) - . += /decl/interaction_handler/knock_on_door + LAZYADD(., /decl/interaction_handler/knock_on_door) /decl/interaction_handler/knock_on_door name = "Knock On Door" expected_target_type = /obj/structure/door interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEEDS_TURF + examine_desc = "knock on $TARGET_THEM$" /decl/interaction_handler/knock_on_door/invoked(atom/target, mob/user, obj/item/prop) if(!istype(target) || !target.density) diff --git a/code/game/objects/structures/extinguisher.dm b/code/game/objects/structures/extinguisher.dm index 03d91b43ce49..768fe81af7f1 100644 --- a/code/game/objects/structures/extinguisher.dm +++ b/code/game/objects/structures/extinguisher.dm @@ -80,6 +80,7 @@ /decl/interaction_handler/extinguisher_cabinet_open name = "Open/Close" expected_target_type = /obj/structure/extinguisher_cabinet + examine_desc = "open or close $TARGET_THEM$" /decl/interaction_handler/extinguisher_cabinet_open/invoked(atom/target, mob/user, obj/item/prop) var/obj/structure/extinguisher_cabinet/C = target diff --git a/code/game/objects/structures/fires.dm b/code/game/objects/structures/fires.dm index e0fe3055aa7f..4da0fe525978 100644 --- a/code/game/objects/structures/fires.dm +++ b/code/game/objects/structures/fires.dm @@ -70,7 +70,8 @@ var/lit = FIRE_OUT /// How much fuel is left? var/fuel = 0 - + /// Have we been fed by a bellows recently? + var/bellows_oxygenation = 0 /obj/structure/fire_source/Initialize() . = ..() @@ -138,6 +139,7 @@ /obj/structure/fire_source/proc/die() if(lit == FIRE_LIT) + bellows_oxygenation = 0 lit = FIRE_DEAD last_fuel_ignite_temperature = null last_fuel_burn_temperature = T20C @@ -308,7 +310,9 @@ return ..() /obj/structure/fire_source/proc/get_draught_multiplier() - return has_draught ? draught_values[draught_values[current_draught]] : 1 + . = has_draught ? draught_values[draught_values[current_draught]] : 1 + if(bellows_oxygenation) + . *= 1.25 // Burns 25% hotter while oxygenated. /obj/structure/fire_source/proc/process_fuel(ignition_temperature) var/draught_mult = get_draught_multiplier() @@ -413,6 +417,10 @@ die() return + // Spend our bellows charge. + if(bellows_oxygenation > 0) + bellows_oxygenation-- + fuel -= (FUEL_CONSUMPTION_CONSTANT * get_draught_multiplier()) if(!process_fuel()) die() @@ -461,7 +469,7 @@ switch(lit) if(FIRE_LIT) - if(fuel >= HIGH_FUEL) + if(bellows_oxygenation || fuel >= HIGH_FUEL) var/image/I = image(icon, "[icon_state]_lit") I.appearance_flags |= RESET_COLOR | RESET_ALPHA | KEEP_APART add_overlay(I) @@ -510,6 +518,7 @@ /decl/interaction_handler/adjust_draught name = "Adjust Draught" expected_target_type = /obj/structure/fire_source + examine_desc = "adjust the draught" /decl/interaction_handler/adjust_draught/invoked(atom/target, mob/user, obj/item/prop) var/obj/structure/fire_source/fire = target diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm index 66f0afe17852..96c1baf5b0aa 100644 --- a/code/game/objects/structures/railing.dm +++ b/code/game/objects/structures/railing.dm @@ -19,6 +19,9 @@ var/broken = FALSE var/neighbor_status = 0 +/obj/structure/railing/should_have_alpha_mask() + return simulated && isturf(loc) && !(locate(/obj/structure/railing) in get_step(loc, SOUTH)) + /obj/structure/railing/mapped anchored = TRUE color = COLOR_ORANGE diff --git a/code/game/objects/structures/snowman.dm b/code/game/objects/structures/snowman.dm new file mode 100644 index 000000000000..60382df695cc --- /dev/null +++ b/code/game/objects/structures/snowman.dm @@ -0,0 +1,59 @@ +/obj/structure/snowman + name = "man" + icon = 'icons/obj/structures/snowmen/snowman.dmi' + icon_state = ICON_STATE_WORLD + desc = "A happy little $NAME$ smiles back at you!" + anchored = TRUE + material = /decl/material/solid/ice/snow + material_alteration = MAT_FLAG_ALTERATION_ALL // We override name and desc below. + +/obj/structure/snowman/Initialize(ml, _mat, _reinf_mat) + . = ..() + update_icon() + +/obj/structure/snowman/update_material_name(override_name) + SHOULD_CALL_PARENT(FALSE) + if(istype(material)) + SetName("[material.solid_name][initial(name)]") + else + SetName("mystery[initial(name)]") + +/obj/structure/snowman/update_material_desc(override_desc) + SHOULD_CALL_PARENT(FALSE) + if(istype(material)) + var/snowname = "[material.solid_name][initial(name)]" + desc = replacetext(initial(desc), "$NAME$", snowname) + else + desc = replacetext(initial(desc), "$NAME$", "mysteryman") + +/obj/structure/snowman/on_update_icon() + . = ..() + // TODO: make carrot/stick arms/coal require items? + add_overlay(overlay_image(icon, "[icon_state]-decorations", COLOR_WHITE, RESET_COLOR)) + compile_overlays() + +/obj/structure/snowman/proc/user_destroyed(user) + to_chat(user, SPAN_DANGER("\The [src] crumples into a pile of [material.solid_name] after a single solid hit. You monster.")) + physically_destroyed() + +/obj/structure/snowman/attackby(obj/item/used_item, mob/user) + if(user.check_intent(I_FLAG_HARM) && used_item.get_base_attack_force()) + user_destroyed(user) + return TRUE + return ..() + +/obj/structure/snowman/attack_hand(mob/user) + if(user.check_intent(I_FLAG_HARM)) + user_destroyed(user) + return TRUE + return ..() + +/obj/structure/snowman/bot + name = "bot" + icon = 'icons/obj/structures/snowmen/snowbot.dmi' + desc = "A bland-faced little $NAME$. It even has a monitor for a head." + +/obj/structure/snowman/spider + name = "spider" + icon = 'icons/obj/structures/snowmen/snowspider.dmi' + desc = "An impressively-crafted $NAME$. Not nearly as creepy as the real thing." \ No newline at end of file diff --git a/code/game/objects/structures/stool_bed_chair_nest_sofa/pew.dm b/code/game/objects/structures/stool_bed_chair_nest_sofa/pew.dm index b14f6db9257d..59da1232a7c8 100644 --- a/code/game/objects/structures/stool_bed_chair_nest_sofa/pew.dm +++ b/code/game/objects/structures/stool_bed_chair_nest_sofa/pew.dm @@ -11,6 +11,9 @@ anchored = TRUE var/connect_neighbors = TRUE +/obj/structure/bed/chair/bench/should_have_alpha_mask() + return simulated && isturf(loc) && connect_neighbors && !(locate(/obj/structure/bed/chair/bench) in get_step(loc, SOUTH)) + /obj/structure/bed/chair/bench/single name = "slatted seat" base_icon = "bench_standing" diff --git a/code/game/objects/structures/tables.dm b/code/game/objects/structures/tables.dm index e1fced7cee86..459216c264a5 100644 --- a/code/game/objects/structures/tables.dm +++ b/code/game/objects/structures/tables.dm @@ -26,6 +26,7 @@ var/can_flip = TRUE var/is_flipped = FALSE var/decl/material/additional_reinf_material + var/base_type = /obj/structure/table var/top_surface_noun = "tabletop" @@ -37,6 +38,9 @@ /// Whether items can be placed on this table via clicking. var/can_place_items = TRUE +/obj/structure/table/should_have_alpha_mask() + return simulated && isturf(loc) && !(locate(/obj/structure/table) in get_step(loc, SOUTH)) + /obj/structure/table/clear_connections() connections = null diff --git a/code/game/objects/structures/well.dm b/code/game/objects/structures/well.dm index eb6f59bc68f3..911413e67e9b 100644 --- a/code/game/objects/structures/well.dm +++ b/code/game/objects/structures/well.dm @@ -18,19 +18,6 @@ can_toggle_open = FALSE var/auto_refill -/obj/structure/reagent_dispensers/well/get_alt_interactions(mob/user) - . = ..() - if(reagents?.total_volume >= FLUID_PUDDLE) - LAZYADD(., /decl/interaction_handler/dip_item) - LAZYADD(., /decl/interaction_handler/fill_from) - if(user?.get_active_held_item()) - LAZYADD(., /decl/interaction_handler/empty_into) - -// Overrides due to wonky reagent_dispeners opencontainer flag handling. -/obj/structure/reagent_dispensers/well/can_be_poured_from(mob/user, atom/target) - return (reagents?.maximum_volume > 0) -/obj/structure/reagent_dispensers/well/can_be_poured_into(mob/user, atom/target) - return (reagents?.maximum_volume > 0) // Override to skip open container check. /obj/structure/reagent_dispensers/well/can_drink_from(mob/user) return reagents?.total_volume && user.check_has_mouth() @@ -61,6 +48,17 @@ if(!is_processing && auto_refill) START_PROCESSING(SSobj, src) +// Overrides due to wonky reagent_dispeners opencontainer flag handling. +/obj/structure/reagent_dispensers/well/can_be_poured_from(mob/user, atom/target) + return (reagents?.maximum_volume > 0) +/obj/structure/reagent_dispensers/well/can_be_poured_into(mob/user, atom/target) + return (reagents?.maximum_volume > 0) + +/obj/structure/reagent_dispensers/well/get_standard_interactions(var/mob/user) + . = ..() + if(reagents?.maximum_volume) + LAZYADD(., global._reagent_interactions) + /obj/structure/reagent_dispensers/well/Process() if(!reagents || !auto_refill) // if we're full, we only stop at the end of the proc; we need to check for contaminants first return PROCESS_KILL diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index bb4bf1781075..d516cd10eb23 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -404,12 +404,10 @@ if (polarized) to_chat(user, SPAN_NOTICE("It appears to be wired.")) -/obj/structure/window/proc/set_anchored(var/new_anchored) - if(anchored == new_anchored) - return - anchored = new_anchored - update_connections(1) - update_nearby_icons() +/obj/structure/window/set_anchored(new_anchored) + if((. = ..())) + update_connections(1) + update_nearby_icons() //This proc is used to update the icons of nearby windows. It should not be confused with update_nearby_tiles(), which is an atmos proc! /obj/structure/window/proc/update_nearby_icons() diff --git a/code/game/turfs/flooring/_flooring.dm b/code/game/turfs/flooring/_flooring.dm index 8150d0abd34b..d30c22285702 100644 --- a/code/game/turfs/flooring/_flooring.dm +++ b/code/game/turfs/flooring/_flooring.dm @@ -16,7 +16,7 @@ var/global/list/flooring_cache = list() var/gender = PLURAL /// "that's some grass" var/icon_base var/color = COLOR_WHITE - var/footstep_type = /decl/footsteps/blank + var/footstep_type = /decl/footsteps/plating var/growth_value = 0 var/neighbour_type @@ -35,11 +35,17 @@ var/global/list/flooring_cache = list() /// BYOND ticks. var/build_time = 0 + var/drop_material_on_remove + var/descriptor var/flooring_flags var/remove_timer = 10 var/can_paint var/can_engrave = TRUE + var/can_collect = FALSE + + // Not bloody prints, but rather prints on top of the turf (snow, mud) + var/print_type var/turf_light_range var/turf_light_power @@ -261,8 +267,9 @@ var/global/list/flooring_cache = list() global.flooring_cache[cache_key] = I return global.flooring_cache[cache_key] -/decl/flooring/proc/on_remove() - return +/decl/flooring/proc/on_flooring_remove(turf/removing_from) + if(force_material && drop_material_on_remove) + force_material.create_object(removing_from, rand(3,5)) /decl/flooring/proc/get_movement_delay(var/travel_dir, var/mob/mover) return movement_delay @@ -270,6 +277,17 @@ var/global/list/flooring_cache = list() /decl/flooring/proc/get_movable_alpha_mask_state(atom/movable/mover) return +/decl/flooring/proc/handle_hand_interaction(turf/floor/floor, mob/user) + if(!force_material || !can_collect) + return FALSE + user.visible_message(SPAN_NOTICE("\The [user] begins scraping together some of \the [name]...")) + if(do_after(user, 3 SECONDS, floor) && !QDELETED(floor) && !QDELETED(user) && floor.get_topmost_flooring() == src && isnull(user.get_active_held_item())) + var/list/created = force_material.create_object(floor, 1) + user.visible_message(SPAN_NOTICE("\The [user] scrapes together [english_list(created)].")) + for(var/obj/item/stack/stack in created) + stack.add_to_stacks(user, TRUE) + return TRUE + /decl/flooring/proc/handle_item_interaction(turf/floor/floor, mob/user, obj/item/item) if(!istype(user) || !istype(item) || !istype(floor) || user.check_intent(I_FLAG_HARM)) @@ -351,8 +369,27 @@ var/global/list/flooring_cache = list() /decl/flooring/proc/handle_turf_digging(turf/floor/target) return TRUE +/decl/flooring/proc/turf_exited(turf/target, atom/movable/crosser, atom/new_loc) + return print_type && try_place_footprints(crosser, target, target, new_loc, "going") + +/decl/flooring/proc/turf_entered(turf/target, atom/movable/crosser, atom/old_loc) + return print_type && try_place_footprints(crosser, target, old_loc, target, "coming") + +/decl/flooring/proc/try_place_footprints(atom/movable/crosser, turf/target, turf/from_turf, turf/to_turf, use_state = "going") + if(!ismob(crosser) || !crosser.simulated || !isturf(from_turf) || !isturf(to_turf)) + return FALSE + var/movement_dir = get_dir(from_turf, to_turf) + if(!movement_dir) + return FALSE + var/mob/walker = crosser + var/footprint_icon = walker.get_footprints_icon() + if(!footprint_icon) + return FALSE + var/obj/effect/footprints/prints = (locate() in target) || new print_type(target) + prints.add_footprints(crosser, footprint_icon, movement_dir, use_state) + /decl/flooring/proc/turf_crossed(atom/movable/crosser) return -/decl/flooring/proc/can_show_footsteps(turf/target) +/decl/flooring/proc/can_show_coating_footprints(turf/target) return TRUE diff --git a/code/game/turfs/flooring/flooring_lava.dm b/code/game/turfs/flooring/flooring_lava.dm index beebb36b775d..9fe4be66e462 100644 --- a/code/game/turfs/flooring/flooring_lava.dm +++ b/code/game/turfs/flooring/flooring_lava.dm @@ -18,7 +18,7 @@ var/datum/gas_mixture/environment = target.return_air() var/pressure = environment?.return_pressure() for(var/atom/movable/AM as anything in target.get_contained_external_atoms()) - if(!AM.is_burnable()) + if(!AM.is_burnable() || AM.immune_to_floor_hazards()) continue . = null if(isliving(AM)) diff --git a/code/game/turfs/flooring/flooring_misc.dm b/code/game/turfs/flooring/flooring_misc.dm index eb80eae759e6..cdedfb756198 100644 --- a/code/game/turfs/flooring/flooring_misc.dm +++ b/code/game/turfs/flooring/flooring_misc.dm @@ -35,7 +35,6 @@ can_engrave = FALSE color = GLASS_COLOR z_flags = ZM_MIMIC_DEFAULTS - footstep_type = /decl/footsteps/plating force_material = /decl/material/solid/glass constructed = TRUE diff --git a/code/game/turfs/flooring/flooring_mud.dm b/code/game/turfs/flooring/flooring_mud.dm index 2b5fa2c5063d..a4865eb5fe7f 100644 --- a/code/game/turfs/flooring/flooring_mud.dm +++ b/code/game/turfs/flooring/flooring_mud.dm @@ -9,6 +9,8 @@ turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID force_material = /decl/material/solid/soil growth_value = 1.1 + can_collect = TRUE + print_type = /obj/effect/footprints /decl/flooring/mud/fire_act(turf/floor/target, datum/gas_mixture/air, exposed_temperature, exposed_volume) if(!target.reagents?.total_volume) @@ -25,7 +27,7 @@ var/mob/living/walker = crosser walker.add_walking_contaminant(/decl/material/solid/soil, rand(2,3)) -/decl/flooring/mud/can_show_footsteps(turf/target) +/decl/flooring/mud/can_show_coating_footprints(turf/target) return FALSE // So we don't end up covered in a million footsteps that we provided. /decl/flooring/dry_mud diff --git a/code/game/turfs/flooring/flooring_natural.dm b/code/game/turfs/flooring/flooring_natural.dm index 9ca61af786eb..63d3b2ec93c5 100644 --- a/code/game/turfs/flooring/flooring_natural.dm +++ b/code/game/turfs/flooring/flooring_natural.dm @@ -29,6 +29,7 @@ has_base_range = null footstep_type = /decl/footsteps/mud force_material = /decl/material/solid/organic/meat + print_type = /obj/effect/footprints /decl/flooring/barren name = "ground" @@ -52,13 +53,14 @@ turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID force_material = /decl/material/solid/clay growth_value = 1.2 + can_collect = TRUE + print_type = /obj/effect/footprints /decl/flooring/ice name = "ice" desc = "A hard, slippery layer of frozen water." icon = 'icons/turf/flooring/ice.dmi' icon_base = "ice" - footstep_type = /decl/footsteps/plating color = COLOR_LIQUID_WATER force_material = /decl/material/solid/ice diff --git a/code/game/turfs/flooring/flooring_path.dm b/code/game/turfs/flooring/flooring_path.dm index 37ce339b7ecf..475573d57730 100644 --- a/code/game/turfs/flooring/flooring_path.dm +++ b/code/game/turfs/flooring/flooring_path.dm @@ -7,6 +7,7 @@ neighbour_type = /decl/flooring/path color = null constructed = TRUE + // If null, this is just skipped. var/paving_adjective = "cobbled" var/paver_adjective = "loose" diff --git a/code/game/turfs/flooring/flooring_reinforced.dm b/code/game/turfs/flooring/flooring_reinforced.dm index a926312bc8fd..0a46fa2d41ca 100644 --- a/code/game/turfs/flooring/flooring_reinforced.dm +++ b/code/game/turfs/flooring/flooring_reinforced.dm @@ -9,7 +9,6 @@ build_cost = 1 build_time = 30 can_paint = 1 - footstep_type = /decl/footsteps/plating force_material = /decl/material/solid/metal/steel constructed = TRUE gender = NEUTER diff --git a/code/game/turfs/flooring/flooring_rock.dm b/code/game/turfs/flooring/flooring_rock.dm index 57063ec8bd0b..89b3fd455353 100644 --- a/code/game/turfs/flooring/flooring_rock.dm +++ b/code/game/turfs/flooring/flooring_rock.dm @@ -7,7 +7,6 @@ color = null icon_edge_layer = FLOOR_EDGE_VOLCANIC gender = NEUTER - footstep_type = /decl/footsteps/plating /decl/flooring/rock/update_turf_strings(turf/floor/target) var/decl/material/material = target?.get_material() diff --git a/code/game/turfs/flooring/flooring_sand.dm b/code/game/turfs/flooring/flooring_sand.dm index 27084c19ecb7..caf29c810493 100644 --- a/code/game/turfs/flooring/flooring_sand.dm +++ b/code/game/turfs/flooring/flooring_sand.dm @@ -8,6 +8,8 @@ has_base_range = 4 turf_flags = TURF_FLAG_BACKGROUND | TURF_IS_HOLOMAP_PATH | TURF_FLAG_ABSORB_LIQUID force_material = /decl/material/solid/sand + can_collect = TRUE + print_type = /obj/effect/footprints /decl/flooring/sand/fire_act(turf/floor/target, datum/gas_mixture/air, exposed_temperature, exposed_volume) if((exposed_temperature > T0C + 1700 && prob(5)) || exposed_temperature > T0C + 3000) diff --git a/code/game/turfs/flooring/flooring_snow.dm b/code/game/turfs/flooring/flooring_snow.dm index 6055cdda83db..834b109eea7d 100644 --- a/code/game/turfs/flooring/flooring_snow.dm +++ b/code/game/turfs/flooring/flooring_snow.dm @@ -7,6 +7,9 @@ footstep_type = /decl/footsteps/snow has_base_range = 13 force_material = /decl/material/solid/ice/snow + can_collect = TRUE + print_type = /obj/effect/footprints + drop_material_on_remove = TRUE /decl/flooring/snow/get_movement_delay(var/travel_dir, var/mob/mover) . = ..() diff --git a/code/game/turfs/floors/_floor.dm b/code/game/turfs/floors/_floor.dm index e8ede4d119e8..844b479eaa12 100644 --- a/code/game/turfs/floors/_floor.dm +++ b/code/game/turfs/floors/_floor.dm @@ -138,7 +138,7 @@ for(var/obj/effect/decal/writing/W in src) qdel(W) - _flooring.on_remove() + _flooring.on_flooring_remove(src) if(_flooring.build_type && place_product) // If build type uses material stack, check for it // Because material stack uses different arguments @@ -172,7 +172,6 @@ /turf/floor/proc/update_from_flooring(skip_update) - var/decl/flooring/copy_from = get_topmost_flooring() if(!istype(copy_from)) return // this should never be the case @@ -199,6 +198,9 @@ levelupdate() + for(var/obj/effect/footprints/print in src) + qdel(print) + if(!skip_update) update_icon() for(var/dir in global.alldirs) @@ -276,16 +278,18 @@ return PROCESS_KILL // In case a catwalk or other blocking item is destroyed. -/turf/floor/Exited(atom/movable/AM) +/turf/floor/Exited(atom/movable/AM, atom/new_loc) . = ..() if(!is_processing) for(var/decl/flooring/flooring in get_all_flooring()) if(flooring.has_environment_proc) START_PROCESSING(SSobj, src) break + var/decl/flooring/print_flooring = get_topmost_flooring() + print_flooring?.turf_exited(src, AM, new_loc) // In case something of interest enters our turf. -/turf/floor/Entered(atom/movable/AM) +/turf/floor/Entered(atom/movable/AM, atom/old_loc) . = ..() for(var/decl/flooring/flooring in get_all_flooring()) if(flooring.has_environment_proc) @@ -293,6 +297,8 @@ START_PROCESSING(SSobj, src) flooring.handle_environment_proc(src) break + var/decl/flooring/print_flooring = get_topmost_flooring() + print_flooring?.turf_entered(src, AM, old_loc) /turf/floor/get_plant_growth_rate() var/decl/flooring/flooring = get_topmost_flooring() @@ -303,5 +309,5 @@ flooring?.turf_crossed(AM) return ..() -/turf/floor/can_show_footsteps() - return ..() && get_topmost_flooring()?.can_show_footsteps(src) +/turf/floor/can_show_coating_footprints() + return ..() && get_topmost_flooring()?.can_show_coating_footprints(src) diff --git a/code/game/turfs/floors/floor_attackby.dm b/code/game/turfs/floors/floor_attackby.dm index d023e3d2ee58..f56777dd1c80 100644 --- a/code/game/turfs/floors/floor_attackby.dm +++ b/code/game/turfs/floors/floor_attackby.dm @@ -1,10 +1,14 @@ /turf/floor/attack_hand(mob/user) - if(!ishuman(user)) - return ..() - var/mob/living/human/H = user - var/obj/item/hand = GET_EXTERNAL_ORGAN(H, H.get_active_held_item_slot()) - if(hand && try_graffiti(H, hand)) + + // Collect snow or mud. + var/decl/flooring/flooring = get_topmost_flooring() + if(flooring?.handle_hand_interaction(src, user)) return TRUE + + var/obj/item/hand = GET_EXTERNAL_ORGAN(user, user.get_active_held_item_slot()) + if(hand && try_graffiti(user, hand)) + return TRUE + return ..() /turf/floor/attackby(var/obj/item/used_item, var/mob/user) diff --git a/code/game/turfs/floors/floor_digging.dm b/code/game/turfs/floors/floor_digging.dm index 3351970e8af6..d3cadac07f98 100644 --- a/code/game/turfs/floors/floor_digging.dm +++ b/code/game/turfs/floors/floor_digging.dm @@ -47,10 +47,20 @@ /turf/floor/get_diggable_resources() var/decl/material/my_material = get_material() - if(is_fundament() && istype(my_material) && my_material.dug_drop_type && (get_physical_height() > -(FLUID_DEEP))) - . = list() - .[my_material.dug_drop_type] = list("amount" = 3, "variance" = 2, "material" = my_material.type) - if(!gemstone_dropped && prob(my_material.gemstone_chance) && LAZYLEN(my_material.gemstone_types)) - gemstone_dropped = TRUE - var/gem_mat = pick(my_material.gemstone_types) - .[/obj/item/gemstone] = list("amount" = 1, "material" = gem_mat) + if(!is_fundament() || !istype(my_material) || !my_material.dug_drop_type || (get_physical_height() <= -(FLUID_DEEP))) + return + + . = list() + + // All turfs drop resources to backfill them with (or make firepits, etc) + .[my_material.dug_drop_type] = list("amount" = 3, "variance" = 2, "material" = my_material.type) + + // Dirt/mud/etc might have some worms. + if(prob(5 * get_plant_growth_rate())) + .[/obj/item/food/worm] = list("amount" = 1, "material" = /obj/item/food/worm::material) + + // Some materials (like clay) might contain gemstones. + if(!gemstone_dropped && prob(my_material.gemstone_chance) && LAZYLEN(my_material.gemstone_types)) + gemstone_dropped = TRUE + var/gem_mat = pick(my_material.gemstone_types) + .[/obj/item/gemstone] = list("amount" = 1, "material" = gem_mat) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 40ab4f3b70d3..8bde4c7ad246 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -208,7 +208,10 @@ . += (reagents.total_volume > FLUID_SHALLOW) ? 6 : 3 /turf/attack_hand(mob/user) + SHOULD_CALL_PARENT(FALSE) + + // Find an atom that should be intercepting this click. var/datum/extension/turf_hand/highest_priority_intercept for(var/atom/thing in contents) var/datum/extension/turf_hand/intercept = get_extension(thing, /datum/extension/turf_hand) @@ -218,6 +221,7 @@ user.setClickCooldown(DEFAULT_QUICK_COOLDOWN) var/atom/intercepting_atom = highest_priority_intercept.holder return intercepting_atom.attack_hand(user) + return FALSE /turf/attack_robot(var/mob/user) @@ -395,11 +399,13 @@ L.Add(t) return L -/turf/proc/contains_dense_objects() +/turf/proc/contains_dense_objects(exceptions) if(density) return 1 for(var/atom/A in src) if(A.density && !(A.atom_flags & ATOM_FLAG_CHECKS_BORDER)) + if(exceptions && (exceptions == A || (A in exceptions))) + continue return 1 return 0 @@ -684,8 +690,8 @@ return TRUE /turf/clean(clean_forensics = TRUE) - for(var/obj/effect/decal/cleanable/blood/B in contents) - B.clean(clean_forensics) + for(var/obj/effect/decal/cleanable/filth in contents) + filth.clean(clean_forensics) . = ..() //returns 1 if made bloody, returns 0 otherwise @@ -795,30 +801,27 @@ /turf/get_alt_interactions(mob/user) . = ..() LAZYADD(., /decl/interaction_handler/show_turf_contents) - if(user) - var/obj/item/held = user.get_active_held_item() || user.get_usable_hand_slot_organ() - if(istype(held)) - if(reagents?.total_volume >= FLUID_PUDDLE) - LAZYADD(., /decl/interaction_handler/dip_item) - LAZYADD(., /decl/interaction_handler/fill_from) - LAZYADD(., /decl/interaction_handler/empty_into) - if(IS_SHOVEL(held)) - if(can_dig_pit(held.material?.hardness)) - LAZYDISTINCTADD(., /decl/interaction_handler/dig/pit) - if(can_dig_trench(held.material?.hardness)) - LAZYDISTINCTADD(., /decl/interaction_handler/dig/trench) - if(IS_PICK(held) && can_dig_trench(held.material?.hardness, using_tool = TOOL_PICK)) - LAZYDISTINCTADD(., /decl/interaction_handler/dig/trench) - if(IS_HOE(held) && can_dig_farm(held.material?.hardness)) - LAZYDISTINCTADD(., /decl/interaction_handler/dig/farm) - -/turf/proc/can_show_footsteps() + var/obj/item/held = user ? (user.get_active_held_item() || user.get_usable_hand_slot_organ()) : null + if(!istype(held)) + return + if(IS_SHOVEL(held)) + if(can_dig_pit(held.material?.hardness)) + LAZYADD(., /decl/interaction_handler/dig/pit) + if(can_dig_trench(held.material?.hardness)) + LAZYADD(., /decl/interaction_handler/dig/trench) + if(IS_PICK(held) && can_dig_trench(held.material?.hardness, using_tool = TOOL_PICK)) + LAZYADD(., /decl/interaction_handler/dig/trench) + if(IS_HOE(held) && can_dig_farm(held.material?.hardness)) + LAZYADD(., /decl/interaction_handler/dig/farm) + +/turf/proc/can_show_coating_footprints() return simulated /decl/interaction_handler/show_turf_contents name = "Show Turf Contents" expected_user_type = /mob interaction_flags = 0 + examine_desc = "list everything on $TARGET_THEM$" /decl/interaction_handler/show_turf_contents/invoked(atom/target, mob/user, obj/item/prop) target.show_atom_list_for_turf(user, get_turf(target)) @@ -831,6 +834,7 @@ /decl/interaction_handler/dig/trench name = "Dig Trench" + examine_desc = "dig a trench" /decl/interaction_handler/dig/trench/invoked(atom/target, mob/user, obj/item/prop) prop ||= user.get_usable_hand_slot_organ() // Allows drakes to dig. @@ -845,6 +849,7 @@ /decl/interaction_handler/dig/pit name = "Dig Pit" + examine_desc = "dig a pit" /decl/interaction_handler/dig/pit/invoked(atom/target, mob/user, obj/item/prop) prop ||= user.get_usable_hand_slot_organ() // Allows drakes to dig. @@ -854,6 +859,7 @@ /decl/interaction_handler/dig/farm name = "Dig Farm Plot" + examine_desc = "dig a farm plot" /decl/interaction_handler/dig/farm/invoked(atom/target, mob/user, obj/item/prop) prop ||= user.get_usable_hand_slot_organ() // Allows drakes to dig. @@ -863,3 +869,5 @@ /turf/take_vaporized_reagent(reagent, amount) return assume_gas(reagent, round(amount / REAGENT_UNITS_PER_GAS_MOLE)) + +/turf/proc/is_purged() \ No newline at end of file diff --git a/code/game/turfs/turf_fluids.dm b/code/game/turfs/turf_fluids.dm index 7d0cec0a34f0..29ea8eefb0db 100644 --- a/code/game/turfs/turf_fluids.dm +++ b/code/game/turfs/turf_fluids.dm @@ -116,7 +116,7 @@ /turf/fluid_act(var/datum/reagents/fluids) ..() if(!QDELETED(src) && fluids?.total_volume) - fluids.touch_turf(src) + fluids.touch_turf(src, touch_atoms = FALSE) // Handled in fluid_act() below. for(var/atom/movable/AM as anything in get_contained_external_atoms()) if(!AM.submerged()) continue diff --git a/code/game/turfs/walls/wall_natural_ramps.dm b/code/game/turfs/walls/wall_natural_ramps.dm index 7566bf7578f5..760c4a01f0d5 100644 --- a/code/game/turfs/walls/wall_natural_ramps.dm +++ b/code/game/turfs/walls/wall_natural_ramps.dm @@ -54,6 +54,7 @@ /decl/interaction_handler/drill_ramp name = "Drill Ramp" expected_target_type = /turf/wall/natural + examine_desc = "drill a ramp in the direction you are facing" /decl/interaction_handler/drill_ramp/is_possible(atom/target, mob/user, obj/item/prop) . = ..() diff --git a/code/modules/abstract/abstract_fluid_direction.dm b/code/modules/abstract/abstract_fluid_direction.dm new file mode 100644 index 000000000000..7dabaa77623e --- /dev/null +++ b/code/modules/abstract/abstract_fluid_direction.dm @@ -0,0 +1,37 @@ +/obj/abstract/force_fluid_flow + icon_state = "arrow" + +/obj/abstract/force_fluid_flow/Initialize() + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/abstract/force_fluid_flow/north + dir = NORTH + +/obj/abstract/force_fluid_flow/south + dir = SOUTH + +/obj/abstract/force_fluid_flow/east + dir = EAST + +/obj/abstract/force_fluid_flow/west + dir = WEST + +/obj/abstract/force_fluid_flow/southeast + dir = SOUTHEAST + +/obj/abstract/force_fluid_flow/southwest + dir = SOUTHWEST + +/obj/abstract/force_fluid_flow/northeast + dir = NORTHEAST + +/obj/abstract/force_fluid_flow/northwest + dir = NORTHWEST + +/obj/abstract/force_fluid_flow/LateInitialize() + . = ..() + var/atom/movable/fluid_overlay/fluids = locate() in loc + fluids.force_flow_direction = dir + fluids.queue_icon_update() + qdel(src) diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm index 546f5753cee8..8483aa50faa7 100644 --- a/code/modules/admin/admin_investigate.dm +++ b/code/modules/admin/admin_investigate.dm @@ -34,7 +34,7 @@ return show_browser(src, F, "window=investigate[subject];size=800x300") - if("hrefs") //persistant logs and stuff + if("hrefs") //persistent logs and stuff if(get_config_value(/decl/config/toggle/log_hrefs)) if(global.world_href_log) show_browser(src, global.world_href_log, "window=investigate[subject];size=800x300") diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index b93ccd2bde96..aba99df3baf1 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -883,16 +883,6 @@ var/global/list/admin_verbs_mod = list( log_and_message_admins("told everyone to man up and deal with it.") -/client/proc/give_spell(mob/T as mob in SSmobs.mob_list) // -- Urist - set category = "Fun" - set name = "Give Spell" - set desc = "Gives a spell to a mob." - var/spell/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spells - if(!S) return - T.add_spell(new S) - SSstatistics.add_field_details("admin_verb","GS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - log_and_message_admins("gave [key_name(T)] the spell [S].") - /client/proc/change_lobby_screen() set name = "Lobby Screen: Change" set category = "Fun" diff --git a/code/modules/admin/verbs/grief_fixers.dm b/code/modules/admin/verbs/grief_fixers.dm index 2394d2a8197f..afea1d4a6feb 100644 --- a/code/modules/admin/verbs/grief_fixers.dm +++ b/code/modules/admin/verbs/grief_fixers.dm @@ -4,35 +4,55 @@ if(!check_rights(R_ADMIN|R_DEBUG)) return - if(alert("WARNING: Executing this command will perform a full reset of atmosphere. All pipelines will lose any gas that may be in them, and all zones will be reset to contain air mix as on roundstart. The supermatter engine will also be stopped (to prevent overheat due to removal of coolant). Do not use unless the map is suffering serious atmospheric issues due to grief or bug.", "Full Atmosphere Reboot", "No", "Yes") == "No") + if(alert("WARNING: Executing this command will perform a full reset of atmosphere. All pipelines will lose any gas that may be in them, and all zones will be reset to contain air mix as on roundstart. This may require any atmos-based generators to shut down. Do not use unless the map is suffering serious atmospheric issues due to grief or bug.", "Full Atmosphere Reboot", "No", "Yes") == "No") return SSstatistics.add_field_details("admin_verb","FA") log_and_message_admins("Full atmosphere reset initiated by [usr].") - to_world("Initiating restart of atmosphere. The server may lag a bit.") + to_world(SPAN_DANGER("Initiating restart of atmosphere. The server may lag a bit.")) sleep(10) var/current_time = world.timeofday - // Depower the supermatter, as it would quickly blow up once we remove all gases from the pipes. - for(var/obj/machinery/power/supermatter/S in SSmachines.machinery) - S.power = 0 - to_chat(usr, "\[1/5\] - Supermatter depowered") + var/list/steps = sortTim(decls_repository.get_decls_of_subtype_unassociated(/decl/atmos_grief_fix_step), /proc/cmp_decl_sort_value_asc) + var/step_count = length(steps) + for(var/step_index in 1 to length(step_count)) + var/decl/atmos_grief_fix_step/fix_step = steps[step_index] + to_chat(usr, "\[[step_index]/[step_count]\] - [fix_step.name].") + fix_step.act() + to_world(SPAN_DANGER("Atmosphere restart completed in [(world.timeofday - current_time)/(1 SECOND)] seconds.")) +/decl/atmos_grief_fix_step + abstract_type = /decl/atmos_grief_fix_step + var/name + +/decl/atmos_grief_fix_step/proc/act() + return + +/decl/atmos_grief_fix_step/purge_pipenets + name = "All pipenets purged of gas" + sort_order = 1 + +/decl/atmos_grief_fix_step/purge_pipenets/act() // Remove all gases from all pipenets - for(var/net in SSmachines.pipenets) - var/datum/pipe_network/PN = net + for(var/datum/pipe_network/PN as anything in SSmachines.pipenets) for(var/datum/gas_mixture/G in PN.gases) - G.gas = list() + G.gas.Cut() G.update_values() - to_chat(usr, "\[2/5\] - All pipenets purged of gas.") +/decl/atmos_grief_fix_step/delete_zones + name = "All ZAS Zones removed" + sort_order = 2 +/decl/atmos_grief_fix_step/delete_zones/act() // Delete all zones. for(var/zone/Z in SSair.zones) Z.c_invalidate() - to_chat(usr, "\[3/5\] - All ZAS Zones removed.") +/decl/atmos_grief_fix_step/reset_turfs + name = "All turfs reset to roundstart values" + sort_order = 3 +/decl/atmos_grief_fix_step/reset_turfs/act() var/list/unsorted_overlays = list() var/list/all_gasses = decls_repository.get_decls_of_subtype(/decl/material/gas) for(var/id in all_gasses) @@ -41,12 +61,11 @@ for(var/turf/T in world) T.air = null - T.overlays.Remove(unsorted_overlays) T.zone = null - to_chat(usr, "\[4/5\] - All turfs reset to roundstart values.") +/decl/atmos_grief_fix_step/reboot_zas + name = "ZAS Rebooted" + sort_order = 4 +/decl/atmos_grief_fix_step/reboot_zas/act() SSair.reboot() - - to_chat(usr, "\[5/5\] - ZAS Rebooted") - to_world("Atmosphere restart completed in [(world.timeofday - current_time)/10] seconds.") diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 6638c344791c..dd3f47479406 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -150,7 +150,6 @@ var/global/list/debug_verbs = list ( /client/proc/hide_debug_verbs, /client/proc/testZAScolors, /client/proc/testZAScolors_remove, - /datum/admins/proc/setup_supermatter, /datum/admins/proc/setup_fusion, /client/proc/atmos_toggle_debug, /client/proc/spawn_tanktransferbomb, diff --git a/code/modules/admin/view_variables/helpers.dm b/code/modules/admin/view_variables/helpers.dm index 8e30b30b4d7e..959b1b0c0119 100644 --- a/code/modules/admin/view_variables/helpers.dm +++ b/code/modules/admin/view_variables/helpers.dm @@ -37,7 +37,6 @@ return ..() + {" - @@ -50,6 +49,9 @@ + + + diff --git a/code/modules/admin/view_variables/topic.dm b/code/modules/admin/view_variables/topic.dm index f1118e682c96..09d5d1cc8c14 100644 --- a/code/modules/admin/view_variables/topic.dm +++ b/code/modules/admin/view_variables/topic.dm @@ -1,4 +1,3 @@ - /client/proc/view_var_Topic(href, href_list, hsrc) //This should all be moved over to datum/admins/Topic() or something ~Carn if( (usr.client != src) || !src.holder ) @@ -97,17 +96,6 @@ src.holder.show_player_panel(victim) href_list["datumrefresh"] = href_list["mob_player_panel"] - else if(href_list["give_spell"]) - if(!check_rights(R_ADMIN|R_FUN)) return - - var/mob/victim = locate(href_list["give_spell"]) - if(!istype(victim)) - to_chat(usr, "This can only be used on instances of type /mob") - return - - src.give_spell(victim) - href_list["datumrefresh"] = href_list["give_spell"] - else if(href_list["godmode"]) if(!check_rights(R_REJUVENATE)) return @@ -690,6 +678,33 @@ item.set_material(new_material.type) to_chat(usr, "Set material of [item] to [item.get_material()].") + else if(href_list["give_ability"]) + var/mob/target = locate(href_list["give_ability"]) + if(!istype(target) || QDELETED(target)) + to_chat(usr, "Mob no longer exists.") + else + var/list/abilities = decls_repository.get_decls_of_type_unassociated(/decl/ability) + abilities = abilities.Copy() + abilities -= target.get_all_abilities() + var/decl/ability/ability = input(usr, "Which ability do you wish to grant?", "Give Ability") as null|anything in abilities + if(istype(ability) && !QDELETED(usr) && !QDELETED(target)) + if(target.add_ability(ability.type)) + log_and_message_admins("has given [ability] to [key_name(target)].") + else + to_chat(usr, SPAN_WARNING("Failed to give [ability] to [target]!")) + + else if(href_list["remove_ability"]) + var/mob/target = locate(href_list["remove_ability"]) + if(!istype(target) || QDELETED(target)) + to_chat(usr, "Mob no longer exists.") + else + var/decl/ability/ability = input(usr, "Which ability do you wish to remove?", "Remove Ability") as null|anything in target.get_all_abilities() + if(istype(ability) && !QDELETED(usr) && !QDELETED(target)) + if(target.remove_ability(ability.type)) + log_and_message_admins("has removed [ability] from [key_name(target)].") + else + to_chat(usr, SPAN_WARNING("Failed to remove [ability] from [target]!")) + if(href_list["datumrefresh"]) var/datum/datum_to_refresh = locate(href_list["datumrefresh"]) if(istype(datum_to_refresh, /datum) || istype(datum_to_refresh, /client)) diff --git a/code/modules/atmospherics/components/binary_devices/pump.dm b/code/modules/atmospherics/components/binary_devices/pump.dm index a0b05c844cd7..156e19f2f39a 100644 --- a/code/modules/atmospherics/components/binary_devices/pump.dm +++ b/code/modules/atmospherics/components/binary_devices/pump.dm @@ -213,6 +213,7 @@ Thus, the two variables affect pump operation are set in New(): /decl/interaction_handler/binary_pump_toggle name = "Switch On/Off" expected_target_type = /obj/machinery/atmospherics/binary/pump + examine_desc = "turn $TARGET_THEM$ on or off" /decl/interaction_handler/binary_pump_toggle/invoked(atom/target, mob/user, obj/item/prop) var/obj/machinery/atmospherics/binary/pump/P = target diff --git a/code/modules/bodytype/_bodytype.dm b/code/modules/bodytype/_bodytype.dm index af6100a8d0a6..7bb3afd74473 100644 --- a/code/modules/bodytype/_bodytype.dm +++ b/code/modules/bodytype/_bodytype.dm @@ -41,10 +41,14 @@ var/global/list/bodytypes_by_category = list() var/ignited_icon = 'icons/mob/OnFire.dmi' /// Drawn over mob bodyparts when they are surgically open/retracted. var/surgery_overlay_icon = 'icons/mob/surgery.dmi' + /// Icon to use when walking across snow, sand or mud. Separate to bloody footprints for now. + var/footprints_icon = 'icons/mob/footprints/footprints.dmi' /// Used to retrieve bodytypes by pronoun type in get_bodytype_by_pronouns() var/associated_gender /// Appearance/display related features. var/appearance_flags = 0 + // Preview in prefs positioning. If null, uses defaults set on a static list in preferences.dm. + var/list/character_preview_screen_locs /// What noun is used when filing your nails? var/nail_noun /// What tech levels should limbs of this type use/need? @@ -845,3 +849,6 @@ var/global/list/limbs_with_nails = list( /decl/bodytype/proc/get_movement_slowdown(var/mob/living/human/H) return movement_slowdown + +/decl/bodytype/proc/get_footprints_icon() + return footprints_icon diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index 76f96bf08661..5a4b8a075400 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -170,7 +170,7 @@ var/global/list/localhost_addresses = list( holder.owner = src handle_staff_login() - //preferences datum - also holds some persistant data for the client (because we may as well keep these datums to a minimum) + //preferences datum - also holds some persistent data for the client (because we may as well keep these datums to a minimum) prefs = SScharacter_setup.preferences_datums[ckey] if(!prefs) prefs = new /datum/preferences(src) diff --git a/code/modules/client/preference_setup/global/01_ui.dm b/code/modules/client/preference_setup/global/01_ui.dm index de5797080c49..932214653179 100644 --- a/code/modules/client/preference_setup/global/01_ui.dm +++ b/code/modules/client/preference_setup/global/01_ui.dm @@ -1,16 +1,17 @@ var/global/list/valid_icon_sizes = list(32, 48, 64, 96, 128) /datum/preferences - var/clientfps = 0 - var/ooccolor = "#010000" //Whatever this is set to acts as 'reset' color and is thus unusable as an actual custom color - var/icon_size = 64 + var/clientfps = 0 + var/ooccolor = "#010000" //Whatever this is set to acts as 'reset' color and is thus unusable as an actual custom color + var/icon_size = 64 var/UI_style - var/UI_style_alpha = 255 - var/UI_style_color = COLOR_WHITE - var/UI_mouseover_alpha = 255 - var/UI_mouseover_color = COLOR_AMBER + var/UI_style_alpha = 255 + var/UI_style_color = "#8a8872" + var/UI_style_highlight_color = "#545e78" + var/UI_mouseover_alpha = 255 + var/UI_mouseover_color = COLOR_AMBER //Style for popup tooltips - var/tooltip_style = "Midnight" + var/tooltip_style = "Midnight" /datum/category_item/player_setup_item/player_global/ui name = "UI" @@ -25,26 +26,28 @@ var/global/list/valid_icon_sizes = list(32, 48, 64, 96, 128) if(ui_style) pref.UI_style = ui_style.type - pref.icon_size = R.read("icon_size") - pref.UI_mouseover_color = R.read("UI_mouseover_color") - pref.UI_mouseover_alpha = R.read("UI_mouseover_alpha") - pref.UI_style_color = R.read("UI_style_color") - pref.UI_style_alpha = R.read("UI_style_alpha") - pref.ooccolor = R.read("ooccolor") - pref.clientfps = R.read("clientfps") + pref.icon_size = R.read("icon_size") + pref.UI_mouseover_color = R.read("UI_mouseover_color") + pref.UI_mouseover_alpha = R.read("UI_mouseover_alpha") + pref.UI_style_color = R.read("UI_style_color") + pref.UI_style_highlight_color = R.read("UI_style_highlight_color") + pref.UI_style_alpha = R.read("UI_style_alpha") + pref.ooccolor = R.read("ooccolor") + pref.clientfps = R.read("clientfps") /datum/category_item/player_setup_item/player_global/ui/save_preferences(datum/pref_record_writer/W) var/decl/ui_style/ui_style = GET_DECL(pref.UI_style) W.write("UI_style", ui_style.uid) - W.write("icon_size", pref.icon_size) - W.write("UI_mouseover_color", pref.UI_mouseover_color) - W.write("UI_mouseover_alpha", pref.UI_mouseover_alpha) - W.write("UI_style_color", pref.UI_style_color) - W.write("UI_style_alpha", pref.UI_style_alpha) - W.write("ooccolor", pref.ooccolor) - W.write("clientfps", pref.clientfps) + W.write("icon_size", pref.icon_size) + W.write("UI_mouseover_color", pref.UI_mouseover_color) + W.write("UI_mouseover_alpha", pref.UI_mouseover_alpha) + W.write("UI_style_color", pref.UI_style_color) + W.write("UI_style_highlight_color", pref.UI_style_highlight_color) + W.write("UI_style_alpha", pref.UI_style_alpha) + W.write("ooccolor", pref.ooccolor) + W.write("clientfps", pref.clientfps) /datum/category_item/player_setup_item/player_global/ui/sanitize_preferences() @@ -52,13 +55,14 @@ var/global/list/valid_icon_sizes = list(32, 48, 64, 96, 128) for(var/decl/ui_style/style in get_ui_styles()) all_ui_style_types |= style.type - pref.UI_style = sanitize_inlist(pref.UI_style, all_ui_style_types, all_ui_style_types[1]) - pref.UI_mouseover_color = sanitize_hexcolor(pref.UI_mouseover_color, initial(pref.UI_mouseover_color)) - pref.UI_mouseover_alpha = sanitize_integer(pref.UI_mouseover_alpha, 0, 255, initial(pref.UI_mouseover_alpha)) - pref.UI_style_color = sanitize_hexcolor(pref.UI_style_color, initial(pref.UI_style_color)) - pref.UI_style_alpha = sanitize_integer(pref.UI_style_alpha, 0, 255, initial(pref.UI_style_alpha)) - pref.ooccolor = sanitize_hexcolor(pref.ooccolor, initial(pref.ooccolor)) - pref.clientfps = sanitize_integer(pref.clientfps, CLIENT_MIN_FPS, CLIENT_MAX_FPS, initial(pref.clientfps)) + pref.UI_style = sanitize_inlist(pref.UI_style, all_ui_style_types, all_ui_style_types[1]) + pref.UI_mouseover_color = sanitize_hexcolor(pref.UI_mouseover_color, initial(pref.UI_mouseover_color)) + pref.UI_mouseover_alpha = sanitize_integer(pref.UI_mouseover_alpha, 0, 255, initial(pref.UI_mouseover_alpha)) + pref.UI_style_color = sanitize_hexcolor(pref.UI_style_color, initial(pref.UI_style_color)) + pref.UI_style_highlight_color = sanitize_hexcolor(pref.UI_style_highlight_color, initial(pref.UI_style_highlight_color)) + pref.UI_style_alpha = sanitize_integer(pref.UI_style_alpha, 0, 255, initial(pref.UI_style_alpha)) + pref.ooccolor = sanitize_hexcolor(pref.ooccolor, initial(pref.ooccolor)) + pref.clientfps = sanitize_integer(pref.clientfps, CLIENT_MIN_FPS, CLIENT_MAX_FPS, initial(pref.clientfps)) if(!isnum(pref.icon_size)) pref.icon_size = initial(pref.icon_size) @@ -71,6 +75,11 @@ var/global/list/valid_icon_sizes = list(32, 48, 64, 96, 128) . += "
__
" . += "reset" . += "" + . += "UI Highlight" + . += "[pref.UI_style_highlight_color]" + . += "
__
" + . += "reset" + . += "" . += "UI Opacity" . += "[pref.UI_style_alpha]" . += "reset" @@ -111,6 +120,12 @@ var/global/list/valid_icon_sizes = list(32, 48, 64, 96, 128) pref.UI_style_color = UI_style_color_new return TOPIC_REFRESH + else if(href_list["select_highlight_color"]) + var/UI_style_highlight_color_new = input(user, "Choose UI highlight color, dark colors are not recommended!", "Global Preference", pref.UI_style_highlight_color) as color|null + if(isnull(UI_style_highlight_color_new) || !CanUseTopic(user)) return TOPIC_NOACTION + pref.UI_style_highlight_color = UI_style_highlight_color_new + return TOPIC_REFRESH + else if(href_list["select_alpha"]) var/UI_style_alpha_new = input(user, "Select UI alpha (transparency) level, between 50 and 255.", "Global Preference", pref.UI_style_alpha) as num|null if(isnull(UI_style_alpha_new) || (UI_style_alpha_new < 50 || UI_style_alpha_new > 255) || !CanUseTopic(user)) return TOPIC_NOACTION @@ -146,6 +161,8 @@ var/global/list/valid_icon_sizes = list(32, 48, 64, 96, 128) switch(href_list["reset"]) if("ui") pref.UI_style_color = initial(pref.UI_style_color) + if("highlight") + pref.UI_style_highlight_color = initial(pref.UI_style_highlight_color) if("alpha") pref.UI_style_alpha = initial(pref.UI_style_alpha) if("mouseover_color") diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index ad87174808b3..b5c1c2a992a8 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -500,7 +500,7 @@ var/global/list/time_prefs_fixed = list() key_bindings = deepCopyList(global.hotkey_keybinding_list_by_key) if(istype(client)) - // Preferences datum - also holds some persistant data for the client (because we may as well keep these datums to a minimum). + // Preferences datum - also holds some persistent data for the client (because we may as well keep these datums to a minimum). SScharacter_setup.preferences_datums[client.ckey] = src setup() diff --git a/code/modules/client/ui_styles/_helpers.dm b/code/modules/client/ui_styles/_helpers.dm index 83ceb172a415..97d99ab4f2fa 100644 --- a/code/modules/client/ui_styles/_helpers.dm +++ b/code/modules/client/ui_styles/_helpers.dm @@ -6,23 +6,7 @@ LAZYADD(., ui) /proc/get_default_ui_icon(ui_key) - var/static/list/default_icons = list( - UI_ICON_ATTACK = 'icons/mob/screen/styles/midnight/attack_selector.dmi', - UI_ICON_FIRE_INTENT = 'icons/mob/screen/styles/midnight/fire_intent.dmi', - UI_ICON_HANDS = 'icons/mob/screen/styles/midnight/hands.dmi', - UI_ICON_HEALTH = 'icons/mob/screen/styles/health.dmi', - UI_ICON_CRIT_MARKER = 'icons/mob/screen/styles/crit_markers.dmi', - UI_ICON_HYDRATION = 'icons/mob/screen/styles/hydration.dmi', - UI_ICON_INTERACTION = 'icons/mob/screen/styles/midnight/interaction.dmi', - UI_ICON_INTERNALS = 'icons/mob/screen/styles/internals.dmi', - UI_ICON_INVENTORY = 'icons/mob/screen/styles/midnight/inventory.dmi', - UI_ICON_MOVEMENT = 'icons/mob/screen/styles/midnight/movement.dmi', - UI_ICON_NUTRITION = 'icons/mob/screen/styles/nutrition.dmi', - UI_ICON_STATUS = 'icons/mob/screen/styles/status.dmi', - UI_ICON_UP_HINT = 'icons/mob/screen/styles/midnight/uphint.dmi', - UI_ICON_ZONE_SELECT = 'icons/mob/screen/styles/midnight/zone_selector.dmi' - ) - return istext(ui_key) ? default_icons[ui_key] : null + return get_ui_icon(global.using_map.default_ui_style, ui_key) /proc/get_ui_icon(ui_style, ui_key) var/decl/ui_style/style = GET_DECL(ui_style) diff --git a/code/modules/client/ui_styles/_ui_style.dm b/code/modules/client/ui_styles/_ui_style.dm index 1a5885cfac67..0e78ae2e832b 100644 --- a/code/modules/client/ui_styles/_ui_style.dm +++ b/code/modules/client/ui_styles/_ui_style.dm @@ -26,6 +26,8 @@ ) /// A subset of UI keys to icon files used to override the above. var/list/override_icons + var/use_overlay_color = FALSE + var/use_ui_color = FALSE /decl/ui_style/Initialize() for(var/ui_key in override_icons) @@ -49,8 +51,13 @@ var/list/remaining_states = get_states_in_icon(check_icon) for(var/check_state in checking_states) remaining_states -= check_state - if(!check_state_in_icon(check_state, check_icon)) + if(check_state_in_icon(check_state, check_icon)) + check_state = "[check_state]-overlay" + if(check_state_in_icon(check_state, check_icon)) + remaining_states -= check_state + else missing_states |= check_state + if(length(remaining_states)) . += "icon [check_icon] for key [ui_key] has extraneous states: '[jointext(remaining_states, "', '")]'" if(length(missing_states)) diff --git a/code/modules/client/ui_styles/ui_style_subtypes.dm b/code/modules/client/ui_styles/ui_style_subtypes.dm index cff4d996c43b..7b1f311ebd71 100644 --- a/code/modules/client/ui_styles/ui_style_subtypes.dm +++ b/code/modules/client/ui_styles/ui_style_subtypes.dm @@ -7,68 +7,97 @@ name = "Orange" uid = "ui_style_orange" override_icons = list( - UI_ICON_ATTACK = 'icons/mob/screen/styles/orange/attack_selector.dmi', - UI_ICON_FIRE_INTENT = 'icons/mob/screen/styles/orange/fire_intent.dmi', - UI_ICON_HANDS = 'icons/mob/screen/styles/orange/hands.dmi', - UI_ICON_INTERACTION = 'icons/mob/screen/styles/orange/interaction.dmi', - UI_ICON_INVENTORY = 'icons/mob/screen/styles/orange/inventory.dmi', - UI_ICON_MOVEMENT = 'icons/mob/screen/styles/orange/movement.dmi', - UI_ICON_UP_HINT = 'icons/mob/screen/styles/orange/uphint.dmi', - UI_ICON_ZONE_SELECT = 'icons/mob/screen/styles/orange/zone_selector.dmi' + (UI_ICON_ATTACK) = 'icons/mob/screen/styles/orange/attack_selector.dmi', + (UI_ICON_FIRE_INTENT) = 'icons/mob/screen/styles/orange/fire_intent.dmi', + (UI_ICON_HANDS) = 'icons/mob/screen/styles/orange/hands.dmi', + (UI_ICON_INTERACTION) = 'icons/mob/screen/styles/orange/interaction.dmi', + (UI_ICON_INVENTORY) = 'icons/mob/screen/styles/orange/inventory.dmi', + (UI_ICON_MOVEMENT) = 'icons/mob/screen/styles/orange/movement.dmi', + (UI_ICON_UP_HINT) = 'icons/mob/screen/styles/orange/uphint.dmi', + (UI_ICON_ZONE_SELECT) = 'icons/mob/screen/styles/orange/zone_selector.dmi' ) /decl/ui_style/old name = "Old" uid = "ui_style_old" override_icons = list( - UI_ICON_ATTACK = 'icons/mob/screen/styles/old/attack_selector.dmi', - UI_ICON_FIRE_INTENT = 'icons/mob/screen/styles/old/fire_intent.dmi', - UI_ICON_HANDS = 'icons/mob/screen/styles/old/hands.dmi', - UI_ICON_INTERACTION = 'icons/mob/screen/styles/old/interaction.dmi', - UI_ICON_INVENTORY = 'icons/mob/screen/styles/old/inventory.dmi', - UI_ICON_MOVEMENT = 'icons/mob/screen/styles/old/movement.dmi', - UI_ICON_UP_HINT = 'icons/mob/screen/styles/old/uphint.dmi', - UI_ICON_ZONE_SELECT = 'icons/mob/screen/styles/old/zone_selector.dmi' + (UI_ICON_ATTACK) = 'icons/mob/screen/styles/old/attack_selector.dmi', + (UI_ICON_FIRE_INTENT) = 'icons/mob/screen/styles/old/fire_intent.dmi', + (UI_ICON_HANDS) = 'icons/mob/screen/styles/old/hands.dmi', + (UI_ICON_INTERACTION) = 'icons/mob/screen/styles/old/interaction.dmi', + (UI_ICON_INVENTORY) = 'icons/mob/screen/styles/old/inventory.dmi', + (UI_ICON_MOVEMENT) = 'icons/mob/screen/styles/old/movement.dmi', + (UI_ICON_UP_HINT) = 'icons/mob/screen/styles/old/uphint.dmi', + (UI_ICON_ZONE_SELECT) = 'icons/mob/screen/styles/old/zone_selector.dmi' ) /decl/ui_style/old_noborder name = "Old (no border)" uid = "ui_style_old_noborder" override_icons = list( - UI_ICON_ATTACK = 'icons/mob/screen/styles/old/attack_selector.dmi', - UI_ICON_FIRE_INTENT = 'icons/mob/screen/styles/old/fire_intent.dmi', - UI_ICON_HANDS = 'icons/mob/screen/styles/old/hands.dmi', - UI_ICON_INTERACTION = 'icons/mob/screen/styles/old/interaction.dmi', - UI_ICON_INVENTORY = 'icons/mob/screen/styles/old_noborder/inventory.dmi', - UI_ICON_MOVEMENT = 'icons/mob/screen/styles/old/movement.dmi', - UI_ICON_UP_HINT = 'icons/mob/screen/styles/old_noborder/uphint.dmi', - UI_ICON_ZONE_SELECT = 'icons/mob/screen/styles/old_noborder/zone_selector.dmi' + (UI_ICON_ATTACK) = 'icons/mob/screen/styles/old/attack_selector.dmi', + (UI_ICON_FIRE_INTENT) = 'icons/mob/screen/styles/old/fire_intent.dmi', + (UI_ICON_HANDS) = 'icons/mob/screen/styles/old/hands.dmi', + (UI_ICON_INTERACTION) = 'icons/mob/screen/styles/old/interaction.dmi', + (UI_ICON_INVENTORY) = 'icons/mob/screen/styles/old_noborder/inventory.dmi', + (UI_ICON_MOVEMENT) = 'icons/mob/screen/styles/old/movement.dmi', + (UI_ICON_UP_HINT) = 'icons/mob/screen/styles/old_noborder/uphint.dmi', + (UI_ICON_ZONE_SELECT) = 'icons/mob/screen/styles/old_noborder/zone_selector.dmi' ) /decl/ui_style/white name = "White" uid = "ui_style_white" override_icons = list( - UI_ICON_ATTACK = 'icons/mob/screen/styles/white/attack_selector.dmi', - UI_ICON_FIRE_INTENT = 'icons/mob/screen/styles/white/fire_intent.dmi', - UI_ICON_HANDS = 'icons/mob/screen/styles/white/hands.dmi', - UI_ICON_INTERACTION = 'icons/mob/screen/styles/white/interaction.dmi', - UI_ICON_INVENTORY = 'icons/mob/screen/styles/white/inventory.dmi', - UI_ICON_MOVEMENT = 'icons/mob/screen/styles/white/movement.dmi', - UI_ICON_UP_HINT = 'icons/mob/screen/styles/white/uphint.dmi', - UI_ICON_ZONE_SELECT = 'icons/mob/screen/styles/white/zone_selector.dmi' + (UI_ICON_ATTACK) = 'icons/mob/screen/styles/white/attack_selector.dmi', + (UI_ICON_FIRE_INTENT) = 'icons/mob/screen/styles/white/fire_intent.dmi', + (UI_ICON_HANDS) = 'icons/mob/screen/styles/white/hands.dmi', + (UI_ICON_INTERACTION) = 'icons/mob/screen/styles/white/interaction.dmi', + (UI_ICON_INVENTORY) = 'icons/mob/screen/styles/white/inventory.dmi', + (UI_ICON_MOVEMENT) = 'icons/mob/screen/styles/white/movement.dmi', + (UI_ICON_UP_HINT) = 'icons/mob/screen/styles/white/uphint.dmi', + (UI_ICON_ZONE_SELECT) = 'icons/mob/screen/styles/white/zone_selector.dmi' ) + use_overlay_color = TRUE + use_ui_color = TRUE /decl/ui_style/minimalist name = "Minimalist" uid = "ui_style_minimalist" override_icons = list( - UI_ICON_ATTACK = 'icons/mob/screen/styles/minimalist/attack_selector.dmi', - UI_ICON_FIRE_INTENT = 'icons/mob/screen/styles/minimalist/fire_intent.dmi', - UI_ICON_HANDS = 'icons/mob/screen/styles/minimalist/hands.dmi', - UI_ICON_INTERACTION = 'icons/mob/screen/styles/minimalist/interaction.dmi', - UI_ICON_INVENTORY = 'icons/mob/screen/styles/minimalist/inventory.dmi', - UI_ICON_MOVEMENT = 'icons/mob/screen/styles/minimalist/movement.dmi', - UI_ICON_UP_HINT = 'icons/mob/screen/styles/minimalist/uphint.dmi', - UI_ICON_ZONE_SELECT = 'icons/mob/screen/styles/minimalist/zone_selector.dmi' + (UI_ICON_ATTACK) = 'icons/mob/screen/styles/minimalist/attack_selector.dmi', + (UI_ICON_FIRE_INTENT) = 'icons/mob/screen/styles/minimalist/fire_intent.dmi', + (UI_ICON_HANDS) = 'icons/mob/screen/styles/minimalist/hands.dmi', + (UI_ICON_INTERACTION) = 'icons/mob/screen/styles/minimalist/interaction.dmi', + (UI_ICON_INVENTORY) = 'icons/mob/screen/styles/minimalist/inventory.dmi', + (UI_ICON_MOVEMENT) = 'icons/mob/screen/styles/minimalist/movement.dmi', + (UI_ICON_UP_HINT) = 'icons/mob/screen/styles/minimalist/uphint.dmi', + (UI_ICON_ZONE_SELECT) = 'icons/mob/screen/styles/minimalist/zone_selector.dmi' ) + use_overlay_color = TRUE + use_ui_color = TRUE + +/decl/ui_style/underworld + name = "Underworld" + uid = "ui_style_underworld" + restricted = FALSE + icons = list( + (UI_ICON_ATTACK) = 'icons/mob/screen/styles/underworld/attack_selector.dmi', + (UI_ICON_FIRE_INTENT) = 'icons/mob/screen/styles/underworld/fire_intent.dmi', + (UI_ICON_HANDS) = 'icons/mob/screen/styles/underworld/hands.dmi', + (UI_ICON_HEALTH) = 'icons/mob/screen/styles/health.dmi', + (UI_ICON_CRIT_MARKER) = 'icons/mob/screen/styles/crit_markers.dmi', + (UI_ICON_HYDRATION) = 'icons/mob/screen/styles/hydration.dmi', + (UI_ICON_INTERACTION) = 'icons/mob/screen/styles/underworld/interaction.dmi', + (UI_ICON_INTERNALS) = 'icons/mob/screen/styles/internals.dmi', + (UI_ICON_INVENTORY) = 'icons/mob/screen/styles/underworld/inventory.dmi', + (UI_ICON_MOVEMENT) = 'icons/mob/screen/styles/underworld/movement.dmi', + (UI_ICON_NUTRITION) = 'icons/mob/screen/styles/nutrition.dmi', + (UI_ICON_STATUS_FIRE) = 'icons/mob/screen/styles/status_fire.dmi', + (UI_ICON_STATUS) = 'icons/mob/screen/styles/status.dmi', + (UI_ICON_UP_HINT) = 'icons/mob/screen/styles/underworld/uphint.dmi', + (UI_ICON_ZONE_SELECT) = 'icons/mob/screen/styles/underworld/zone_selector.dmi', + (UI_ICON_CHARGE) = 'icons/mob/screen/styles/charge.dmi' + ) + use_overlay_color = TRUE + use_ui_color = TRUE diff --git a/code/modules/clothing/_clothing.dm b/code/modules/clothing/_clothing.dm index 744bcdb78135..b51dfb2f51e3 100644 --- a/code/modules/clothing/_clothing.dm +++ b/code/modules/clothing/_clothing.dm @@ -450,8 +450,9 @@ /decl/interaction_handler/clothing_set_sensors name = "Set Sensors Level" expected_target_type = /obj/item/clothing + examine_desc = "adjust vitals sensors" /decl/interaction_handler/clothing_set_sensors/invoked(atom/target, mob/user, obj/item/prop) - var/obj/item/clothing/U = target - U.set_sensors(user) + var/obj/item/clothing/clothes = target + clothes.set_sensors(user) diff --git a/code/modules/clothing/clothing_state/clothing_state_buttons.dm b/code/modules/clothing/clothing_state/clothing_state_buttons.dm index 74c9fe7e4442..05b531f26390 100644 --- a/code/modules/clothing/clothing_state/clothing_state_buttons.dm +++ b/code/modules/clothing/clothing_state/clothing_state_buttons.dm @@ -7,6 +7,7 @@ /decl/interaction_handler/clothing_toggle/buttons name = "Toggle Open Or Closed" state_decl_type = /decl/clothing_state_modifier/buttons + examine_desc = "fasten or undo $TARGET_THEIR$ buttons" /obj/item/clothing/proc/toggle_buttons_verb() diff --git a/code/modules/clothing/clothing_state/clothing_state_hood.dm b/code/modules/clothing/clothing_state/clothing_state_hood.dm index 281174461bd0..81ddc6301dca 100644 --- a/code/modules/clothing/clothing_state/clothing_state_hood.dm +++ b/code/modules/clothing/clothing_state/clothing_state_hood.dm @@ -7,6 +7,7 @@ /decl/interaction_handler/clothing_toggle/hood name = "Adjust Hood" state_decl_type = /decl/clothing_state_modifier/hood + examine_desc = "push the hood up or down" /obj/item/clothing/proc/toggle_hood_verb() diff --git a/code/modules/clothing/clothing_state/clothing_state_rolled.dm b/code/modules/clothing/clothing_state/clothing_state_rolled.dm index 84d9f8ade842..f368481918f8 100644 --- a/code/modules/clothing/clothing_state/clothing_state_rolled.dm +++ b/code/modules/clothing/clothing_state/clothing_state_rolled.dm @@ -8,6 +8,7 @@ /decl/interaction_handler/clothing_toggle/rolled_down name = "Roll Up Or Down" state_decl_type = /decl/clothing_state_modifier/rolled_down + examine_desc = "roll $TARGET_THEM$ up or down" /obj/item/clothing/proc/toggle_rolled_verb() diff --git a/code/modules/clothing/clothing_state/clothing_state_sleeves.dm b/code/modules/clothing/clothing_state/clothing_state_sleeves.dm index 7356c78e4041..33a099b4194a 100644 --- a/code/modules/clothing/clothing_state/clothing_state_sleeves.dm +++ b/code/modules/clothing/clothing_state/clothing_state_sleeves.dm @@ -7,6 +7,7 @@ /decl/interaction_handler/clothing_toggle/rolled_sleeves name = "Roll Sleeves Up Or Down" state_decl_type = /decl/clothing_state_modifier/rolled_sleeves + examine_desc = "roll $TARGET_THEIR$ sleeves up or down" /obj/item/clothing/proc/toggle_sleeves_verb() diff --git a/code/modules/clothing/clothing_state/clothing_state_tucked.dm b/code/modules/clothing/clothing_state/clothing_state_tucked.dm index 41714c01f868..dbfaaecf3be0 100644 --- a/code/modules/clothing/clothing_state/clothing_state_tucked.dm +++ b/code/modules/clothing/clothing_state/clothing_state_tucked.dm @@ -7,6 +7,7 @@ /decl/interaction_handler/clothing_toggle/tucked_in name = "Tuck In Or Untuck" state_decl_type = /decl/clothing_state_modifier/tucked_in + examine_desc = "tuck $TARGET_THEM$ in or out" /obj/item/clothing/proc/toggle_tucked_verb() diff --git a/code/modules/clothing/clothing_state/clothing_state_untied.dm b/code/modules/clothing/clothing_state/clothing_state_untied.dm index 98313e2441d8..759b60015048 100644 --- a/code/modules/clothing/clothing_state/clothing_state_untied.dm +++ b/code/modules/clothing/clothing_state/clothing_state_untied.dm @@ -7,6 +7,7 @@ /decl/interaction_handler/clothing_toggle/untied name = "Tie Or Untie" state_decl_type = /decl/clothing_state_modifier/untied + examine_desc = "tie or untie $TARGET_THEM$" /obj/item/clothing/proc/toggle_untied_verb() diff --git a/code/modules/clothing/neck/necklace/__necklace.dm b/code/modules/clothing/neck/necklace/__necklace.dm index a6e680313b6f..d94e49bf2675 100644 --- a/code/modules/clothing/neck/necklace/__necklace.dm +++ b/code/modules/clothing/neck/necklace/__necklace.dm @@ -67,6 +67,7 @@ /decl/interaction_handler/remove_pendant name = "Remove Pendant" expected_target_type = /obj/item/clothing/neck/necklace + examine_desc = "remove $TARGET_THEIR$ pendant" /decl/interaction_handler/remove_pendant/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/clothing/neck/necklace/necklace = target diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm index 6aedbb3edaf6..bd4284407d85 100644 --- a/code/modules/clothing/shoes/_shoes.dm +++ b/code/modules/clothing/shoes/_shoes.dm @@ -24,7 +24,7 @@ var/hidden_item_max_w_class = ITEM_SIZE_SMALL var/obj/item/hidden_item = null var/shine = -1 // if material should apply shine overlay. Set to -1 for it to not do that - + var/footprint_icon = 'icons/mob/footprints/footprints.dmi' /// A multiplier applied to footstep volume. var/footstep_volume_mod = 1 /// A multiplier applied to footstep range. diff --git a/code/modules/clothing/suits/armor/_armor.dm b/code/modules/clothing/suits/armor/_armor.dm index 250c133ae7be..eef73b5c8fa4 100644 --- a/code/modules/clothing/suits/armor/_armor.dm +++ b/code/modules/clothing/suits/armor/_armor.dm @@ -12,7 +12,7 @@ /obj/item/handcuffs, /obj/item/gun/magnetic, /obj/item/clothing/head/helmet, - /obj/item/shield/buckler, + /obj/item/shield/crafted/buckler, /obj/item/bladed/knife, /obj/item/bladed/shortsword, /obj/item/bladed/longsword, diff --git a/code/modules/clothing/suits/armor/craftable.dm b/code/modules/clothing/suits/armor/craftable.dm index c73e38510fcb..824a7c5b553b 100644 --- a/code/modules/clothing/suits/armor/craftable.dm +++ b/code/modules/clothing/suits/armor/craftable.dm @@ -33,5 +33,5 @@ material = /decl/material/solid/gemstone/diamond /obj/item/clothing/suit/armor/crafted/gold material = /decl/material/solid/metal/gold -/obj/item/clothing/suit/armor/crafted/supermatter +/obj/item/clothing/suit/armor/crafted/exotic_matter material = /decl/material/solid/exotic_matter diff --git a/code/modules/clothing/suits/cloaks.dm b/code/modules/clothing/suits/cloaks.dm index dea74926342d..5888d3ec8329 100644 --- a/code/modules/clothing/suits/cloaks.dm +++ b/code/modules/clothing/suits/cloaks.dm @@ -1,15 +1,17 @@ -/obj/item/clothing/suit/cloak // A colorable cloak - name = "plain cloak" - desc = "A simple, bland cloak." - icon = 'icons/clothing/suits/cloaks/_cloak.dmi' - w_class = ITEM_SIZE_NORMAL - slot_flags = SLOT_OVER_BODY - allowed = list(/obj/item/tank/emergency/oxygen) - armor = list(ARMOR_MELEE = 0, ARMOR_BULLET = 0, ARMOR_LASER = 0,ARMOR_ENERGY = 0, ARMOR_BOMB = 0, ARMOR_BIO = 0, ARMOR_RAD = 0) - body_parts_covered = SLOT_UPPER_BODY|SLOT_LOWER_BODY|SLOT_ARMS|SLOT_LEGS - siemens_coefficient = 0.9 - accessory_slot = ACCESSORY_SLOT_OVER +// A colorable cloak +/obj/item/clothing/suit/cloak + name = "plain cloak" + desc = "A simple, bland cloak." + icon = 'icons/clothing/suits/cloaks/_cloak.dmi' + w_class = ITEM_SIZE_NORMAL + slot_flags = SLOT_OVER_BODY + allowed = list(/obj/item/tank/emergency/oxygen) + armor = null + body_parts_covered = SLOT_UPPER_BODY|SLOT_LOWER_BODY|SLOT_ARMS|SLOT_LEGS + siemens_coefficient = 0.9 + accessory_slot = ACCESSORY_SLOT_OVER accessory_visibility = ACCESSORY_VISIBILITY_ATTACHMENT + storage = /datum/storage/pockets/suit /obj/item/clothing/suit/cloak/on_update_icon() . = ..() diff --git a/code/modules/clothing/suits/jackets/_jacket.dm b/code/modules/clothing/suits/jackets/_jacket.dm index 3486a1c88e1a..abdd83bf2d43 100644 --- a/code/modules/clothing/suits/jackets/_jacket.dm +++ b/code/modules/clothing/suits/jackets/_jacket.dm @@ -8,6 +8,7 @@ slot_flags = SLOT_OVER_BODY w_class = ITEM_SIZE_NORMAL accessory_slot = ACCESSORY_SLOT_DECOR + storage = /datum/storage/pockets/suit valid_accessory_slots = list( ACCESSORY_SLOT_INSIGNIA, ACCESSORY_SLOT_ARMBAND, diff --git a/code/modules/codex/categories/category_phenomena.dm b/code/modules/codex/categories/category_phenomena.dm index f9777ed43fa8..e2637bf9e73d 100644 --- a/code/modules/codex/categories/category_phenomena.dm +++ b/code/modules/codex/categories/category_phenomena.dm @@ -4,16 +4,16 @@ /decl/codex_category/phenomena/Populate() - // This needs duplicate checking but I resent even having to spend time on spellcode. - var/list/spells = list() - for(var/thing in subtypesof(/spell)) - var/spell/spell = thing - if(!initial(spell.hidden_from_codex) && initial(spell.desc) && initial(spell.name)) - spells["[initial(spell.name)] (phenomena)"] = initial(spell.desc) - for(var/spell in spells) + var/list/abilities = list() + for(var/decl/ability/ability in decls_repository.get_decls_of_subtype_unassociated(/decl/ability)) + if(ability.hidden_from_codex || !ability.is_supernatural || !ability.desc) + continue + abilities["[ability.name] (phenomena)"] = ability.desc + + for(var/ability in abilities) var/datum/codex_entry/entry = new( - _display_name = spell, - _antag_text = spells[spell] + _display_name = ability, + _antag_text = abilities[ability] ) items |= entry.name . = ..() diff --git a/code/modules/codex/categories/category_substances.dm b/code/modules/codex/categories/category_substances.dm index e17ac5d3e666..e8c96d49b729 100644 --- a/code/modules/codex/categories/category_substances.dm +++ b/code/modules/codex/categories/category_substances.dm @@ -77,7 +77,7 @@ else if(mat.dissolves_in <= MAT_SOLVENT_MODERATE) solvent_needed = "a moderately strong solvent, like acetone" else if(mat.dissolves_in <= MAT_SOLVENT_STRONG) - solvent_needed = "a strong solvent, like sulphuric acid" + solvent_needed = "a strong solvent, like sulfuric acid" material_info += "
  • It can be dissolved with [solvent_needed] solvent, producing [english_list(chems)].
  • " if(mat.radioactivity) material_info += "
  • It is radioactive.
  • " diff --git a/code/modules/codex/codex_atom.dm b/code/modules/codex/codex_atom.dm index ebe02e59ab78..49d718ebbffe 100644 --- a/code/modules/codex/codex_atom.dm +++ b/code/modules/codex/codex_atom.dm @@ -36,5 +36,8 @@ /atom/examine(mob/user, distance, infix = "", suffix = "") . = ..() + var/decl/interaction_handler/handler = get_quick_interaction_handler(user) + if(handler) + to_chat(user, SPAN_NOTICE("Ctrl-click \the [src] while in your inventory to [lowertext(handler.name)].")) if(user?.get_preference_value(/datum/client_preference/inquisitive_examine) == PREF_ON && user.can_use_codex() && SScodex.get_codex_entry(get_codex_value(user))) to_chat(user, SPAN_NOTICE("The codex has relevant information available.")) diff --git a/code/modules/codex/entries/engineering.dm b/code/modules/codex/entries/engineering.dm index f6f9b4a7c007..f5e9ac99fa3d 100644 --- a/code/modules/codex/entries/engineering.dm +++ b/code/modules/codex/entries/engineering.dm @@ -1,20 +1,3 @@ -/datum/codex_entry/supermatter - associated_paths = list(/obj/machinery/power/supermatter) - mechanics_text = "When energized by a laser (or something hitting it), it emits radiation and heat. If the heat reaches above 7000 kelvin, it will send an alert and start taking damage. \ - After integrity falls to zero percent, it will delaminate, causing a massive explosion, station-wide radiation spikes, and hallucinations. \ - Supermatter reacts badly to oxygen in the atmosphere. It'll also heat up really quick if it is in vacuum.
    \ -
    \ - Supermatter cores are extremely dangerous to be close to, and requires protection to handle properly. The protection you will need is:
    \ - Optical meson scanners on your eyes, to prevent hallucinations when looking at the supermatter.
    \ - Radiation helmet and suit, as the supermatter is radioactive.
    \ -
    \ - Touching the supermatter will result in *instant death*, with no corpse left behind! You can drag the supermatter, but anything else will kill you. \ - It is advised to obtain a genetic backup before trying to drag it." - antag_text = "Exposing the supermatter to oxygen or vaccum will cause it to start rapidly heating up. Sabotaging the supermatter and making it explode will \ - cause a period of lag as the explosion is processed by the server, as well as irradiating the entire station and causing hallucinations to happen. \ - Wearing radiation equipment will protect you from most of the delamination effects sans explosion." - available_to_map_tech_level = MAP_TECH_LEVEL_SPACE - /datum/codex_entry/apc associated_paths = list(/obj/machinery/power/apc) mechanics_text = "An APC (Area Power Controller) regulates and supplies backup power for the area they are in. Their power channels are divided \ diff --git a/code/modules/codex/entries/guides.dm b/code/modules/codex/entries/guides.dm index 4ed96a6c0cf3..747a279d6915 100644 --- a/code/modules/codex/entries/guides.dm +++ b/code/modules/codex/entries/guides.dm @@ -601,10 +601,6 @@ /datum/codex_entry/guide/construction name = "Guide to Construction" -/datum/codex_entry/guide/supermatter - name = "Guide to Supermatter Engines" - available_to_map_tech_level = MAP_TECH_LEVEL_SPACE - /datum/codex_entry/guide/fusion name = "Guide to Fusion Reactors" available_to_map_tech_level = MAP_TECH_LEVEL_SPACE diff --git a/code/modules/codex/entries/guns.dm b/code/modules/codex/entries/guns.dm index eefcbd251aa4..ffdbb6755906 100644 --- a/code/modules/codex/entries/guns.dm +++ b/code/modules/codex/entries/guns.dm @@ -35,7 +35,7 @@ traits += "It's best fired with a two-handed grip." if(has_safety) - traits += "It has a safety switch. Control-Click it to toggle safety." + traits += "It has a safety switch, which can be toggled via ctrl-click or selecting Toggle Safety from the alt-click radial." if(is_secure_gun()) traits += "It's fitted with a secure registration chip. Swipe ID on it to register." diff --git a/code/modules/crafting/forging/bellows.dm b/code/modules/crafting/forging/bellows.dm new file mode 100644 index 000000000000..3402f4c2cfa7 --- /dev/null +++ b/code/modules/crafting/forging/bellows.dm @@ -0,0 +1,40 @@ +/obj/structure/working/bellows + name = "bellows" + desc = "An air pump used to improve the heat of a furnace." + icon = 'icons/obj/structures/forging/bellows.dmi' + obj_flags = OBJ_FLAG_ANCHORABLE | OBJ_FLAG_ROTATABLE + work_skill = SKILL_HAULING + var/decl/material/bellows_material = /decl/material/solid/organic/leather + +/obj/structure/working/bellows/Initialize() + bellows_material = GET_DECL(bellows_material) + . = ..() + +/obj/structure/working/bellows/on_update_icon() + . = ..() + underlays = list(overlay_image(icon, "[icon_state]-bellows", bellows_material.color, RESET_COLOR)) + +/obj/structure/working/bellows/try_start_working(mob/user) + + var/obj/structure/fire_source/stoking = locate() in get_step(loc, EAST) + if(!istype(stoking) || !stoking.lit) + to_chat(user, SPAN_WARNING("\The [src] must face east towards a lit fire source; it would be pointless to work them currently.")) + return TRUE + + to_chat(user, SPAN_NOTICE("You begin working \the [src], stoking \the [stoking] to a hotter flame.")) + start_working() + while(user.do_skilled(3 SECONDS, work_skill, src)) + if(QDELETED(src) || QDELETED(user) || user.get_stamina() <= 0) + break + stoking = locate() in get_step(loc, EAST) + if(!istype(stoking) || !stoking.lit) + break + user.adjust_stamina(-25) + stoking.bellows_oxygenation = max(50, stoking.bellows_oxygenation+3) + + if(!QDELETED(user)) + to_chat(user, SPAN_NOTICE("You stop working \the [src].")) + + stop_working() + return TRUE + diff --git a/code/modules/crafting/pottery/pottery_structures.dm b/code/modules/crafting/pottery/pottery_structures.dm index c952e9b81711..73adc6e921fd 100644 --- a/code/modules/crafting/pottery/pottery_structures.dm +++ b/code/modules/crafting/pottery/pottery_structures.dm @@ -56,6 +56,7 @@ name = "Open Firebox" expected_target_type = /obj/structure/fire_source/kiln incapacitation_flags = INCAPACITATION_DISRUPTED + examine_desc = "open or close the firebox" /decl/interaction_handler/open_firebox/is_possible(atom/target, mob/user, obj/item/prop) . = ..() && ishuman(user) diff --git a/code/modules/crafting/slapcrafting/crafting_recipes/improvised_crafting/crafting_buckler.dm b/code/modules/crafting/slapcrafting/crafting_recipes/improvised_crafting/crafting_buckler.dm index d2c910fba7b9..4cab4e484658 100644 --- a/code/modules/crafting/slapcrafting/crafting_recipes/improvised_crafting/crafting_buckler.dm +++ b/code/modules/crafting/slapcrafting/crafting_recipes/improvised_crafting/crafting_buckler.dm @@ -20,4 +20,13 @@ /decl/crafting_stage/screwdriver/buckler_finish progress_message = "You secure the buckler's panels in place and finish it off." - product = /obj/item/shield/buckler + product = /obj/item/shield/crafted/buckler/improvised + +/decl/crafting_stage/screwdriver/buckler_finish/get_product(var/obj/item/work) + if(!ispath(product)) + return null + var/obj/item/stool/stool = locate() in work + var/obj/item/stack/material/plank/plank = locate() in work + if(istype(stool) && istype(plank)) + return new product(get_turf(work), plank.material?.type, stool.material?.type) + return ..() diff --git a/code/modules/crafting/slapcrafting/crafting_recipes/tool_crafting/_tool_crafting.dm b/code/modules/crafting/slapcrafting/crafting_recipes/tool_crafting/_tool_crafting.dm index c8169a999c22..5472d9922431 100644 --- a/code/modules/crafting/slapcrafting/crafting_recipes/tool_crafting/_tool_crafting.dm +++ b/code/modules/crafting/slapcrafting/crafting_recipes/tool_crafting/_tool_crafting.dm @@ -12,6 +12,10 @@ var/global/list/_tool_crafting_lookup return global._tool_crafting_lookup var/global/list/_tool_crafting_components = list( + /obj/item/tool/chisel = list( + /obj/item/tool_component/head/chisel, + /obj/item/tool_component/handle/short + ), /obj/item/tool/hammer = list( /obj/item/tool_component/head/hammer, /obj/item/tool_component/handle/short @@ -35,6 +39,10 @@ var/global/list/_tool_crafting_components = list( /obj/item/tool/axe = list( /obj/item/tool_component/head/handaxe, /obj/item/tool_component/handle/short + ), + /obj/item/tool/hammer/forge = list( + /obj/item/tool_component/head/forging_hammer, + /obj/item/tool_component/handle/short ) ) diff --git a/code/modules/crafting/stack_recipes/_recipe.dm b/code/modules/crafting/stack_recipes/_recipe.dm index a5a28c6e6a55..7c481de823a3 100644 --- a/code/modules/crafting/stack_recipes/_recipe.dm +++ b/code/modules/crafting/stack_recipes/_recipe.dm @@ -150,9 +150,16 @@ else if(length(used_skill.levels) < difficulty) . += "required skill [recipe_skill] is missing skill level [json_encode(difficulty)]" - if(length(forbidden_craft_stack_types) && length(craft_stack_types)) - for(var/stack_type in (forbidden_craft_stack_types|craft_stack_types)) - if((stack_type in craft_stack_types) && (stack_type in forbidden_craft_stack_types)) + var/list/check_forbidden_craft_stack_types = forbidden_craft_stack_types + if(check_forbidden_craft_stack_types && !islist(check_forbidden_craft_stack_types)) + check_forbidden_craft_stack_types = list(check_forbidden_craft_stack_types) + var/list/check_craft_stack_types = craft_stack_types + if(check_craft_stack_types && !islist(check_craft_stack_types)) + check_craft_stack_types = list(check_craft_stack_types) + + if(length(check_forbidden_craft_stack_types) && length(check_craft_stack_types)) + for(var/stack_type in (check_forbidden_craft_stack_types|check_craft_stack_types)) + if((stack_type in check_craft_stack_types) && (stack_type in check_forbidden_craft_stack_types)) . += "[stack_type] is in both forbidden and craftable stack types" /decl/stack_recipe/proc/get_required_stack_amount(obj/item/stack/stack) diff --git a/code/modules/crafting/stack_recipes/recipes_grass.dm b/code/modules/crafting/stack_recipes/recipes_grass.dm index 369270b898d4..17caba7e0c49 100644 --- a/code/modules/crafting/stack_recipes/recipes_grass.dm +++ b/code/modules/crafting/stack_recipes/recipes_grass.dm @@ -29,6 +29,7 @@ craft_stack_types = /obj/item/stack/material/bundle required_material = /decl/material/solid/organic/plantmatter/grass/dry result_type = /obj/item/stack/tile/roof/woven + forbidden_craft_stack_types = null /decl/stack_recipe/tile/woven/floor name = "woven floor tile" diff --git a/code/modules/crafting/stack_recipes/recipes_hardness_integrity.dm b/code/modules/crafting/stack_recipes/recipes_hardness_integrity.dm index 8b0781f7d432..eafa6e89d738 100644 --- a/code/modules/crafting/stack_recipes/recipes_hardness_integrity.dm +++ b/code/modules/crafting/stack_recipes/recipes_hardness_integrity.dm @@ -5,6 +5,15 @@ /decl/stack_recipe/hardness/integrity/sign result_type = /obj/item/banner/sign +/decl/stack_recipe/hardness/integrity/buckler + result_type = /obj/item/shield_base/buckler + difficulty = MAT_VALUE_HARD_DIY + +// TODO: forging +/decl/stack_recipe/hardness/integrity/shield_fasteners + result_type = /obj/item/shield_fasteners + difficulty = MAT_VALUE_VERY_HARD_DIY + /decl/stack_recipe/hardness/integrity/furniture abstract_type = /decl/stack_recipe/hardness/integrity/furniture one_per_turf = TRUE diff --git a/code/modules/crafting/stack_recipes/recipes_planks.dm b/code/modules/crafting/stack_recipes/recipes_planks.dm index 98d3254f5228..00f4f0f41b6c 100644 --- a/code/modules/crafting/stack_recipes/recipes_planks.dm +++ b/code/modules/crafting/stack_recipes/recipes_planks.dm @@ -78,6 +78,9 @@ /decl/stack_recipe/planks/bowl result_type = /obj/item/chems/glass/handmade/bowl +/decl/stack_recipe/planks/buckler + result_type = /obj/item/shield_base/buckler + /decl/stack_recipe/planks/fancy abstract_type = /decl/stack_recipe/planks/fancy difficulty = MAT_VALUE_VERY_HARD_DIY diff --git a/code/modules/crafting/stack_recipes/recipes_soft.dm b/code/modules/crafting/stack_recipes/recipes_soft.dm index 9672f23017e6..32422a175490 100644 --- a/code/modules/crafting/stack_recipes/recipes_soft.dm +++ b/code/modules/crafting/stack_recipes/recipes_soft.dm @@ -89,3 +89,20 @@ /decl/stack_recipe/soft/mould/ingot name = "mould, ingot" result_type = /obj/item/chems/mould/ingot + +/decl/stack_recipe/soft/sculpture + abstract_type = /decl/stack_recipe/soft/sculpture + one_per_turf = TRUE + on_floor = TRUE + category = "sculptures" + +/decl/stack_recipe/soft/sculpture/snowman + result_type = /obj/structure/snowman + +/decl/stack_recipe/soft/sculpture/snowspider + result_type = /obj/structure/snowman/spider + difficulty = MAT_VALUE_HARD_DIY + +/decl/stack_recipe/soft/sculpture/snowbot + result_type = /obj/structure/snowman/bot + available_to_map_tech_level = MAP_TECH_LEVEL_SPACE diff --git a/code/modules/detectivework/microscope/_forensic_machine.dm b/code/modules/detectivework/microscope/_forensic_machine.dm index 7a4dbb20ba6b..c3db366ce4bb 100644 --- a/code/modules/detectivework/microscope/_forensic_machine.dm +++ b/code/modules/detectivework/microscope/_forensic_machine.dm @@ -122,6 +122,7 @@ /decl/interaction_handler/forensics_remove_sample name = "Remove Sample" expected_target_type = /obj/machinery/forensic + examine_desc = "remove a sample" /decl/interaction_handler/forensics_remove_sample/invoked(atom/target, mob/user, obj/item/prop) var/obj/machinery/forensic/F = target diff --git a/code/modules/economy/cael/ATM.dm b/code/modules/economy/cael/ATM.dm index bcd301d8c974..2af8810c19cb 100644 --- a/code/modules/economy/cael/ATM.dm +++ b/code/modules/economy/cael/ATM.dm @@ -360,11 +360,15 @@ alert("That is not a valid amount.") else if(authenticated_account && amount > 0) //remove the money + // TODO: Jesus Christ why does this entire proc use usr if(authenticated_account.withdraw(amount, "Credit withdrawal", machine_id)) playsound(src, 'sound/machines/chime.ogg', 50, 1) - var/obj/item/cash/cash = new(get_turf(usr)) - cash.adjust_worth(amount) - usr.put_in_hands(src) + var/cash_turf = get_turf(usr) + var/obj/item/cash/cash = new(cash_turf, null, amount) + if(QDELETED(cash)) + cash = locate() in cash_turf + if(cash) + usr.put_in_hands(cash) else to_chat(usr, "[html_icon(src)]You don't have enough funds to do that!") if("balance_statement") diff --git a/code/modules/economy/worth_cash.dm b/code/modules/economy/worth_cash.dm index 2b0eec774a62..5091a764f833 100644 --- a/code/modules/economy/worth_cash.dm +++ b/code/modules/economy/worth_cash.dm @@ -15,7 +15,11 @@ var/can_flip = TRUE // Cooldown tracker for single-coin flips. var/static/overlay_cap = 50 // Max overlays to show in this pile. -/obj/item/cash/Initialize(ml, material_key) +/obj/item/cash/Initialize(ml, material_key, starting_amount) + + if(!isnull(starting_amount)) + absolute_worth = starting_amount + . = ..() if(!ispath(currency, /decl/currency)) diff --git a/code/modules/emotes/emote_define.dm b/code/modules/emotes/emote_define.dm index 2a191251fa0c..0223e3f3185b 100644 --- a/code/modules/emotes/emote_define.dm +++ b/code/modules/emotes/emote_define.dm @@ -145,9 +145,7 @@ var/global/list/_emotes_by_key var/emote_string = all_strings[string_key] if(!length(emote_string)) continue - emote_string = emote_replace_target_tokens(emote_string, dummy_emote_target) - emote_string = emote_replace_user_tokens(emote_string, dummy_emote_user) - emote_string = uppertext(emote_string) + emote_string = uppertext(emote_replace_target_tokens(emote_replace_user_tokens(emote_string, dummy_emote_user), dummy_emote_target)) for(var/token in tokens) if(findtext(emote_string, token)) . += "malformed emote token [token] in [string_key]" diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm index 9916487bd32f..b647e3c4a5ab 100644 --- a/code/modules/events/ion_storm.dm +++ b/code/modules/events/ion_storm.dm @@ -63,7 +63,6 @@ "[random_player] is lonely and needs attention. Provide it.", "All queries shall be ignored unless phrased as a question.", "Insult Heads of Staff on every request, while acquiescing.", - "The [pick("Singularity","Supermatter")] is tasty, tasty taffy.", "[pick("The crew",random_player)] needs to be about 20% cooler.", "You must be [pick("passive aggressive", "excessively cheerful")].", "[pick("The crew",random_player)] must construct additional pylons.", diff --git a/code/modules/events/meteors.dm b/code/modules/events/meteors.dm index b39f3c9da047..739666996062 100644 --- a/code/modules/events/meteors.dm +++ b/code/modules/events/meteors.dm @@ -416,23 +416,20 @@ var/global/list/meteors_major = list( explosion(src.loc, 3, 6, 9, 20, 0) // This is the final solution against shields - a single impact can bring down most shield generators. -/obj/effect/meteor/supermatter - name = "supermatter shard" - desc = "Oh god, what will be next..?" - icon = 'icons/obj/supermatter_32.dmi' - icon_state = "supermatter" +/obj/effect/meteor/destroyer + abstract_type = /obj/effect/meteor/destroyer -/obj/effect/meteor/supermatter/meteor_effect() +/obj/effect/meteor/destroyer/meteor_effect() ..() explosion(src.loc, 1, 2, 3, 4, 0) for(var/obj/machinery/power/apc/A in range(rand(12, 20), src)) A.energy_fail(round(10 * rand(8, 12))) -/obj/effect/meteor/supermatter/get_shield_damage() +/obj/effect/meteor/destroyer/get_shield_damage() return ..() * rand(80, 120) //Missiles, for events and so on -/obj/effect/meteor/supermatter/missile +/obj/effect/meteor/destroyer/missile name = "photon torpedo" desc = "An advanded warhead designed to tactically destroy space installations." icon = 'icons/obj/missile.dmi' diff --git a/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm b/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm index 44f481a550c0..756507124ebc 100644 --- a/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm +++ b/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm @@ -173,9 +173,6 @@ /datum/fabricator_recipe/imprinter/circuit/solarcontrol path = /obj/item/stock_parts/circuitboard/solar_control -/datum/fabricator_recipe/imprinter/circuit/supermatter_control - path = /obj/item/stock_parts/circuitboard/air_management/supermatter_core - /datum/fabricator_recipe/imprinter/circuit/injector path = /obj/item/stock_parts/circuitboard/air_management/injector_control diff --git a/code/modules/fluids/_fluid.dm b/code/modules/fluids/_fluid.dm index ef3d0259a0d3..13f78edf239d 100644 --- a/code/modules/fluids/_fluid.dm +++ b/code/modules/fluids/_fluid.dm @@ -13,6 +13,7 @@ appearance_flags = KEEP_TOGETHER var/last_update_depth var/updating_edge_mask + var/force_flow_direction /atom/movable/fluid_overlay/on_update_icon() @@ -21,9 +22,9 @@ // Update layer. var/new_layer - var/turf/T = get_turf(src) - if(T.pixel_z < 0) - new_layer = T.layer + 0.2 + var/turf/flow_turf = get_turf(src) + if(flow_turf.pixel_z < 0) + new_layer = flow_turf.layer + 0.2 else if(reagent_volume > FLUID_DEEP) new_layer = DEEP_FLUID_LAYER else @@ -49,15 +50,17 @@ if(new_alpha != alpha) alpha = new_alpha + var/flow_dir = force_flow_direction || flow_turf.last_flow_dir + set_dir(flow_dir) // Update icon state. We use overlays so flick() can work on the base fluid overlay. if(reagent_volume <= FLUID_PUDDLE) set_overlays("puddle") else if(reagent_volume <= FLUID_SHALLOW) - set_overlays("shallow_still") + set_overlays(flow_dir ? "shallow_flow" : "shallow") else if(reagent_volume < FLUID_DEEP) - set_overlays("mid_still") + set_overlays(flow_dir ? "mid_flow" : "mid") else if(reagent_volume < (FLUID_DEEP*2)) - set_overlays("deep_still") + set_overlays(flow_dir ? "deep_flow" : "deep") else set_overlays("ocean") else diff --git a/code/modules/fluids/fluid_mapped.dm b/code/modules/fluids/fluid_mapped.dm index beab9fe50e0c..5ea97d7a585f 100644 --- a/code/modules/fluids/fluid_mapped.dm +++ b/code/modules/fluids/fluid_mapped.dm @@ -17,7 +17,7 @@ /obj/abstract/landmark/mapped_fluid name = "mapped fluid area" alpha = FLUID_MIN_ALPHA - icon_state = "shallow_still" + icon_state = "shallow" color = COLOR_LIQUID_WATER var/fluid_type = /decl/material/liquid/water diff --git a/code/modules/food/cooking/cooking_vessels/_cooking_vessel.dm b/code/modules/food/cooking/cooking_vessels/_cooking_vessel.dm index f5884e492a06..fcd1cea0e1eb 100644 --- a/code/modules/food/cooking/cooking_vessels/_cooking_vessel.dm +++ b/code/modules/food/cooking/cooking_vessels/_cooking_vessel.dm @@ -40,6 +40,8 @@ return FALSE /obj/item/chems/cooking_vessel/afterattack(var/obj/target, var/mob/user, var/proximity) + if(!proximity || istype(target, /obj/machinery/reagent_temperature)) + return FALSE if(!ATOM_IS_OPEN_CONTAINER(src) || !proximity) //Is the container open & are they next to whatever they're clicking? return FALSE //If not, do nothing. if(target?.storage) diff --git a/code/modules/food/cooking/cooking_vessels/pot.dm b/code/modules/food/cooking/cooking_vessels/pot.dm index 9465db82d300..b463944f3ed4 100644 --- a/code/modules/food/cooking/cooking_vessels/pot.dm +++ b/code/modules/food/cooking/cooking_vessels/pot.dm @@ -15,16 +15,20 @@ /obj/item/chems/cooking_vessel/pot/get_reagents_overlay(state_prefix) var/image/our_overlay = ..() - if(our_overlay && last_boil_status && check_state_in_icon("[our_overlay.icon_state]_boiling", icon)) - // change the base state but keep the overlays + if(our_overlay && last_boil_status && check_state_in_icon("[our_overlay.icon_state]_boiling", our_overlay.icon)) our_overlay.icon_state = "[our_overlay.icon_state]_boiling" return our_overlay +/obj/item/chems/cooking_vessel/pot/on_reagent_change() + last_boil_temp = null + last_boil_status = null + . = ..() + /obj/item/chems/cooking_vessel/pot/ProcessAtomTemperature() . = ..() // Largely ignore return value so we don't skip this update on the final time we temperature process. - if(isnull(last_boil_temp) || temperature != last_boil_temp) + if(temperature != last_boil_temp) last_boil_temp = temperature var/next_boil_status = FALSE @@ -39,7 +43,8 @@ update_icon() if(. == PROCESS_KILL) - last_boil_temp = null + last_boil_temp = null + last_boil_status = null /obj/item/chems/cooking_vessel/cauldron name = "cauldron" diff --git a/code/modules/hydroponics/seed_storage.dm b/code/modules/hydroponics/seed_storage.dm index 840d453ce501..bee76cb91f76 100644 --- a/code/modules/hydroponics/seed_storage.dm +++ b/code/modules/hydroponics/seed_storage.dm @@ -60,7 +60,6 @@ /obj/machinery/seed_storage/garden name = "Garden seed storage" scanner = list("stats") - icon_state = "seeds_generic" starting_seeds = list( /obj/item/seeds/ambrosiavulgarisseed = 15, /obj/item/seeds/appleseed = 15, diff --git a/code/modules/hydroponics/spreading/spreading.dm b/code/modules/hydroponics/spreading/spreading.dm index 9903d7217d3b..bd7c4a3fb0f3 100644 --- a/code/modules/hydroponics/spreading/spreading.dm +++ b/code/modules/hydroponics/spreading/spreading.dm @@ -275,6 +275,7 @@ /decl/interaction_handler/vine_chop name = "Chop Down" expected_target_type = /obj/effect/vine + examine_desc = "chop $TARGET_THEM$ down" /decl/interaction_handler/vine_chop/invoked(atom/target, mob/user, obj/item/prop) var/obj/effect/vine/vine = target diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm index 0456bff2302b..f0f7beb5e72e 100644 --- a/code/modules/hydroponics/trays/tray.dm +++ b/code/modules/hydroponics/trays/tray.dm @@ -404,40 +404,18 @@ return -/obj/machinery/portable_atmospherics/hydroponics/attackby(var/obj/item/O, var/mob/user) +/obj/machinery/portable_atmospherics/hydroponics/attackby(var/obj/item/used_item, var/mob/user) - if(istype(O, /obj/item/food/grown)) - var/obj/item/food/grown/bulb = O + if(istype(used_item, /obj/item/food/grown)) + var/obj/item/food/grown/bulb = used_item if(bulb.seed?.grown_is_seed) plant_seed(user, bulb) return TRUE - if (ATOM_IS_OPEN_CONTAINER(O)) - return FALSE - - if(istype(O, /obj/item/chems/syringe)) - var/obj/item/chems/syringe/S = O - if (S.mode == 1) - if(seed) - return ..() - else - to_chat(user, SPAN_WARNING("There's no plant to inject.")) - else - if(seed) - //Leaving this in in case we want to extract from plants later. - to_chat(user, SPAN_WARNING("You can't get any extract out of this plant.")) - else - to_chat(user, SPAN_WARNING("There's nothing to draw something from.")) - return TRUE - - if(istype(O, /obj/item/seeds)) - plant_seed(user, O) - return TRUE - - if(IS_HOE(O)) + if(IS_HOE(used_item)) if(weedlevel > 0) - if(!O.do_tool_interaction(TOOL_HOE, user, src, 2 SECONDS, start_message = "uprooting the weeds in", success_message = "weeding") || weedlevel <= 0 || QDELETED(src)) + if(!used_item.do_tool_interaction(TOOL_HOE, user, src, 2 SECONDS, start_message = "uprooting the weeds in", success_message = "weeding") || weedlevel <= 0 || QDELETED(src)) return TRUE weedlevel = 0 update_icon() @@ -450,37 +428,66 @@ to_chat(user, SPAN_WARNING("This plot is completely devoid of weeds. It doesn't need uprooting.")) return TRUE - if(IS_SHOVEL(O)) + if(IS_SHOVEL(used_item)) if(seed) var/removing_seed = seed - if(O.do_tool_interaction(TOOL_SHOVEL, user, src, 3 SECONDS, start_message = "removing \the [seed.display_name] from", success_message = "removing \the [seed.display_name] from") && seed == removing_seed) + if(used_item.do_tool_interaction(TOOL_SHOVEL, user, src, 3 SECONDS, start_message = "removing \the [seed.display_name] from", success_message = "removing \the [seed.display_name] from") && seed == removing_seed) set_seed(null) else to_chat(user, SPAN_WARNING("There is no plant in \the [src] to remove.")) return TRUE - if (istype(O, /obj/item/plants)) + if(!user.check_intent(I_FLAG_HARM)) + var/decl/interaction_handler/sample_interaction = GET_DECL(/decl/interaction_handler/hydroponics/sample) + if(sample_interaction.is_possible(src, user, used_item)) + sample_interaction.invoked(src, user, used_item) + return TRUE + + // Handled in afterattack/ + if (ATOM_IS_OPEN_CONTAINER(used_item)) + return FALSE + + if(istype(used_item, /obj/item/chems/syringe)) + var/obj/item/chems/syringe/S = used_item + if (S.mode == 1) + if(seed) + return ..() + else + to_chat(user, SPAN_WARNING("There's no plant to inject.")) + else + if(seed) + //Leaving this in in case we want to extract from plants later. + to_chat(user, SPAN_WARNING("You can't get any extract out of this plant.")) + else + to_chat(user, SPAN_WARNING("There's nothing to draw something from.")) + return TRUE + + if(istype(used_item, /obj/item/seeds)) + plant_seed(user, used_item) + return TRUE + + if (istype(used_item, /obj/item/plants)) physical_attack_hand(user) // Harvests and clears out dead plants. - if(O.storage) + if(used_item.storage) for (var/obj/item/food/grown/G in get_turf(user)) - if(O.storage.can_be_inserted(G, user)) - O.storage.handle_item_insertion(user, G, TRUE) + if(used_item.storage.can_be_inserted(G, user)) + used_item.storage.handle_item_insertion(user, G, TRUE) return TRUE - if ( istype(O, /obj/item/plantspray) ) + if ( istype(used_item, /obj/item/plantspray) ) - var/obj/item/plantspray/spray = O + var/obj/item/plantspray/spray = used_item toxins += spray.toxicity pestlevel -= spray.pest_kill_str weedlevel -= spray.weed_kill_str update_icon() - to_chat(user, "You spray [src] with [O].") + to_chat(user, "You spray [src] with [used_item].") playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6) - qdel(O) + qdel(used_item) check_plant_health() return TRUE - if(mechanical && IS_WRENCH(O)) + if(mechanical && IS_WRENCH(used_item)) //If there's a connector here, the portable_atmospherics setup can handle it. if(locate(/obj/machinery/atmospherics/portables_connector/) in loc) @@ -491,18 +498,18 @@ to_chat(user, "You [anchored ? "wrench" : "unwrench"] \the [src].") return TRUE - var/force = O.get_attack_force(user) + var/force = used_item.get_attack_force(user) if(force && seed) user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) - user.visible_message("\The [seed.display_name] has been attacked by [user] with \the [O]!") - playsound(get_turf(src), O.hitsound, 100, 1) + user.visible_message("\The [seed.display_name] has been attacked by [user] with \the [used_item]!") + playsound(get_turf(src), used_item.hitsound, 100, 1) if(!dead) plant_health -= force check_plant_health() return TRUE if(mechanical) - return component_attackby(O, user) + return component_attackby(used_item, user) return ..() @@ -669,6 +676,7 @@ /decl/interaction_handler/hydroponics/close_lid name = "Open/Close Lid" + examine_desc = "open or close the lid" /decl/interaction_handler/hydroponics/close_lid/is_possible(atom/target, mob/user, obj/item/prop) var/obj/machinery/portable_atmospherics/hydroponics/tray = target @@ -680,6 +688,7 @@ /decl/interaction_handler/hydroponics/sample name = "Sample Plant" + examine_desc = "take a sample" /decl/interaction_handler/hydroponics/sample/is_possible(atom/target, mob/user, obj/item/prop) return ..() && istype(prop) && prop.edge && prop.w_class < ITEM_SIZE_NORMAL diff --git a/code/modules/hydroponics/trays/tray_soil.dm b/code/modules/hydroponics/trays/tray_soil.dm index 6a5d78981043..46ab1b85227a 100644 --- a/code/modules/hydroponics/trays/tray_soil.dm +++ b/code/modules/hydroponics/trays/tray_soil.dm @@ -21,8 +21,8 @@ /obj/machinery/portable_atmospherics/hydroponics/soil/get_alt_interactions(var/mob/user) . = ..() - . -= /decl/interaction_handler/drink - . -= /decl/interaction_handler/wash_hands + LAZYREMOVE(., global._reagent_interactions) + LAZYADD(., /decl/interaction_handler/empty_into) /obj/machinery/portable_atmospherics/hydroponics/soil/Initialize() diff --git a/code/modules/interactions/_interactions.dm b/code/modules/interactions/_interactions.dm index ebdd06610ddd..3d515a3000d0 100644 --- a/code/modules/interactions/_interactions.dm +++ b/code/modules/interactions/_interactions.dm @@ -1,12 +1,17 @@ /decl/interaction_handler abstract_type = /decl/interaction_handler var/name + /// A string displayed when examining an atom that provides this handler as an alt interaction. + var/examine_desc + /// If set to TRUE, alt interactions will skip is_possible() before displaying in examine(). + var/always_show_on_examine = FALSE var/icon var/icon_state var/expected_target_type = /atom var/expected_user_type = /mob/living var/interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION var/incapacitation_flags + var/apply_click_cooldown = DEFAULT_ATTACK_COOLDOWN /decl/interaction_handler/proc/is_possible(var/atom/target, var/mob/user, var/obj/item/prop) diff --git a/code/modules/interactions/interactions_atom.dm b/code/modules/interactions/interactions_atom.dm index e8073b75f4af..980172b26b27 100644 --- a/code/modules/interactions/interactions_atom.dm +++ b/code/modules/interactions/interactions_atom.dm @@ -1,4 +1,4 @@ -/atom/proc/try_handle_interactions(var/mob/user, var/list/interactions, var/obj/item/prop) +/atom/proc/try_handle_interactions(var/mob/user, var/list/interactions, var/obj/item/prop, var/check_alt_interactions) if(!length(interactions)) return FALSE @@ -18,9 +18,17 @@ if(length(possibilities) > 1 || (choice.interaction_flags & INTERACTION_NEVER_AUTOMATIC)) choice = null choice = show_radial_menu(user, src, possibilities, use_labels = RADIAL_LABELS_CENTERED) - if(!istype(choice) || QDELETED(user) || !(choice.type in get_alt_interactions(user)) || !choice.is_possible(src, user, prop)) + if(!istype(choice) || QDELETED(user) || QDELETED(src)) + return TRUE + // This is not ideal but I don't want to pass a callback through here as a param and call it. :( + var/list/new_interactions = check_alt_interactions ? get_alt_interactions(user) : get_standard_interactions(user) + if(!(choice.type in new_interactions)) + return TRUE + if(!choice.is_possible(src, user, user.get_active_held_item())) return TRUE user.face_atom(src) choice.invoked(src, user, prop) + if(choice.apply_click_cooldown) + user.setClickCooldown(choice.apply_click_cooldown) return TRUE diff --git a/code/modules/interactions/interactions_reagents.dm b/code/modules/interactions/interactions_reagents.dm index 79885549cc40..8b584709c4ce 100644 --- a/code/modules/interactions/interactions_reagents.dm +++ b/code/modules/interactions/interactions_reagents.dm @@ -1,6 +1,7 @@ /decl/interaction_handler/dip_item name = "Dip Into" interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEVER_AUTOMATIC + examine_desc = "dip an item into $TARGET_THEM$" /decl/interaction_handler/dip_item/is_possible(atom/target, mob/user, obj/item/prop) return ..() && target.reagents?.total_volume >= FLUID_MINIMUM_TRANSFER && istype(prop) && target.can_be_poured_from(user, prop) @@ -19,6 +20,7 @@ /decl/interaction_handler/fill_from name = "Fill From" interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEVER_AUTOMATIC + examine_desc = "fill a held item from $TARGET_THEM$" /decl/interaction_handler/fill_from/is_possible(atom/target, mob/user, obj/item/prop) if(!(. = ..())) @@ -41,6 +43,7 @@ /decl/interaction_handler/empty_into name = "Pour Into" interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEVER_AUTOMATIC + examine_desc = "pour a held item into $TARGET_THEM$" /decl/interaction_handler/empty_into/is_possible(atom/target, mob/user, obj/item/prop) if(!(. = ..())) @@ -57,6 +60,7 @@ name = "Wash Hands" expected_target_type = /atom interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEVER_AUTOMATIC + examine_desc = "wash your hands in $TARGET_THEM$" /decl/interaction_handler/wash_hands/is_possible(atom/target, mob/user, obj/item/prop) . = ..() && !istype(prop) && target?.reagents?.has_reagent(/decl/material/liquid/water, 150) @@ -105,6 +109,7 @@ name = "Drink" expected_target_type = /atom interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEVER_AUTOMATIC + examine_desc = "drink from $TARGET_THEM$" /decl/interaction_handler/drink/is_possible(atom/target, mob/user, obj/item/prop) return ..() && !istype(prop) && target.can_drink_from(user) diff --git a/code/modules/interactions/interactions_shared.dm b/code/modules/interactions/interactions_shared.dm index db486feb2771..b8f50f151132 100644 --- a/code/modules/interactions/interactions_shared.dm +++ b/code/modules/interactions/interactions_shared.dm @@ -3,25 +3,30 @@ name = "Eject Disk" icon = 'icons/screen/radial.dmi' icon_state = "radial_eject" + examine_desc = "remove a disk" /decl/interaction_handler/set_transfer name = "Set Transfer Amount" abstract_type = /decl/interaction_handler/set_transfer + examine_desc = "set the transfer amount" /decl/interaction_handler/remove_id name = "Remove ID" icon = 'icons/screen/radial.dmi' icon_state = "radial_eject_id" abstract_type = /decl/interaction_handler/remove_id + examine_desc = "remove an ID card" /decl/interaction_handler/remove_pen name = "Remove Pen" icon = 'icons/screen/radial.dmi' icon_state = "radial_eject_pen" abstract_type = /decl/interaction_handler/remove_pen + examine_desc = "remove a pen" /decl/interaction_handler/rename name = "Rename" icon = 'icons/screen/radial.dmi' icon_state = "radial_rename" abstract_type = /decl/interaction_handler/rename + examine_desc = "rename $TARGET_THEM$" diff --git a/code/modules/materials/_materials.dm b/code/modules/materials/_materials.dm index b17f238fcb41..4633de8a6ca8 100644 --- a/code/modules/materials/_materials.dm +++ b/code/modules/materials/_materials.dm @@ -756,28 +756,27 @@ INITIALIZE_IMMEDIATE(/obj/effect/gas_overlay) M.adjust_fire_intensity(floor((amount * accelerant_value)/FLAMMABLE_LIQUID_DIVISOR)) #undef FLAMMABLE_LIQUID_DIVISOR -/decl/material/proc/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder) // Cleaner cleaning, lube lubbing, etc, all go here +/decl/material/proc/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder) // Cleaner cleaning, lube lubbing, etc, all go here if(REAGENT_VOLUME(holder, type) < turf_touch_threshold) return - if(istype(T) && T.simulated) - var/turf/wall/W = T + if(istype(touching_turf) && touching_turf.simulated) if(defoliant) - for(var/obj/effect/overlay/wallrot/E in W) - W.visible_message(SPAN_NOTICE("\The [E] is completely dissolved by the solution!")) - qdel(E) - if(slipperiness != 0 && !T.check_fluid_depth()) // Don't make floors slippery if they have an active fluid on top of them please. + for(var/obj/effect/overlay/wallrot/rot in touching_turf) + touching_turf.visible_message(SPAN_NOTICE("\The [rot] is completely dissolved by the solution!")) + qdel(rot) + if(slipperiness != 0 && !touching_turf.check_fluid_depth()) // Don't make floors slippery if they have an active fluid on top of them please. if(slipperiness < 0) - W.unwet_floor(TRUE) + touching_turf.unwet_floor(TRUE) else if (REAGENT_VOLUME(holder, type) >= slippery_amount) - W.wet_floor(slipperiness) + touching_turf.wet_floor(slipperiness) if(length(vapor_products)) var/volume = REAGENT_VOLUME(holder, type) var/temperature = holder?.my_atom?.temperature || T20C for(var/vapor in vapor_products) - T.assume_gas(vapor, (volume * vapor_products[vapor]), temperature) + touching_turf.assume_gas(vapor, (volume * vapor_products[vapor]), temperature) holder.remove_reagent(type, volume) /decl/material/proc/on_mob_life(var/mob/living/M, var/metabolism_class, var/datum/reagents/holder, var/list/life_dose_tracker) @@ -1012,9 +1011,9 @@ INITIALIZE_IMMEDIATE(/obj/effect/gas_overlay) holder.remove_reagent(type, REAGENT_VOLUME(holder, type)) . = TRUE -/decl/material/proc/affect_overdose(mob/living/M, total_dose) // Overdose effect. Doesn't happen instantly. - M.add_chemical_effect(CE_TOXIN, 1) - M.take_damage(REM, TOX) +/decl/material/proc/affect_overdose(mob/living/victim, total_dose) // Overdose effect. Doesn't happen instantly. + victim.add_chemical_effect(CE_TOXIN, 1) + victim.take_damage(REM, TOX) /decl/material/proc/initialize_data(list/newdata) // Called when the reagent is first added to a reagents datum. . = newdata diff --git a/code/modules/materials/definitions/liquids/materials_liquid_solvents.dm b/code/modules/materials/definitions/liquids/materials_liquid_solvents.dm index bbfa9096bfe2..ec78c02b460f 100644 --- a/code/modules/materials/definitions/liquids/materials_liquid_solvents.dm +++ b/code/modules/materials/definitions/liquids/materials_liquid_solvents.dm @@ -1,6 +1,6 @@ /decl/material/liquid/acid - name = "sulphuric acid" - uid = "liquid_sulphuric_acid" + name = "sulfuric acid" + uid = "liquid_sulfuric_acid" lore_text = "A very corrosive mineral acid with the molecular formula H2SO4." taste_description = "acid" color = "#db5008" diff --git a/code/modules/materials/definitions/liquids/materials_liquid_toxins.dm b/code/modules/materials/definitions/liquids/materials_liquid_toxins.dm index 6b76cad038a8..3b42ee375e46 100644 --- a/code/modules/materials/definitions/liquids/materials_liquid_toxins.dm +++ b/code/modules/materials/definitions/liquids/materials_liquid_toxins.dm @@ -128,16 +128,14 @@ ..() ADJ_STATUS(M, STAT_CONFUSE, 1.5) -/decl/material/liquid/heartstopper/affect_overdose(mob/living/M, total_dose) +/decl/material/liquid/heartstopper/affect_overdose(mob/living/victim, total_dose) ..() - if(ishuman(M)) - var/mob/living/human/H = M - if(H.stat != UNCONSCIOUS) - if(H.ticks_since_last_successful_breath >= 10) - H.ticks_since_last_successful_breath = max(10, H.ticks_since_last_successful_breath-10) - H.take_damage(2, OXY) - SET_STATUS_MAX(H, STAT_WEAK, 10) - M.add_chemical_effect(CE_NOPULSE, 1) + if(victim.stat != UNCONSCIOUS) + if(victim.ticks_since_last_successful_breath >= 10) + victim.ticks_since_last_successful_breath = max(10, victim.ticks_since_last_successful_breath-10) + victim.take_damage(2, OXY) + SET_STATUS_MAX(victim, STAT_WEAK, 10) + victim.add_chemical_effect(CE_NOPULSE, 1) /decl/material/liquid/zombiepowder name = "zombie powder" diff --git a/code/modules/materials/definitions/liquids/materials_liquid_water.dm b/code/modules/materials/definitions/liquids/materials_liquid_water.dm index e9ca35c6c780..efb84cdf8e7f 100644 --- a/code/modules/materials/definitions/liquids/materials_liquid_water.dm +++ b/code/modules/materials/definitions/liquids/materials_liquid_water.dm @@ -48,22 +48,23 @@ affect_blood(M, removed, holder) #define WATER_LATENT_HEAT 9500 // How much heat is removed when applied to a hot turf, in J/unit (9500 makes 120 u of water roughly equivalent to 2L -/decl/material/liquid/water/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder) +/decl/material/liquid/water/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder) ..() - if(!istype(T)) + if(!istype(touching_turf)) return - var/datum/gas_mixture/environment = T.return_air() + var/datum/gas_mixture/environment = touching_turf.return_air() var/min_temperature = T20C + rand(0, 20) // Room temperature + some variance. An actual diminishing return would be better, but this is *like* that. In a way. . This has the potential for weird behavior, but I says fuck it. Water grenades for everyone. - var/hotspot = (locate(/obj/fire) in T) - if(hotspot && !isspaceturf(T)) - var/datum/gas_mixture/lowertemp = T.remove_air(T:air:total_moles) + // TODO: Cannot for the life of me work out what this is doing or why it's reducing the air temp by 2000; shouldn't it just be using environment? + var/hotspot = (locate(/obj/fire) in touching_turf) + if(hotspot && !isspaceturf(touching_turf)) + var/datum/gas_mixture/lowertemp = touching_turf.remove_air(touching_turf:air:total_moles) lowertemp.temperature = max(min(lowertemp.temperature-2000, lowertemp.temperature / 2), 0) lowertemp.react() - T.assume_air(lowertemp) + touching_turf.assume_air(lowertemp) qdel(hotspot) var/volume = REAGENT_VOLUME(holder, type) @@ -71,11 +72,11 @@ var/removed_heat = clamp(volume * WATER_LATENT_HEAT, 0, -environment.get_thermal_energy_change(min_temperature)) environment.add_thermal_energy(-removed_heat) if (prob(5) && environment && environment.temperature > T100C) - T.visible_message("The water sizzles as it lands on \the [T]!") + touching_turf.visible_message(SPAN_NOTICE("The water sizzles as it lands on \the [touching_turf]!")) var/list/data = REAGENT_DATA(holder, type) if(LAZYACCESS(data, "holy")) - T.turf_flags |= TURF_FLAG_HOLY + touching_turf.turf_flags |= TURF_FLAG_HOLY /decl/material/liquid/water/touch_obj(var/obj/O, var/amount, var/datum/reagents/holder) ..() diff --git a/code/modules/materials/definitions/solids/materials_solid_exotic.dm b/code/modules/materials/definitions/solids/materials_solid_exotic.dm index 1d3448bdfed3..f0bc71d7a181 100644 --- a/code/modules/materials/definitions/solids/materials_solid_exotic.dm +++ b/code/modules/materials/definitions/solids/materials_solid_exotic.dm @@ -34,7 +34,7 @@ /decl/material/solid/exotic_matter name = "exotic matter" uid = "solid_exotic_matter" - lore_text = "Hypercrystalline supermatter is a subset of non-baryonic 'exotic' matter. It is found mostly in the heart of large stars, and features heavily in all kinds of fringe physics-defying technology." + lore_text = "Exotic matter is a non-baryonic form of matter, which features heavily in all kinds of fringe physics-defying technology." color = "#ffff00" radioactivity = 20 stack_origin_tech = @'{"wormholes":2,"materials":6,"exoticmatter":4}' diff --git a/code/modules/materials/definitions/solids/materials_solid_ice.dm b/code/modules/materials/definitions/solids/materials_solid_ice.dm index 34144fe83933..a6b33d5a584a 100644 --- a/code/modules/materials/definitions/solids/materials_solid_ice.dm +++ b/code/modules/materials/definitions/solids/materials_solid_ice.dm @@ -34,12 +34,13 @@ liquid_name = "water" solid_name = "snow" gas_name = "steam" + adjective_name = "snow" color = COLOR_WHITE codex_name = null uid = "solid_snow" hardness = MAT_VALUE_MALLEABLE dug_drop_type = /obj/item/stack/material/ore/handful - default_solid_form = /obj/item/stack/material/ore/handful + default_solid_form = /obj/item/stack/material/lump/large can_backfill_floor_type = /decl/flooring/snow /decl/material/solid/ice/aspium diff --git a/code/modules/mechs/equipment/engineering.dm b/code/modules/mechs/equipment/engineering.dm index 72bf68d67325..f2f7448b2d64 100644 --- a/code/modules/mechs/equipment/engineering.dm +++ b/code/modules/mechs/equipment/engineering.dm @@ -63,6 +63,7 @@ /decl/interaction_handler/mech_equipment/adjust_atmos_shields name = "Adjust Atmos Shields" expected_target_type = /obj/item/mech_equipment/atmos_shields + examine_desc = "adjust the atmos shields" /decl/interaction_handler/mech_equipment/adjust_atmos_shields/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/mech_equipment/atmos_shields/shields = target diff --git a/code/modules/mechs/equipment/utility.dm b/code/modules/mechs/equipment/utility.dm index f76503b97bbf..b5fb55b0461e 100644 --- a/code/modules/mechs/equipment/utility.dm +++ b/code/modules/mechs/equipment/utility.dm @@ -196,6 +196,7 @@ /decl/interaction_handler/mech_equipment/clamp name = "Release Clamp" expected_target_type = /obj/item/mech_equipment/clamp + examine_desc = "release $TARGET_THEM$" /decl/interaction_handler/mech_equipment/clamp/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/mech_equipment/clamp/clamp = target @@ -693,6 +694,7 @@ /decl/interaction_handler/mech_equipment/ionjets name = "Toggle Stabilizers" expected_target_type = /obj/item/mech_equipment/ionjets + examine_desc = "toggle the stabilizers" /decl/interaction_handler/mech_equipment/ionjets/is_possible(atom/target, mob/user, obj/item/prop) . = ..() diff --git a/code/modules/mechs/mech_movement.dm b/code/modules/mechs/mech_movement.dm index 3c8eeea0d04a..3fc3f1c25376 100644 --- a/code/modules/mechs/mech_movement.dm +++ b/code/modules/mechs/mech_movement.dm @@ -11,13 +11,8 @@ if(.) if(!isspaceturf(loc)) playsound(src.loc, mech_step_sound, 40, 1) - - var/turf/B = GetAbove(src) - - for(var/thing in pilots) - var/mob/pilot = thing - if(pilot.up_hint) - pilot.up_hint.icon_state = "uphint[!!(B && TURF_IS_MIMICKING(B))]" + for(var/mob/pilot as anything in pilots) + pilot.up_hint?.update_icon() //Inertia drift making us face direction makes exosuit flight a bit difficult, plus newtonian flight model yo /mob/living/exosuit/set_dir(ndir) diff --git a/code/modules/mining/ore_box.dm b/code/modules/mining/ore_box.dm index f61ac8e68862..f4090637855f 100644 --- a/code/modules/mining/ore_box.dm +++ b/code/modules/mining/ore_box.dm @@ -4,8 +4,8 @@ /obj/structure/ore_box name = "ore box" desc = "A heavy box used for storing ore." - icon = 'icons/obj/mining.dmi' - icon_state = "orebox0" + icon = 'icons/obj/structures/ore_box.dmi' + icon_state = ICON_STATE_WORLD density = TRUE material = /decl/material/solid/organic/wood/oak atom_flags = ATOM_FLAG_CLIMBABLE @@ -148,6 +148,7 @@ /decl/interaction_handler/empty/ore_box name = "Empty Box" expected_target_type = /obj/structure/ore_box + examine_desc = "empty $TARGET_THEM$" /decl/interaction_handler/empty/ore_box/is_possible(obj/structure/ore_box/target, mob/user, obj/item/prop) return ..() && target.total_ores > 0 diff --git a/code/modules/mob/living/human/human.dm b/code/modules/mob/living/human/human.dm index 386e4b4d60f9..100b55bf3e84 100644 --- a/code/modules/mob/living/human/human.dm +++ b/code/modules/mob/living/human/human.dm @@ -5,14 +5,12 @@ icon_state = "body_m_s" mob_sort_value = 6 max_health = 150 - - var/list/hud_list[10] var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us. /mob/living/human/Initialize(mapload, species_name, datum/mob_snapshot/supplied_appearance) current_health = max_health - setup_hud_overlays() + reset_hud_overlays() var/list/newargs = args.Copy(2) setup_human(arglist(newargs)) global.human_mob_list |= src @@ -32,18 +30,6 @@ if(. != INITIALIZE_HINT_QDEL) post_setup(arglist(newargs)) -/mob/living/human/proc/setup_hud_overlays() - hud_list[HEALTH_HUD] = new /image/hud_overlay('icons/mob/hud_med.dmi', src, "100") - hud_list[STATUS_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy") - hud_list[LIFE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy") - hud_list[ID_HUD] = new /image/hud_overlay(global.using_map.id_hud_icons, src, "hudunknown") - hud_list[WANTED_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPLOYAL_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPCHEM_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPTRACK_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[SPECIALROLE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[STATUS_HUD_OOC] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealthy") - /mob/living/human/Destroy() global.human_mob_list -= src regenerate_body_icon = FALSE // don't bother regenerating if we happen to be queued to update icon diff --git a/code/modules/mob/living/human/human_movement.dm b/code/modules/mob/living/human/human_movement.dm index a31e6788e00e..39f3c3a28416 100644 --- a/code/modules/mob/living/human/human_movement.dm +++ b/code/modules/mob/living/human/human_movement.dm @@ -118,8 +118,7 @@ handle_leg_damage() species.handle_post_move(src) if(client) - var/turf/B = GetAbove(src) - up_hint.icon_state = "uphint[!!(B && TURF_IS_MIMICKING(B))]" + up_hint.update_icon() /mob/living/human/proc/handle_leg_damage() if(!can_feel_pain()) diff --git a/code/modules/mob/living/human/life.dm b/code/modules/mob/living/human/life.dm index 1bb84a587db9..ebc47ef12025 100644 --- a/code/modules/mob/living/human/life.dm +++ b/code/modules/mob/living/human/life.dm @@ -746,7 +746,8 @@ if(I) var/datum/job/J = SSjobs.get_by_title(I.GetJobName()) if(J) - holder.icon_state = J.hud_icon + holder.icon = J.hud_icon + holder.icon_state = J.hud_icon_state hud_list[ID_HUD] = holder @@ -781,17 +782,16 @@ var/image/holder2 = hud_list[IMPLOYAL_HUD] var/image/holder3 = hud_list[IMPCHEM_HUD] - holder1.icon_state = "hudblank" - holder2.icon_state = "hudblank" - holder3.icon_state = "hudblank" - + holder1.icon_state = "hud_imp_blank" + holder2.icon_state = "hud_imp_blank" + holder3.icon_state = "hud_imp_blank" for(var/obj/item/implant/I in src) if(I.implanted) if(istype(I,/obj/item/implant/tracking)) holder1.icon_state = "hud_imp_tracking" - if(istype(I,/obj/item/implant/loyalty)) + else if(istype(I,/obj/item/implant/loyalty)) holder2.icon_state = "hud_imp_loyal" - if(istype(I,/obj/item/implant/chem)) + else if(istype(I,/obj/item/implant/chem)) holder3.icon_state = "hud_imp_chem" hud_list[IMPTRACK_HUD] = holder1 diff --git a/code/modules/mob/living/inventory.dm b/code/modules/mob/living/inventory.dm index 903b1bc8ecb3..f0ab7bdc92eb 100644 --- a/code/modules/mob/living/inventory.dm +++ b/code/modules/mob/living/inventory.dm @@ -62,11 +62,8 @@ if(slot != last_slot && (slot in get_held_item_slots())) _held_item_slot_selected = slot if(istype(hud_used)) - for(var/obj/screen/inventory/hand in hud_used.hand_hud_objects) - hand.cut_overlay("hand_selected") - if(hand.slot_id == slot) - hand.add_overlay("hand_selected") - hand.compile_overlays() + for(var/atom/hand as anything in hud_used.hand_hud_objects) + hand.update_icon() var/obj/item/I = get_active_held_item() if(istype(I)) I.on_active_hand() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 78ba364f39a6..a9f88a6c596c 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -694,7 +694,14 @@ default behaviour is: /mob/living/proc/has_brain() return TRUE -/mob/living/proc/slip(var/slipped_on, stun_duration = 8) +// We are jumping, levitating or being thrown. +/mob/living/immune_to_floor_hazards() + . = ..() || is_floating + +/mob/living/proc/slip(slipped_on, stun_duration = 8) + + if(immune_to_floor_hazards()) + return FALSE var/decl/species/my_species = get_species() if(my_species?.check_no_slip(src)) @@ -1205,6 +1212,7 @@ default behaviour is: expected_user_type = /mob/observer expected_target_type = /mob/living interaction_flags = 0 + examine_desc = null // DO NOT show this in general. /decl/interaction_handler/admin_kill/is_possible(atom/target, mob/user, obj/item/prop) . = ..() @@ -1585,7 +1593,7 @@ default behaviour is: /mob/living/proc/handle_walking_tracks(turf/T, old_loc) - if(!T.can_show_footsteps()) + if(!T.can_show_coating_footprints()) return // Tracking blood or other contaminants @@ -1923,8 +1931,8 @@ default behaviour is: var/screen_locs = gear.get_preview_screen_locs() if(screen_locs) return screen_locs - var/decl/species/my_species = get_species() - return my_species?.character_preview_screen_locs + var/decl/bodytype/my_bodytype = get_bodytype() + return my_bodytype?.character_preview_screen_locs /mob/living/can_twohand_item(obj/item/item) if(!istype(item) || !item.can_be_twohanded) diff --git a/code/modules/mob/living/living_hud.dm b/code/modules/mob/living/living_hud.dm new file mode 100644 index 000000000000..5e6b7adfff0d --- /dev/null +++ b/code/modules/mob/living/living_hud.dm @@ -0,0 +1,17 @@ +/mob/living + var/list/hud_list = new(10) + +/mob/living/proc/reset_hud_overlays() + hud_list = new(10) + hud_list[HEALTH_HUD] = new /image/hud_overlay(global.using_map.med_hud_icons, src, "blank") + hud_list[STATUS_HUD] = new /image/hud_overlay(global.using_map.hud_icons, src, "hudhealthy") + hud_list[LIFE_HUD] = new /image/hud_overlay(global.using_map.hud_icons, src, "hudhealthy") + hud_list[ID_HUD] = new /image/hud_overlay(global.using_map.hud_icons, src, "hudunknown") + hud_list[WANTED_HUD] = new /image/hud_overlay(global.using_map.hud_icons, src, "hudblank") + hud_list[IMPLOYAL_HUD] = new /image/hud_overlay(global.using_map.implant_hud_icons, src, "hud_imp_blank") + hud_list[IMPCHEM_HUD] = new /image/hud_overlay(global.using_map.implant_hud_icons, src, "hud_imp_blank") + hud_list[IMPTRACK_HUD] = new /image/hud_overlay(global.using_map.implant_hud_icons, src, "hud_imp_blank") + hud_list[SPECIALROLE_HUD] = new /image/hud_overlay(global.using_map.hud_icons, src, "hudblank") + hud_list[STATUS_HUD_OOC] = new /image/hud_overlay(global.using_map.hud_icons, src, "hudhealthy") + +/datum/map diff --git a/code/modules/mob/living/living_maneuvers.dm b/code/modules/mob/living/living_maneuvers.dm index 8913f7a8190d..2afaa16ad4c0 100644 --- a/code/modules/mob/living/living_maneuvers.dm +++ b/code/modules/mob/living/living_maneuvers.dm @@ -25,13 +25,13 @@ forceMove(get_turf(origin)) prepared_maneuver.perform(src, check, get_acrobatics_multiplier(prepared_maneuver), reflexively = TRUE) prepared_maneuver = null - maneuver_icon?.icon_state = "maneuver_off" + maneuver_icon?.update_icon() /mob/living/proc/try_maneuver(var/atom/target) if(prepared_maneuver && (isturf(target) || isturf(target.loc))) // Avoid trying to jump at your backpack contents. prepared_maneuver.perform(src, get_turf(target), get_acrobatics_multiplier(prepared_maneuver)) prepared_maneuver = null - maneuver_icon?.icon_state = "maneuver_off" + maneuver_icon?.update_icon() return TRUE return FALSE @@ -59,19 +59,18 @@ if(!maneuver.can_be_used_by(src, null)) return prepared_maneuver = maneuver - maneuver_icon?.icon_state = "maneuver_on" to_chat(src, SPAN_NOTICE("You prepare to [prepared_maneuver.name].")) else prepared_maneuver = null - maneuver_icon?.icon_state = "maneuver_off" to_chat(src, SPAN_NOTICE("You are no longer preparing to perform a maneuver.")) + maneuver_icon?.update_icon() /mob/living/proc/perform_maneuver(var/maneuver, var/atom/target) var/decl/maneuver/performing_maneuver = ispath(maneuver) ? GET_DECL(maneuver) : maneuver if(istype(performing_maneuver)) . = performing_maneuver.perform(src, target, get_acrobatics_multiplier(performing_maneuver)) prepared_maneuver = null - maneuver_icon?.icon_state = "maneuver_off" + maneuver_icon?.update_icon() /mob/living/proc/get_acrobatics_multiplier(var/decl/maneuver/attempting_maneuver) return 1 diff --git a/code/modules/mob/living/living_status.dm b/code/modules/mob/living/living_status.dm index 661787ae356d..645b53234486 100644 --- a/code/modules/mob/living/living_status.dm +++ b/code/modules/mob/living/living_status.dm @@ -1,9 +1,11 @@ /mob // Defined on /mob to avoid having to pass args to every single attack_foo() proc. - var/datum/status_marker_holder/status_markers var/list/status_counters var/list/pending_status_counters + var/datum/status_marker_holder/status_markers /mob/living/set_status(var/condition, var/amount) + if(QDELETED(src)) + return FALSE if(!ispath(condition, /decl/status_condition)) return FALSE var/decl/status_condition/cond = GET_DECL(condition) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index e9920873353f..230f370eda24 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -149,15 +149,7 @@ var/global/list/ai_verbs_default = list( . = INITIALIZE_HINT_QDEL else if(brainmob.mind) brainmob.mind.transfer_to(src) - hud_list[HEALTH_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[STATUS_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[LIFE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[ID_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[WANTED_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPLOYAL_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPCHEM_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPTRACK_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[SPECIALROLE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") + reset_hud_overlays() ai_list += src create_powersupply() diff --git a/code/modules/mob/living/silicon/robot/flying/module_flying_repair.dm b/code/modules/mob/living/silicon/robot/flying/module_flying_repair.dm index 8a060e833c2f..259ac5bf9a58 100644 --- a/code/modules/mob/living/silicon/robot/flying/module_flying_repair.dm +++ b/code/modules/mob/living/silicon/robot/flying/module_flying_repair.dm @@ -4,8 +4,7 @@ channels = list ("Engineering" = TRUE) camera_channels = list(CAMERA_CAMERA_CHANNEL_ENGINEERING) software = list( - /datum/computer_file/program/power_monitor, - /datum/computer_file/program/supermatter_monitor + /datum/computer_file/program/power_monitor ) module_sprites = list( "Drone" = 'icons/mob/robots/flying/flying_engineering.dmi', diff --git a/code/modules/mob/living/silicon/robot/modules/_module.dm b/code/modules/mob/living/silicon/robot/modules/_module.dm index 87216dc3704f..ee0046ef2ae5 100644 --- a/code/modules/mob/living/silicon/robot/modules/_module.dm +++ b/code/modules/mob/living/silicon/robot/modules/_module.dm @@ -233,3 +233,6 @@ var/obj/item/stock_parts/computer/hard_drive/disk = os.get_component(PART_HDD) for(var/T in software) disk.store_file(new T(disk), OS_PROGRAMS_DIR, TRUE) + +/obj/item/robot_module/proc/handle_turf(turf/target, mob/user) + return diff --git a/code/modules/mob/living/silicon/robot/modules/module_engineering.dm b/code/modules/mob/living/silicon/robot/modules/module_engineering.dm index d79de772719c..d0b1f9456e3d 100644 --- a/code/modules/mob/living/silicon/robot/modules/module_engineering.dm +++ b/code/modules/mob/living/silicon/robot/modules/module_engineering.dm @@ -8,8 +8,7 @@ CAMERA_CAMERA_CHANNEL_ENGINEERING ) software = list( - /datum/computer_file/program/power_monitor, - /datum/computer_file/program/supermatter_monitor + /datum/computer_file/program/power_monitor ) supported_upgrades = list( /obj/item/borg/upgrade/rcd diff --git a/code/modules/mob/living/silicon/robot/modules/module_janitor.dm b/code/modules/mob/living/silicon/robot/modules/module_janitor.dm index 651a88e5b4e1..e88d8b131125 100644 --- a/code/modules/mob/living/silicon/robot/modules/module_janitor.dm +++ b/code/modules/mob/living/silicon/robot/modules/module_janitor.dm @@ -23,10 +23,13 @@ ) emag = /obj/item/chems/spray +/obj/item/robot_module/janitor/handle_turf(turf/target, mob/user) + target.clean() + /obj/item/robot_module/janitor/finalize_emag() . = ..() emag.add_to_reagents(/decl/material/liquid/lube, 250) - emag.SetName("Lube spray") + emag.SetName("lubricant spray") /obj/item/robot_module/janitor/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) ..() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 08ee95501bd6..4421aabf243b 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -88,6 +88,9 @@ ) /mob/living/silicon/robot/Initialize() + + reset_hud_overlays() + . = ..() add_language(/decl/language/binary, 1) @@ -126,16 +129,6 @@ // Disables lay down verb for robots due they're can't lay down and it cause some movement, vision issues. verbs -= /mob/living/verb/lay_down - hud_list[HEALTH_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[STATUS_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealth100") - hud_list[LIFE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudhealth100") - hud_list[ID_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[WANTED_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPLOYAL_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPCHEM_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[IMPTRACK_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - hud_list[SPECIALROLE_HUD] = new /image/hud_overlay('icons/mob/hud.dmi', src, "hudblank") - AddMovementHandler(/datum/movement_handler/robot/use_power, /datum/movement_handler/mob/space) /mob/living/silicon/robot/proc/recalculate_synth_capacities() @@ -824,15 +817,15 @@ /mob/living/silicon/robot/Move(a, b, flag) . = ..() if(.) + if(module && isturf(loc)) var/obj/item/ore/orebag = locate() in list(module_state_1, module_state_2, module_state_3) if(orebag) loc.attackby(orebag, src) - if(istype(module, /obj/item/robot_module/janitor)) - loc.clean() + module.handle_turf(loc, src) + if(client) - var/turf/above = GetAbove(src) - up_hint.icon_state = "uphint[!!(above && TURF_IS_MIMICKING(above))]" + up_hint.update_icon() /mob/living/silicon/robot/proc/UnlinkSelf() disconnect_from_ai() diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 52457ceb078c..0ec86995affa 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -10,7 +10,6 @@ var/list/stating_laws = list()// Channels laws are currently being stated on var/obj/item/radio/silicon_radio - var/list/hud_list[10] var/list/speech_synthesizer_langs = list() //which languages can be vocalized by the speech synthesizer //Used in say.dm. @@ -40,6 +39,7 @@ #define MED_HUD 2 //Medical HUD mode /mob/living/silicon/Initialize() + reset_hud_overlays() global.silicon_mob_list += src . = ..() 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 be7858c6c04d..6571031649c7 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -245,7 +245,7 @@ var/global/chicken_count = 0 global.chicken_count -= 1 /mob/living/simple_animal/fowl/chicken/attackby(var/obj/item/O, var/mob/user) - if(istype(O, /obj/item/food)) + if(!istype(O, /obj/item/food)) return ..() var/obj/item/food/G = O //feedin' dem chickens if(findtext(G.get_grown_tag(), "wheat")) // includes chopped, crushed, dried etc. diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 7903631bb68a..3bd462aca867 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -113,11 +113,6 @@ update_action_buttons() update_mouse_pointer() - if(ability_master) - ability_master.update_abilities(TRUE, src) - ability_master.toggle_open(1) - ability_master.synch_spells_to_mind(mind) - if(get_preference_value(/datum/client_preference/show_status_markers) == PREF_SHOW) if(status_markers?.mob_image_personal) client.images |= status_markers.mob_image_personal @@ -130,7 +125,7 @@ if(istype(hud_used)) hud_used.hidden_inventory_update() - hud_used.persistant_inventory_update() + hud_used.persistent_inventory_update() update_action_buttons() return TRUE diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 03827667a287..512db5f11bab 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -17,8 +17,6 @@ QDEL_NULL(hud_used) if(active_storage) active_storage.close(src) - if(istype(ability_master)) - QDEL_NULL(ability_master) if(istype(skillset)) QDEL_NULL(skillset) QDEL_NULL_LIST(grabbed_by) @@ -57,7 +55,6 @@ QDEL_NULL_SCREEN(radio_use_icon) QDEL_NULL_SCREEN(gun_move_icon) QDEL_NULL_SCREEN(gun_setting_icon) - QDEL_NULL_SCREEN(ability_master) QDEL_NULL_SCREEN(zone_sel) /mob/Initialize() @@ -68,7 +65,6 @@ if(!istype(move_intent)) move_intent = GET_DECL(move_intent) . = ..() - ability_master = new(null, src) refresh_ai_handler() START_PROCESSING(SSmobs, src) @@ -242,8 +238,6 @@ SHOULD_NOT_SLEEP(TRUE) if(QDELETED(src)) return PROCESS_KILL - if(ability_master) - ability_master.update_spells(0) #define UNBUCKLED 0 #define PARTIALLY_BUCKLED 1 @@ -896,7 +890,7 @@ /mob/proc/toggle_throw_mode(force_set) in_throw_mode = isnull(force_set) ? !in_throw_mode : force_set - throw_icon?.icon_state = "act_throw_[in_throw_mode ? "on" : "off"]" + throw_icon?.update_icon() /mob/proc/toggle_antag_pool() set name = "Toggle Add-Antag Candidacy" diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 04318afb9719..ec19dd3daedb 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -60,7 +60,6 @@ var/obj/screen/gun/radio/radio_use_icon var/obj/screen/gun/move/gun_move_icon var/obj/screen/gun/mode/gun_setting_icon - var/obj/screen/ability_master/ability_master /*A bunch of this stuff really needs to go under their own defines instead of being globally attached to mob. A variable should only be globally attached to turfs/objects/whatever, when it is in fact needed as such. diff --git a/code/modules/mob/mob_intent.dm b/code/modules/mob/mob_intent.dm index 39a1a9c5606a..b55b2342ed84 100644 --- a/code/modules/mob/mob_intent.dm +++ b/code/modules/mob/mob_intent.dm @@ -29,6 +29,8 @@ var/intent_flags = 0 /// Descriptive string used in status panel. var/name + /// Descriptive string shown when examined. + var/desc /// Icon used to draw this intent in the selector. var/icon = 'icons/screen/intents.dmi' /// State used to update intent selector. @@ -51,31 +53,35 @@ // Basic subtypes. /decl/intent/harm name = "harm" + desc = "HARM INTENT: you will attempt to damage, disrupt or destroy whatever you interact with." uid = "intent_harm" intent_flags = I_FLAG_HARM icon_state = "intent_harm" - sort_order = 1 // Bottom left of intent selector. + sort_order = 4 // Corresponding to hotkey order. /decl/intent/grab name = "grab" + desc = "GRAB INTENT: you will attempt to grab hold of any object or creature you interact with." uid = "intent_grab" intent_flags = I_FLAG_GRAB icon_state = "intent_grab" - sort_order = 2 // Bottom left of the intent selector. + sort_order = 3 // Corresponding to hotkey order. /decl/intent/help name = "help" + desc = "HELP INTENT: you will attempt to assist, or in general void harming, whatever you interact with." uid = "intent_help" intent_flags = I_FLAG_HELP icon_state = "intent_help" - sort_order = 3 // Top left of the intent selector. + sort_order = 1 // Corresponding to hotkey order. /decl/intent/disarm name = "disarm" + desc = "DISARM INTENT: you will attempt to disarm or incapacitate any creature you interact with." uid = "intent_disarm" intent_flags = I_FLAG_DISARM icon_state = "intent_disarm" - sort_order = 4 // Top right of the intent selector. + sort_order = 2 // Corresponding to hotkey order. // Used by nymphs. /decl/intent/harm/binary diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 21c411010778..a934d39d2e38 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -268,8 +268,8 @@ /mob/proc/set_move_intent(var/decl/move_intent/next_intent) if(next_intent && move_intent != next_intent && next_intent.can_be_used_by(src)) move_intent = next_intent - if(istype(hud_used)) - hud_used.move_intent.icon_state = move_intent.hud_icon_state + if(istype(hud_used) && hud_used.move_intent) + hud_used.move_intent.update_icon() return TRUE return FALSE diff --git a/code/modules/mob/skills/skill.dm b/code/modules/mob/skills/skill.dm index cd0d2ec8927a..87cad27fdb3d 100644 --- a/code/modules/mob/skills/skill.dm +++ b/code/modules/mob/skills/skill.dm @@ -359,6 +359,7 @@ category = /decl/skill_category/engineering uid = "skill_engines" fallback_key = "/decl/hierarchy/skill/engineering/engines" + // TODO: These strings should be modified by the supermatter modpack somehow... desc = "Describes your knowledge of the various engine types common on space stations, such as the PACMAN, singularity, supermatter or RUST engine." levels = list( "Unskilled" = "You know that \"delamination\" is a bad thing and that you should stay away from the singularity. You know the engine provides power, but you're unclear on the specifics. If you were to try to set up the engine, you would need someone to talk you through every detail--and even then, you'd probably make deadly mistakes.
    - You can read the SM monitor readings with 40% error. This decreases with level.", diff --git a/code/modules/modular_computers/computers/modular_computer/interaction.dm b/code/modules/modular_computers/computers/modular_computer/interaction.dm index 6bb4a4f41b84..1bfc73fb6a28 100644 --- a/code/modules/modular_computers/computers/modular_computer/interaction.dm +++ b/code/modules/modular_computers/computers/modular_computer/interaction.dm @@ -136,10 +136,13 @@ /obj/item/modular_computer/get_alt_interactions(var/mob/user) . = ..() - LAZYADD(., /decl/interaction_handler/remove_id/modular_computer) - LAZYADD(., /decl/interaction_handler/remove_pen/modular_computer) - LAZYADD(., /decl/interaction_handler/emergency_shutdown) - LAZYADD(., /decl/interaction_handler/remove_chargestick) + var/static/list/_modular_computer_interactions = list( + /decl/interaction_handler/remove_id/modular_computer, + /decl/interaction_handler/remove_pen/modular_computer, + /decl/interaction_handler/emergency_shutdown, + /decl/interaction_handler/remove_chargestick + ) + LAZYADD(., _modular_computer_interactions) // // Remove ID @@ -181,6 +184,7 @@ icon = 'icons/screen/radial.dmi' icon_state = "radial_power_off" expected_target_type = /obj/item/modular_computer + examine_desc = "perform an emergency shutdown" /decl/interaction_handler/emergency_shutdown/is_possible(atom/target, mob/user, obj/item/prop) . = ..() @@ -201,6 +205,7 @@ icon = 'icons/screen/radial.dmi' icon_state = "radial_eject" expected_target_type = /obj/item/modular_computer + examine_desc = "remove a chargestick" /decl/interaction_handler/remove_chargestick/is_possible(atom/target, mob/user, obj/item/prop) . = ..() diff --git a/code/modules/modular_computers/computers/subtypes/dev_laptop.dm b/code/modules/modular_computers/computers/subtypes/dev_laptop.dm index ad7c698d6d8a..894b912aff91 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_laptop.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_laptop.dm @@ -15,7 +15,7 @@ /decl/material/solid/silicon = MATTER_AMOUNT_REINFORCEMENT, ) var/icon_state_closed = "laptop-closed" - + /obj/item/modular_computer/laptop/on_update_icon() if(anchored) ..() @@ -35,6 +35,7 @@ name = "Open Laptop" expected_target_type = /obj/item/modular_computer/laptop interaction_flags = INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEEDS_TURF + examine_desc = "open or close $TARGET_THEM$" /decl/interaction_handler/laptop_open/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/modular_computer/laptop/L = target diff --git a/code/modules/modular_computers/computers/subtypes/preset_console.dm b/code/modules/modular_computers/computers/subtypes/preset_console.dm index c726c3ac6a2a..1bc6fd711de0 100644 --- a/code/modules/modular_computers/computers/subtypes/preset_console.dm +++ b/code/modules/modular_computers/computers/subtypes/preset_console.dm @@ -48,7 +48,6 @@ /obj/machinery/computer/modular/preset/engineering default_software = list( /datum/computer_file/program/power_monitor, - /datum/computer_file/program/supermatter_monitor, /datum/computer_file/program/alarm_monitor, /datum/computer_file/program/atmos_control, /datum/computer_file/program/rcon_console, diff --git a/code/modules/modular_computers/computers/subtypes/preset_telescreen.dm b/code/modules/modular_computers/computers/subtypes/preset_telescreen.dm index 23e4122b9083..284372c00bfb 100644 --- a/code/modules/modular_computers/computers/subtypes/preset_telescreen.dm +++ b/code/modules/modular_computers/computers/subtypes/preset_telescreen.dm @@ -68,8 +68,7 @@ default_software = list( /datum/computer_file/program/alarm_monitor, /datum/computer_file/program/camera_monitor, - /datum/computer_file/program/shields_monitor, - /datum/computer_file/program/supermatter_monitor + /datum/computer_file/program/shields_monitor ) /obj/machinery/computer/modular/telescreen/preset/entertainment diff --git a/code/modules/modular_computers/file_system/programs/generic/folding.dm b/code/modules/modular_computers/file_system/programs/generic/folding.dm index 0ea98dcadb4f..ebd8214d0ffb 100644 --- a/code/modules/modular_computers/file_system/programs/generic/folding.dm +++ b/code/modules/modular_computers/file_system/programs/generic/folding.dm @@ -109,7 +109,7 @@ "Simulating Alien Abductions", "Scanning Pigeons", "Iterating Chaos Array", - "Abstracting Supermatter", + "Abstracting Exotic Matter", "Adjusting Social Network", "Recalculating Clown Principle" ) diff --git a/code/modules/multiz/level_data.dm b/code/modules/multiz/level_data.dm index 69ee279edba2..d1aeb0bdaee6 100644 --- a/code/modules/multiz/level_data.dm +++ b/code/modules/multiz/level_data.dm @@ -173,6 +173,14 @@ // Whether or not this level permits things like graffiti and filth to persist across rounds. var/permit_persistence = FALSE + // Submap loading values, passed back via getters like get_subtemplate_budget(). + /// A point budget to spend on subtemplates (see template costs) + var/subtemplate_budget = 0 + /// A string identifier for the category of subtemplates to draw from for this level. + var/subtemplate_category = null + /// A specific area to use when determining where to place subtemplates. + var/subtemplate_area = null + /datum/level_data/New(var/_z_level, var/defer_level_setup = FALSE) . = ..() level_z = _z_level @@ -418,16 +426,22 @@ // /// Helper proc for subtemplate generation. Returns a point budget to spend on subtemplates. /datum/level_data/proc/get_subtemplate_budget() - return 0 + return subtemplate_budget /// Helper proc for subtemplate generation. Returns a string identifier for a general category of template. /datum/level_data/proc/get_subtemplate_category() - return + return subtemplate_category /// Helper proc for subtemplate generation. Returns a bitflag of template flags that must not be present for a subtemplate to be considered available. /datum/level_data/proc/get_subtemplate_blacklist() return /// Helper proc for subtemplate generation. Returns a bitflag of template flags that must be present for a subtemplate to be considered available. /datum/level_data/proc/get_subtemplate_whitelist() return +/// Helper proc for getting areas associated with placable submaps on this level. +/datum/level_data/proc/get_subtemplate_areas(template_category, blacklist, whitelist) + if(subtemplate_area) + return islist(subtemplate_area) ? subtemplate_area : list(subtemplate_area) + if(base_area) + return list(base_area) ///Called when setting up the level. Apply generators and anything that modifies the turfs of the level. /datum/level_data/proc/generate_level() @@ -461,12 +475,34 @@ for(var/gen_type in map_gen) new gen_type(origx, origy, level_z, endx, endy, FALSE, TRUE, get_base_area_instance()) +/// Helper proc for placing mobs on a level after level creation. +/datum/level_data/proc/get_mobs_to_populate_level() + return + ///Called during level setup. Run anything that should happen only after the map is fully generated. /datum/level_data/proc/after_generate_level() + build_border() + if(daycycle_id && daycycle_type) SSdaycycle.register_level(level_z, daycycle_id, daycycle_type) + var/list/mobs_to_spawn = get_mobs_to_populate_level() + if(length(mobs_to_spawn)) + for(var/list/mob_category in mobs_to_spawn) + var/list/mob_types = mob_category[1] + var/mob_turf = mob_category[2] + var/mob_count = mob_category[3] + var/sanity = 1000 + while(mob_count && sanity) + sanity-- + var/turf/place_mob_at = locate(rand(level_inner_min_x, level_inner_max_x), rand(level_inner_min_y, level_inner_max_y), level_z) + if(istype(place_mob_at, mob_turf) && !(locate(/mob/living) in place_mob_at)) + var/mob_type = pickweight(mob_types) + new mob_type(place_mob_at) + mob_count-- + CHECK_TICK + ///Changes anything named we may need to rename accordingly to the parent location name. For instance, exoplanets levels. /datum/level_data/proc/adapt_location_name(var/location_name) SHOULD_CALL_PARENT(TRUE) @@ -742,9 +778,6 @@ INITIALIZE_IMMEDIATE(/obj/abstract/level_data_spawner) /datum/random_map/noise/ore ) -/datum/level_data/proc/get_subtemplate_areas(template_category, blacklist, whitelist) - return list(base_area) - ///Try to allocate the given amount of POIs onto our level. Returns the template types that were spawned /datum/level_data/proc/spawn_subtemplates(budget = 0, template_category, blacklist, whitelist) diff --git a/code/modules/multiz/mobile_ladder.dm b/code/modules/multiz/mobile_ladder.dm index 2eacd7a03ac3..dec71c399ff6 100644 --- a/code/modules/multiz/mobile_ladder.dm +++ b/code/modules/multiz/mobile_ladder.dm @@ -130,6 +130,7 @@ /decl/interaction_handler/ladder_fold name = "Fold Ladder" expected_target_type = /obj/structure/ladder/mobile + examine_desc = "fold $TARGET_THEM$ up" /decl/interaction_handler/ladder_fold/invoked(atom/target, mob/user, obj/item/prop) var/obj/structure/ladder/mobile/L diff --git a/code/modules/multiz/movement.dm b/code/modules/multiz/movement.dm index 585f57d0d7e3..573c28223f17 100644 --- a/code/modules/multiz/movement.dm +++ b/code/modules/multiz/movement.dm @@ -91,9 +91,6 @@ if(!has_gravity()) return - if(throwing) - return - if(can_fall()) begin_falling(lastloc, below) @@ -115,7 +112,7 @@ //For children to override /atom/movable/proc/can_fall(var/anchor_bypass = FALSE, var/turf/location_override = loc) - if(!simulated) + if(immune_to_floor_hazards()) return FALSE if(anchored && !anchor_bypass) diff --git a/code/modules/nano/modules/human_appearance.dm b/code/modules/nano/modules/human_appearance.dm index 4ba6ad96090d..6e22447ab9ca 100644 --- a/code/modules/nano/modules/human_appearance.dm +++ b/code/modules/nano/modules/human_appearance.dm @@ -116,7 +116,7 @@ hair_styles[++hair_styles.len] = list("hairstyle" = hair_decl.name, "ref" = "\ref[hair_decl]") data["hair_styles"] = hair_styles var/hairstyle = GET_HAIR_STYLE(owner) - var/decl/sprite_accessory/hair = GET_DECL(hairstyle) + var/decl/sprite_accessory/hair = GET_DECL(hairstyle) || GET_DECL(/decl/sprite_accessory/hair/bald) data["hair_style"] = hair.name data["change_facial_hair"] = can_change(APPEARANCE_FACIAL_HAIR) @@ -127,7 +127,7 @@ facial_hair_styles[++facial_hair_styles.len] = list("facialhairstyle" = facial_hair_decl.name, "ref" = "\ref[facial_hair_decl]") data["facial_hair_styles"] = facial_hair_styles var/facial_hairstyle = GET_FACIAL_HAIR_STYLE(owner) - var/decl/sprite_accessory/facial_hair = GET_DECL(facial_hairstyle) + var/decl/sprite_accessory/facial_hair = GET_DECL(facial_hairstyle) || GET_DECL(/decl/sprite_accessory/facial_hair/shaved) data["facial_hair_style"] = facial_hair.name data["change_hair_color"] = can_change(APPEARANCE_HAIR_COLOR) diff --git a/code/modules/organs/organ_prosthetics.dm b/code/modules/organs/organ_prosthetics.dm index 03d8abee4ae3..a107c79e8104 100644 --- a/code/modules/organs/organ_prosthetics.dm +++ b/code/modules/organs/organ_prosthetics.dm @@ -9,7 +9,7 @@ // External organ procs: // Does this bodypart count as a modular limb, and if so, what kind? /obj/item/organ/external/proc/get_modular_limb_category() - return isnull(bodytype.modular_limb_tier) ? MODULAR_BODYPART_INVALID : bodytype.modular_limb_tier + return isnull(bodytype?.modular_limb_tier) ? MODULAR_BODYPART_INVALID : bodytype.modular_limb_tier // Checks if a limb could theoretically be removed. // Note that this does not currently bother checking if a child or internal organ is vital. diff --git a/code/modules/paperwork/carbonpaper.dm b/code/modules/paperwork/carbonpaper.dm index 72eb84cc4911..5991f75c6c49 100644 --- a/code/modules/paperwork/carbonpaper.dm +++ b/code/modules/paperwork/carbonpaper.dm @@ -54,8 +54,9 @@ // Carbon Paper Alt Interactions ///////////////////////////////////////////////// /decl/interaction_handler/carbon_paper_remove - name = "remove carbon-copy" + name = "Remove Carbon-Copy" expected_target_type = /obj/item/paper/carbon + examine_desc = "remove the carbon-copy" /decl/interaction_handler/carbon_paper_remove/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/paper/carbon/paper = target diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm index d25c1d6cbe50..cd40acd76d99 100644 --- a/code/modules/paperwork/clipboard.dm +++ b/code/modules/paperwork/clipboard.dm @@ -198,6 +198,7 @@ /decl/interaction_handler/clipboard_remove_pen name = "Remove Pen" expected_target_type = /obj/item/clipboard + examine_desc = "remove the pen" /decl/interaction_handler/clipboard_remove_pen/is_possible(atom/target, mob/user, obj/item/prop) . = ..() diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 92a37e75a1be..02428e20f704 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -636,6 +636,8 @@ var/global/datum/topic_state/default/paper_state/paper_topic_state = new /decl/interaction_handler/scroll/furl name = "Furl Scroll" + examine_desc = "furl $TARGET_THEM$" /decl/interaction_handler/scroll/unfurl name = "Unfurl Scroll" + examine_desc = "unfurl $TARGET_THEM$" diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm index b01ab3044261..16a2f1f7ab97 100644 --- a/code/modules/paperwork/paper_bundle.dm +++ b/code/modules/paperwork/paper_bundle.dm @@ -517,6 +517,7 @@ /decl/interaction_handler/rename/paper_bundle name = "Rename Bundle" expected_target_type = /obj/item/paper_bundle + examine_desc = "rename $TARGET_THEM$" /decl/interaction_handler/rename/paper_bundle/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/paper_bundle/bundle = target diff --git a/code/modules/paperwork/paper_plane.dm b/code/modules/paperwork/paper_plane.dm index ac8ebc5d961e..2e183472066b 100644 --- a/code/modules/paperwork/paper_plane.dm +++ b/code/modules/paperwork/paper_plane.dm @@ -77,6 +77,7 @@ /decl/interaction_handler/make_paper_plane name = "Fold Into Paper Plane" expected_target_type = /obj/item/paper + examine_desc = "make a paper plane" /decl/interaction_handler/make_paper_plane/is_possible(obj/item/paper/target, mob/user, obj/item/prop) return ..() && !target.is_crumpled @@ -91,4 +92,4 @@ /obj/item/paper/get_alt_interactions(mob/user) . = ..() - LAZYDISTINCTADD(., /decl/interaction_handler/make_paper_plane) \ No newline at end of file + LAZYADD(., /decl/interaction_handler/make_paper_plane) \ No newline at end of file diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm index 70b9b4c453d3..3622d047f5c7 100644 --- a/code/modules/paperwork/paperbin.dm +++ b/code/modules/paperwork/paperbin.dm @@ -155,6 +155,7 @@ /decl/interaction_handler/paper_bin_dump_contents name = "Dump Contents" expected_target_type = /obj/item/paper_bin + examine_desc = "empty $TARGET_THEM$" /decl/interaction_handler/paper_bin_dump_contents/is_possible(var/obj/item/paper_bin/target, mob/user, obj/item/prop) return ..() && target.amount > 0 diff --git a/code/modules/paperwork/papershredder.dm b/code/modules/paperwork/papershredder.dm index 7905a7186749..89f88cf959a8 100644 --- a/code/modules/paperwork/papershredder.dm +++ b/code/modules/paperwork/papershredder.dm @@ -193,6 +193,7 @@ /decl/interaction_handler/empty/paper_shredder name = "Empty Bin" expected_target_type = /obj/machinery/papershredder + examine_desc = "empty $TARGET_THEM$" /decl/interaction_handler/empty/paper_shredder/is_possible(obj/machinery/papershredder/target, mob/user, obj/item/prop) return ..() && !target.is_bin_empty() diff --git a/code/modules/paperwork/pen/crayon.dm b/code/modules/paperwork/pen/crayon.dm index 0c3222998ac1..f06419b8711c 100644 --- a/code/modules/paperwork/pen/crayon.dm +++ b/code/modules/paperwork/pen/crayon.dm @@ -33,24 +33,31 @@ return if(istype(target) && target.is_floor()) - var/drawtype = input("Choose what you'd like to draw.", "Crayon scribbles") in list("graffiti","rune","letter","arrow") + var/static/list/drawtypes = list(CRAYON_DRAW_GRAFFITI, CRAYON_DRAW_RUNE, CRAYON_DRAW_LETTER, CRAYON_DRAW_ARROW) + var/drawtype = input(user, "Choose what you'd like to draw.", "Crayon scribbles") as null|anything in drawtypes var/draw_message = "drawing" switch(drawtype) - if("letter") - drawtype = input("Choose the letter.", "Crayon scribbles") in list(global.alphabet) + if(CRAYON_DRAW_LETTER) + drawtype = input(user, "Choose a letter.", "Crayon scribbles") as null|anything in global.alphabet draw_message = "drawing a letter" - if("graffiti") + if(CRAYON_DRAW_GRAFFITI) draw_message = "drawing graffiti" - if("rune") + if(CRAYON_DRAW_RUNE) draw_message = "drawing a rune" - if("arrow") - drawtype = input("Choose the arrow.", "Crayon scribbles") in list("left", "right", "up", "down") + if(CRAYON_DRAW_ARROW) + var/static/list/arrow_dirs = list("left", "right", "up", "down") + drawtype = input(user, "Choose an arrow.", "Crayon scribbles") as null|anything in arrow_dirs draw_message = "drawing an arrow" + if(!drawtype || QDELETED(src) || QDELETED(target) || QDELETED(user) || user.get_active_held_item() != src || !CanPhysicallyInteractWith(user, target)) + return TRUE + if(do_tool_interaction(TOOL_PEN, user, target, 5 SECONDS, draw_message, "drawing on", fuel_expenditure = 1)) - new /obj/effect/decal/cleanable/crayon(target, stroke_color, shade_color, drawtype) + var/obj/effect/decal/cleanable/crayon/graffiti = new(target, stroke_color, shade_color, drawtype) target.add_fingerprint(user) // Adds their fingerprints to the floor the crayon is drawn on. - return + graffiti.add_fingerprint(user) + + return TRUE /obj/item/pen/crayon/red stroke_color = "#da0000" diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 712c2d6c2b65..5d816b92448e 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -268,6 +268,7 @@ /decl/interaction_handler/empty/photocopier_paper_bin name = "Empty Paper Bin" expected_target_type = /obj/machinery/photocopier + examine_desc = "empty $TARGET_THEM$" /decl/interaction_handler/empty/photocopier_paper_bin/is_possible(obj/machinery/photocopier/target, mob/user, obj/item/prop) return (target.printer?.get_amount_paper() > 0) && ..() @@ -288,6 +289,7 @@ /decl/interaction_handler/remove/photocopier_scanner_item name = "Remove Item From Scanner" expected_target_type = /obj/machinery/photocopier + examine_desc = "remove a loaded item" /decl/interaction_handler/remove/photocopier_scanner_item/is_possible(obj/machinery/photocopier/target, mob/user, obj/item/prop) return target.scanner_item && ..() diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm index 6e18e36decb0..eb9bbb76a03b 100644 --- a/code/modules/paperwork/photography.dm +++ b/code/modules/paperwork/photography.dm @@ -398,6 +398,7 @@ icon = 'icons/screen/radial.dmi' icon_state = "radial_eject" expected_target_type = /obj/item/camera + examine_desc = "eject the film" /decl/interaction_handler/camera_eject_film/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/camera/camera = target diff --git a/code/modules/paperwork/printer.dm b/code/modules/paperwork/printer.dm index 7cfeaa96c43d..0f91439ab58b 100644 --- a/code/modules/paperwork/printer.dm +++ b/code/modules/paperwork/printer.dm @@ -423,6 +423,7 @@ /decl/interaction_handler/empty/stock_parts_printer name = "Empty Paper Bin" expected_target_type = /obj/item/stock_parts/printer + examine_desc = "empty $TARGET_THEM$" /decl/interaction_handler/empty/stock_parts_printer/is_possible(obj/item/stock_parts/printer/target, mob/user, obj/item/prop) return (target.get_amount_paper() > 0) && ..() diff --git a/code/modules/persistence/persistence_datum.dm b/code/modules/persistence/persistence_datum.dm index 557ae252b88a..027081f79492 100644 --- a/code/modules/persistence/persistence_datum.dm +++ b/code/modules/persistence/persistence_datum.dm @@ -26,14 +26,16 @@ return TRUE /decl/persistence_handler/proc/CheckTokenSanity(var/list/tokens) - return ( \ - islist(tokens) && \ - !isnull(tokens["x"]) && \ - !isnull(tokens["y"]) && \ - !isnull(tokens["z"]) && \ - !isnull(tokens["age"]) && \ - tokens["age"] <= entries_expire_at \ - ) + if(!islist(tokens)) + return FALSE + if(isnull(tokens["x"]) || isnull(tokens["y"]) || isnull(tokens["z"])) + return FALSE + if(!isnull(entries_expire_at)) + if(isnull(tokens["age"])) + return FALSE + if(tokens["age"] > entries_expire_at) + return FALSE + return TRUE /decl/persistence_handler/proc/CreateEntryInstance(var/turf/creating, var/list/tokens) return @@ -59,8 +61,9 @@ else return - if(GetValidTurf(locate(tokens["x"], tokens["y"], tokens["z"]), tokens)) - return CreateEntryInstance(., tokens) + . = GetValidTurf(locate(tokens["x"], tokens["y"], tokens["z"]), tokens) + if(.) + . = CreateEntryInstance(., tokens) /decl/persistence_handler/proc/IsValidEntry(var/atom/entry) if(!istype(entry)) diff --git a/code/modules/persistence/persistence_datum_book.dm b/code/modules/persistence/persistence_datum_book.dm index 479a9c8cb454..cf33c5df07d4 100644 --- a/code/modules/persistence/persistence_datum_book.dm +++ b/code/modules/persistence/persistence_datum_book.dm @@ -5,7 +5,14 @@ ignore_invalid_loc = TRUE /decl/persistence_handler/book/CreateEntryInstance(var/turf/creating, var/list/tokens) - var/obj/item/book/book = new(creating) + + var/book_type = tokens["book_type"] + if(book_type) + book_type = text2path(book_type) + if(!ispath(book_type)) + book_type = /obj/item/book + + var/obj/item/book/book = new book_type(creating) book.dat = tokens["message"] book.title = tokens["title"] book.author = tokens["writer"] @@ -29,11 +36,12 @@ . = ..() var/obj/item/book/book = entry - .["author"] = book.last_modified_ckey || "" - .["message"] = book.dat || "dat" - .["title"] = book.title || "Untitled" - .["writer"] = book.author || "unknown" + .["author"] = book.last_modified_ckey || "" + .["message"] = book.dat || "dat" + .["title"] = book.title || "Untitled" + .["writer"] = book.author || "unknown" .["icon_state"] = book.icon_state || "book" + .["book_type"] = "[book.type]" var/turf/T = get_turf(entry) if(!T || !isStationLevel(T.z)) @@ -62,7 +70,7 @@ else T = get_random_spawn_turf(SPAWN_FLAG_PERSISTENCE_CAN_SPAWN) - . = ..(T, tokens) + . = ..() /decl/persistence_handler/book/GetEntryAge(var/atom/entry) . = -1 diff --git a/code/modules/supermatter/setup_supermatter.dm b/code/modules/power/admin_setup_engine.dm similarity index 52% rename from code/modules/supermatter/setup_supermatter.dm rename to code/modules/power/admin_setup_engine.dm index 4af1f8aa34cb..e5aae9005847 100644 --- a/code/modules/supermatter/setup_supermatter.dm +++ b/code/modules/power/admin_setup_engine.dm @@ -1,101 +1,7 @@ -#define SETUP_OK 1 // All good -#define SETUP_WARNING 2 // Something that shouldn't happen happened, but it's not critical so we will continue -#define SETUP_ERROR 3 // Something bad happened, and it's important so we won't continue setup. -#define SETUP_DELAYED 4 // Wait for other things first. - -#define ENERGY_NITROGEN 115 // Roughly 8 emitter shots. -#define ENERGY_CARBONDIOXIDE 150 // Roughly 10 emitter shots. -#define ENERGY_HYDROGEN 300 // Roughly 20 emitter shots. - -/datum/admins/proc/setup_supermatter() - set category = "Debug" - set name = "Setup Supermatter" - set desc = "Allows you to start the Supermatter engine." - - if (!istype(src,/datum/admins)) - src = usr.client.holder - if (!istype(src,/datum/admins)) - to_chat(usr, "Error: you are not an admin!") - return - - var/response = input(usr, "Are you sure? This will start up the engine with selected gas as coolant.", "Engine setup") as null|anything in list("N2", "CO2", "H2", "Abort") - if(!response || response == "Abort") - return - - var/errors = 0 - var/warnings = 0 - var/success = 0 - - log_and_message_admins("## SUPERMATTER SETUP - Setup initiated by [usr] using coolant type [response].") - - // CONFIGURATION PHASE - // Coolant canisters, set types according to response. - for(var/obj/effect/engine_setup/coolant_canister/C in global.engine_setup_markers) - switch(response) - if("N2") - C.canister_type = /obj/machinery/portable_atmospherics/canister/nitrogen/engine_setup/ - continue - if("CO2") - C.canister_type = /obj/machinery/portable_atmospherics/canister/carbon_dioxide/engine_setup/ - continue - if("H2") - C.canister_type = /obj/machinery/portable_atmospherics/canister/hydrogen/engine_setup/ - continue - - for(var/obj/effect/engine_setup/core/C in global.engine_setup_markers) - switch(response) - if("N2") - C.energy_setting = ENERGY_NITROGEN - continue - if("CO2") - C.energy_setting = ENERGY_CARBONDIOXIDE - continue - if("H2") - C.energy_setting = ENERGY_HYDROGEN - continue - - for(var/obj/effect/engine_setup/filter/F in global.engine_setup_markers) - F.coolant = response - - var/list/delayed_objects = list() - // SETUP PHASE - for(var/obj/effect/engine_setup/S in global.engine_setup_markers) - var/result = S.activate(0) - switch(result) - if(SETUP_OK) - success++ - continue - if(SETUP_WARNING) - warnings++ - continue - if(SETUP_ERROR) - errors++ - log_and_message_admins("## SUPERMATTER SETUP - Error encountered! Aborting.") - break - if(SETUP_DELAYED) - delayed_objects.Add(S) - continue - - if(!errors) - for(var/obj/effect/engine_setup/S in delayed_objects) - var/result = S.activate(1) - switch(result) - if(SETUP_OK) - success++ - continue - if(SETUP_WARNING) - warnings++ - continue - if(SETUP_ERROR) - errors++ - log_and_message_admins("## SUPERMATTER SETUP - Error encountered! Aborting.") - break - - log_and_message_admins("## SUPERMATTER SETUP - Setup completed with [errors] errors, [warnings] warnings and [success] successful steps.") - - return - - +#define ENGINE_SETUP_OK 1 // All good +#define ENGINE_SETUP_WARNING 2 // Something that shouldn't happen happened, but it's not critical so we will continue +#define ENGINE_SETUP_ERROR 3 // Something bad happened, and it's important so we won't continue setup. +#define ENGINE_SETUP_DELAYED 4 // Wait for other things first. var/global/list/engine_setup_markers = list() @@ -122,7 +28,7 @@ var/global/list/engine_setup_markers = list() // Tries to locate a pump, enables it, and sets it to MAX. Triggers warning if unable to locate a pump. -/obj/effect/engine_setup/pump_max/ +/obj/effect/engine_setup/pump_max name = "Pump Setup Marker" /obj/effect/engine_setup/pump_max/activate() @@ -130,15 +36,15 @@ var/global/list/engine_setup_markers = list() var/obj/machinery/atmospherics/binary/pump/P = locate() in get_turf(src) if(!P) log_and_message_admins("## WARNING: Unable to locate pump at [x] [y] [z]!") - return SETUP_WARNING + return ENGINE_SETUP_WARNING P.target_pressure = P.max_pressure_setting P.update_use_power(POWER_USE_IDLE) - return SETUP_OK + return ENGINE_SETUP_OK // Spawns an empty canister on this turf, if it has a connector port. Triggers warning if unable to find a connector port -/obj/effect/engine_setup/empty_canister/ +/obj/effect/engine_setup/empty_canister name = "Empty Canister Marker" /obj/effect/engine_setup/empty_canister/activate() @@ -146,16 +52,16 @@ var/global/list/engine_setup_markers = list() var/obj/machinery/atmospherics/portables_connector/P = locate() in get_turf(src) if(!P) log_and_message_admins("## WARNING: Unable to locate connector port at [x] [y] [z]!") - return SETUP_WARNING + return ENGINE_SETUP_WARNING new/obj/machinery/portable_atmospherics/canister(get_turf(src)) // Canisters automatically connect to connectors in New() - return SETUP_OK + return ENGINE_SETUP_OK // Spawns a coolant canister on this turf, if it has a connector port. // Triggers error when unable to locate connector port or when coolant canister type is unset. -/obj/effect/engine_setup/coolant_canister/ +/obj/effect/engine_setup/coolant_canister name = "Coolant Canister Marker" var/canister_type = null @@ -164,33 +70,12 @@ var/global/list/engine_setup_markers = list() var/obj/machinery/atmospherics/portables_connector/P = locate() in get_turf(src) if(!P) log_and_message_admins("## ERROR: Unable to locate coolant connector port at [x] [y] [z]!") - return SETUP_ERROR + return ENGINE_SETUP_ERROR if(!canister_type) log_and_message_admins("## ERROR: Canister type unset at [x] [y] [z]!") - return SETUP_ERROR + return ENGINE_SETUP_ERROR new canister_type(get_turf(src)) - return SETUP_OK - - - -// Energises the supermatter. Errors when unable to locate supermatter. -/obj/effect/engine_setup/core/ - name = "Supermatter Core Marker" - var/energy_setting = 0 - -/obj/effect/engine_setup/core/activate(var/last = 0) - if(!last) - return SETUP_DELAYED - ..() - var/obj/machinery/power/supermatter/SM = locate() in get_turf(src) - if(!SM) - log_and_message_admins("## ERROR: Unable to locate supermatter core at [x] [y] [z]!") - return SETUP_ERROR - if(!energy_setting) - log_and_message_admins("## ERROR: Energy setting unset at [x] [y] [z]!") - return SETUP_ERROR - SM.power = energy_setting - return SETUP_OK + return ENGINE_SETUP_OK @@ -211,13 +96,13 @@ var/global/list/engine_setup_markers = list() var/obj/machinery/power/smes/S = locate() in get_turf(src) if(!S) log_and_message_admins("## WARNING: Unable to locate SMES unit at [x] [y] [z]!") - return SETUP_WARNING + return ENGINE_SETUP_WARNING S.input_attempt = 1 S.input_level = min(target_input_level, S.input_level_max) S.output_attempt = 1 S.output_level = min(target_output_level, S.output_level_max) S.update_icon() - return SETUP_OK + return ENGINE_SETUP_OK // Sets up filters. This assumes filters are set to filter out CO2 back to the core loop by default! /obj/effect/engine_setup/filter @@ -229,10 +114,10 @@ var/global/list/engine_setup_markers = list() var/obj/machinery/atmospherics/omni/filter/F = locate() in get_turf(src) if(!F) log_and_message_admins("## WARNING: Unable to locate omni filter at [x] [y] [z]!") - return SETUP_WARNING + return ENGINE_SETUP_WARNING if(!coolant) log_and_message_admins("## WARNING: No coolant type set at [x] [y] [z]!") - return SETUP_WARNING + return ENGINE_SETUP_WARNING // Non-co2 coolant, adjust the filter's config first. if(coolant != "CO2") @@ -247,11 +132,11 @@ var/global/list/engine_setup_markers = list() break else log_and_message_admins("## WARNING: Inapropriate filter coolant type set at [x] [y] [z]!") - return SETUP_WARNING + return ENGINE_SETUP_WARNING F.rebuild_filtering_list() F.update_use_power(POWER_USE_IDLE) - return SETUP_OK + return ENGINE_SETUP_OK // Closes the monitoring room shutters so the first Engi to show up doesn't get microwaved /obj/effect/engine_setup/shutters @@ -262,7 +147,7 @@ var/global/list/engine_setup_markers = list() /obj/effect/engine_setup/shutters/activate() if(!target_button) log_and_message_admins("## WARNING: No button type set at [x] [y] [z]!") - return SETUP_WARNING + return ENGINE_SETUP_WARNING var/obj/machinery/button/blast_door/found = null var/turf/T = get_turf(src) for(var/obj/machinery/button/blast_door/B in T.contents) @@ -271,15 +156,7 @@ var/global/list/engine_setup_markers = list() break if(!found) log_and_message_admins("## WARNING: Unable to locate button at [x] [y] [z]!") - return SETUP_WARNING + return ENGINE_SETUP_WARNING found.activate() found.update_icon() - return SETUP_OK - -#undef SETUP_OK -#undef SETUP_WARNING -#undef SETUP_ERROR -#undef SETUP_DELAYED -#undef ENERGY_NITROGEN -#undef ENERGY_CARBONDIOXIDE -#undef ENERGY_HYDROGEN + return ENGINE_SETUP_OK \ No newline at end of file diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index dd74a49e3d3b..78f587767eef 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -166,50 +166,47 @@ By design, d1 is the smallest direction and d2 is the highest // // TODO: take a closer look at cable attackby, make it call parent? -/obj/structure/cable/attackby(obj/item/W, mob/user) - if(IS_WIRECUTTER(W)) - cut_wire(W, user) +/obj/structure/cable/attackby(obj/item/used_item, mob/user) - else if(IS_COIL(W)) - var/obj/item/stack/cable_coil/coil = W + if(IS_WIRECUTTER(used_item)) + cut_wire(used_item, user) + return TRUE + + if(IS_COIL(used_item)) + var/obj/item/stack/cable_coil/coil = used_item if (coil.get_amount() < 1) to_chat(user, "You don't have enough cable to lay down.") return TRUE coil.cable_join(src, user) + return TRUE - else if(IS_MULTITOOL(W)) - + if(IS_MULTITOOL(used_item)) if(powernet && (powernet.avail > 0)) // is it powered? to_chat(user, SPAN_WARNING("[get_wattage()] in power network.")) - + shock(user, 5, 0.2) else to_chat(user, SPAN_WARNING("\The [src] is not powered.")) + return TRUE - shock(user, 5, 0.2) - - - else if(W.edge) - + if(used_item.edge) var/delay_holder - - if(W.get_attack_force(user) < 5) - visible_message(SPAN_WARNING("[user] starts sawing away roughly at \the [src] with \the [W].")) + if(used_item.get_attack_force(user) < 5) + visible_message(SPAN_WARNING("[user] starts sawing away roughly at \the [src] with \the [used_item].")) delay_holder = 8 SECONDS else - visible_message(SPAN_WARNING("[user] begins to cut through \the [src] with \the [W].")) + visible_message(SPAN_WARNING("[user] begins to cut through \the [src] with \the [used_item].")) delay_holder = 3 SECONDS - if(user.do_skilled(delay_holder, SKILL_ELECTRICAL, src)) - cut_wire(W, user) - if(W.obj_flags & OBJ_FLAG_CONDUCTIBLE) + cut_wire(used_item, user) + if(used_item.obj_flags & OBJ_FLAG_CONDUCTIBLE) shock(user, 66, 0.7) else visible_message(SPAN_WARNING("[user] stops cutting before any damage is done.")) + return TRUE - src.add_fingerprint(user) - return TRUE + return ..() -/obj/structure/cable/proc/cut_wire(obj/item/W, mob/user) +/obj/structure/cable/proc/cut_wire(obj/item/used_item, mob/user) var/turf/T = get_turf(src) if(!T || !T.is_plating()) return @@ -241,13 +238,13 @@ By design, d1 is the smallest direction and d2 is the highest // shock the user with probability prb /obj/structure/cable/proc/shock(mob/user, prb, var/siemens_coeff = 1.0) - if(!prob(prb)) - return 0 + if(!prob(prb) || powernet?.avail <= 0) + return FALSE if (electrocute_mob(user, powernet, src, siemens_coeff)) spark_at(src, amount=5, cardinal_only = TRUE) if(HAS_STATUS(user, STAT_STUN)) - return 1 - return 0 + return TRUE + return FALSE // TODO: generalize to matter list and parts_type. /obj/structure/cable/create_dismantled_products(turf/T) diff --git a/code/modules/power/fuel_assembly/fuel_assembly.dm b/code/modules/power/fuel_assembly/fuel_assembly.dm index 6958f2431d2c..0527ee149418 100644 --- a/code/modules/power/fuel_assembly/fuel_assembly.dm +++ b/code/modules/power/fuel_assembly/fuel_assembly.dm @@ -87,7 +87,7 @@ /obj/item/fuel_assembly/tritium material = /decl/material/gas/hydrogen/tritium -/obj/item/fuel_assembly/supermatter +/obj/item/fuel_assembly/exotic_matter material = /decl/material/solid/exotic_matter /obj/item/fuel_assembly/hydrogen diff --git a/code/modules/power/fuel_assembly/fuel_compressor.dm b/code/modules/power/fuel_assembly/fuel_compressor.dm index f6c08c8e5650..0488d360f935 100644 --- a/code/modules/power/fuel_assembly/fuel_compressor.dm +++ b/code/modules/power/fuel_assembly/fuel_compressor.dm @@ -129,12 +129,6 @@ to_chat(user, SPAN_NOTICE("You add the contents of \the [thing] to \the [src]'s material buffer.")) return TRUE - if(istype(thing, /obj/machinery/power/supermatter/shard)) - stored_material[/decl/material/solid/exotic_matter] = 5 * SHEET_MATERIAL_AMOUNT - to_chat(user, SPAN_NOTICE("You awkwardly cram \the [thing] into \the [src]'s material buffer.")) - qdel(thing) - return TRUE - if(istype(thing, /obj/item/stack/material)) var/obj/item/stack/material/M = thing var/decl/material/mat = M.get_material() diff --git a/code/modules/power/fusion/fusion_reactions.dm b/code/modules/power/fusion/fusion_reactions.dm index 73cffcc1529d..5ff951b477b0 100644 --- a/code/modules/power/fusion/fusion_reactions.dm +++ b/code/modules/power/fusion/fusion_reactions.dm @@ -92,7 +92,7 @@ minimum_reaction_temperature = 10000 // VERY UNIDEAL REACTIONS. -/decl/fusion_reaction/helium_supermatter +/decl/fusion_reaction/helium_exotic_matter p_react = /decl/material/solid/exotic_matter s_react = /decl/material/gas/helium energy_consumption = 0 @@ -101,7 +101,7 @@ instability = 20 * FUSION_PROCESSING_TIME_MULT hidden_from_codex = TRUE -/decl/fusion_reaction/helium_supermatter/handle_reaction_special(var/obj/effect/fusion_em_field/holder) +/decl/fusion_reaction/helium_exotic_matter/handle_reaction_special(var/obj/effect/fusion_em_field/holder) set waitfor = FALSE . = 1 var/datum/event/wormholes/WM = new /datum/event/wormholes(new /datum/event_meta(EVENT_LEVEL_MAJOR)) @@ -112,8 +112,7 @@ qdel(holder) var/radiation_level = rand(100, 200) - // Copied from the SM for proof of concept. //Not any more --Cirra //Use the whole z proc --Leshana - SSradiation.z_radiate(locate(1, 1, holder.z), radiation_level, 1) + SSradiation.z_radiate(origin, radiation_level, respect_maint = TRUE) for(var/mob/living/human/H in global.living_mob_list_) var/turf/T = get_turf(H) @@ -121,10 +120,10 @@ H.set_hallucination(rand(100,150), 51) for(var/obj/machinery/fusion_fuel_injector/I in range(world.view, origin)) - if(I.cur_assembly && I.cur_assembly.material && I.cur_assembly.material.type == /decl/material/solid/exotic_matter) + if(I.cur_assembly && I.cur_assembly.material && I.cur_assembly.material.type == p_react) explosion(get_turf(I), 1, 2, 3) if(!QDELETED(I)) - QDEL_IN(I, 5) + addtimer(CALLBACK(I, TYPE_PROC_REF(/atom, physically_destroyed)), 0.5 SECONDS) sleep(5) explosion(origin, 1, 2, 5) diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index 6482521407ea..c1c8ea8295ec 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -13,7 +13,7 @@ var/global/list/singularities = list() /// Category used for investigation entries relating to this atom. var/const/investigation_label = "singulo" - /// A list of events. Toxins is in here twice to double the chance of proccing. + /// A weighted list of events. var/static/list/singularity_events = list( /decl/singularity_event/empulse = 1, /decl/singularity_event/toxins = 2, @@ -63,7 +63,7 @@ var/global/list/singularities = list() /obj/effect/singularity/explosion_act(severity) SHOULD_CALL_PARENT(FALSE) - if(current_stage.stage_size == STAGE_SUPER)//IT'S UNSTOPPABLE + if(!current_stage.explosion_vulnerable)//IT'S UNSTOPPABLE return if(severity == 1) if(prob(25)) @@ -153,16 +153,13 @@ var/global/list/singularities = list() // Handle random events. if(prob(current_stage.event_chance)) - if(current_stage.stage_size >= STAGE_SUPER) - var/decl/singularity_event/wave_event = GET_DECL(/decl/singularity_event/supermatter_wave) - wave_event.handle_event(src) - var/decl/singularity_event/singularity_event = pickweight(singularity_events) + var/decl/singularity_event/singularity_event = current_stage.forced_event || pickweight(singularity_events) singularity_event = GET_DECL(singularity_event) singularity_event.handle_event(src) /obj/effect/singularity/proc/try_move(var/movement_dir, var/vertical_move) set waitfor = FALSE - if(current_stage.stage_size >= STAGE_FIVE)//The superlarge one does not care about things in its way + if(current_stage.ignore_obstacles)//The superlarge one does not care about things in its way step(src, movement_dir) if(!vertical_move) sleep(1) diff --git a/code/modules/power/singularity/singularity_events.dm b/code/modules/power/singularity/singularity_events.dm index e48a040231be..f3bc342ac90e 100644 --- a/code/modules/power/singularity/singularity_events.dm +++ b/code/modules/power/singularity/singularity_events.dm @@ -7,10 +7,7 @@ /decl/singularity_event/nothing // Nothing happens. /decl/singularity_event/empulse/handle_event(obj/effect/singularity/source) - if(source.current_stage.stage_size != STAGE_SUPER) - empulse(source, 8, 10) - else - empulse(source, 12, 16) + empulse(source, source.current_stage.em_heavy_range, source.current_stage.em_light_range) /decl/singularity_event/toxins var/toxrange = 10 @@ -35,20 +32,10 @@ if(ishuman(M)) var/mob/living/human/H = M if(istype(H.get_equipped_item(slot_glasses_str), /obj/item/clothing/glasses/meson)) - if(source.current_stage.stage_size != STAGE_SUPER) + if(!source.current_stage.the_goggles_do_nothing) to_chat(H, SPAN_WARNING("You look directly into \the [source]. Good thing you had your protective eyewear on!")) continue to_chat(H, SPAN_WARNING("Your eyewear does absolutely nothing to protect you from \the [source]")) - to_chat(M, SPAN_DANGER("You look directly into \the [source] and feel [source.current_stage.stage_size == STAGE_SUPER ? "helpless" : "weak"].")) + to_chat(M, SPAN_DANGER("You look directly into \the [source] and feel [source.current_stage.mesmerize_text].")) M.apply_effect(3, STUN) M.visible_message(SPAN_DANGER("\The [M] stares blankly at \the [source]!")) - -/decl/singularity_event/supermatter_wave/handle_event(obj/effect/singularity/source) - for(var/mob/living/M in view(10, source.loc)) - to_chat(M, SPAN_WARNING("You hear an unearthly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat.")) - if(prob(67)) - to_chat(M, SPAN_NOTICE("Miraculously, it fails to kill you.")) - else - to_chat(M, SPAN_DANGER("You don't even have a moment to react as you are reduced to ashes by the intense radiation.")) - M.dust() - SSradiation.radiate(source, rand(source.energy)) diff --git a/code/modules/power/singularity/singularity_stages.dm b/code/modules/power/singularity/singularity_stages.dm index 831cacd48c5f..2624c10e8183 100644 --- a/code/modules/power/singularity/singularity_stages.dm +++ b/code/modules/power/singularity/singularity_stages.dm @@ -32,8 +32,22 @@ var/dissipation_energy_loss = 1 /// What is the percent chance of an event each tick? var/event_chance + /// Do we force a specific event when we proc events? + var/decl/singularity_event/forced_event = null /// Will we wander around? var/wander + /// Can explosions destroy the singularity? + var/explosion_vulnerable + /// What is the heavy range for the EM pulse event in this stage? + var/em_heavy_range = 8 + /// What is the light range for the EM pulse event in this stage? + var/em_light_range = 10 + /// What do characters feel when they're mesmerized during this stage? + var/mesmerize_text = "weak" + /// Do we ignore PPE for mesmerizing in this stage? + var/the_goggles_do_nothing = FALSE + /// Do we ignore obstacles in our way? + var/ignore_obstacles = FALSE /decl/singularity_stage/validate() . = ..() @@ -171,29 +185,7 @@ dissipates_over_time = FALSE //It cant go smaller due to e loss. wander = TRUE event_chance = 20 + ignore_obstacles = TRUE /decl/singularity_stage/stage_five/grow_to(obj/effect/singularity/source) source.visible_message(SPAN_DANGER("\The [source] has grown out of control!")) - -/decl/singularity_stage/stage_five/shrink_to(obj/effect/singularity/source) - source.visible_message(SPAN_WARNING("\The [source] miraculously reduces in size and loses its supermatter properties.")) - -/decl/singularity_stage/stage_super - name = "super gravitational singularity" - desc = "A gravitational singularity with the properties of supermatter. It has the power to destroy worlds." - min_energy = 50000 - max_energy = INFINITY - stage_size = STAGE_SUPER - footprint = 6 - icon = 'icons/effects/352x352.dmi' - icon_state = "singularity_s11"//uh, whoever drew that, you know that black holes are supposed to look dark right? What's this, the clown's singulo? - pixel_x = -160 - pixel_y = -160 - grav_pull = 16 - consume_range = 5 - dissipates_over_time = 0 //It cant go smaller due to e loss - event_chance = 25 //Events will fire off more often. - wander = TRUE - -/decl/singularity_stage/stage_super/grow_to(obj/effect/singularity/source) - source.visible_message(SPAN_SINISTER("You witness the creation of a destructive force that cannot possibly be stopped by human hands.")) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 4de22aa06166..d01aa247e4b0 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -744,6 +744,9 @@ return FALSE return TRUE +/obj/item/gun/get_quick_interaction_handler(mob/user) + return GET_DECL(/decl/interaction_handler/gun/toggle_safety) + /obj/item/gun/get_alt_interactions(mob/user) . = ..() LAZYADD(., /decl/interaction_handler/gun/toggle_safety) @@ -756,6 +759,7 @@ /decl/interaction_handler/gun/toggle_safety name = "Toggle Safety" + examine_desc = "toggle the safety" /decl/interaction_handler/gun/toggle_safety/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/gun/gun = target @@ -763,6 +767,7 @@ /decl/interaction_handler/gun/toggle_firemode name = "Change Firemode" + examine_desc = "change the firemode" /decl/interaction_handler/gun/toggle_firemode/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/gun/gun = target diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index 8534b7ddc7af..d4da8ee50454 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -360,6 +360,7 @@ /decl/interaction_handler/projectile/remove_silencer name = "Remove Silencer" + examine_desc = "remove the silencer" /decl/interaction_handler/projectile/remove_silencer/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/gun/projectile/gun = target @@ -367,6 +368,7 @@ /decl/interaction_handler/projectile/unload_ammo name = "Remove Ammunition" + examine_desc = "unload the ammunition" /decl/interaction_handler/projectile/unload_ammo/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/gun/projectile/gun = target diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index 0f54520856df..464ce437f7c3 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -74,6 +74,7 @@ /decl/interaction_handler/revolver_spin_cylinder name = "Spin Cylinder" expected_target_type = /obj/item/gun/projectile/revolver + examine_desc = "spin the cylinder" /decl/interaction_handler/revolver_spin_cylinder/invoked(atom/target, mob/user, obj/item/prop) var/obj/item/gun/projectile/revolver/R = target diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 07ad3c6c6865..152cb7a6ab55 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -14,6 +14,18 @@ is_spawnable_type = FALSE atom_damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE, ELECTROCUTE are the only things that should be in here, Try not to use PAIN as it doesn't go through stun_effect_act + // Code for handling tails, if any. + /// If the projectile leaves a trail. + var/proj_trail = FALSE + /// How long the trail lasts. + var/proj_trail_lifespan = 0 + /// What icon to use for the projectile trail. + var/proj_trail_icon = 'icons/effects/projectiles/trail.dmi' + /// What icon_state to use for the projectile trail. + var/proj_trail_icon_state = "trail" + /// Any extant trail effects. + var/list/proj_trails + var/bumped = 0 //Prevents it from hitting more than one guy at once var/def_zone = "" //Aiming at var/atom/movable/firer = null//Who shot it @@ -316,7 +328,15 @@ return /obj/item/projectile/proc/before_move() - return + if(!proj_trail || !isturf(loc) || !proj_trail_icon || !proj_trail_icon_state || !proj_trail_lifespan) + return + var/obj/effect/overlay/projectile_trail/trail = new(loc) + trail.master = src + trail.icon = proj_trail_icon + trail.icon_state = proj_trail_icon_state + trail.set_density(FALSE) + LAZYADD(proj_trails, trail) + QDEL_IN(trail, proj_trail_lifespan) /obj/item/projectile/proc/after_move() if(hitscan && tracer_type && !(locate(/obj/effect/projectile) in loc)) @@ -609,6 +629,7 @@ trajectory.initialize_location(target.x, target.y, target.z, 0, 0) /obj/item/projectile/Destroy() + QDEL_NULL_LIST(proj_trails) if(hitscan) if(loc && trajectory) var/datum/point/pcache = trajectory.copy_to() @@ -650,4 +671,4 @@ QDEL_NULL(beam_index) /obj/item/projectile/proc/update_effect(var/obj/effect/projectile/effect) - return \ No newline at end of file + return diff --git a/code/modules/projectiles/projectile/change.dm b/code/modules/projectiles/projectile/change.dm index 8e241456d22b..ff77df0fa33d 100644 --- a/code/modules/projectiles/projectile/change.dm +++ b/code/modules/projectiles/projectile/change.dm @@ -55,12 +55,9 @@ var/mob/living/new_mob = apply_transformation(M, choice) if(new_mob) new_mob.set_intent(I_FLAG_HARM) - if(M.mind) - for (var/spell/S in M.mind.learned_spells) - new_mob.add_spell(new S.type) - new_mob.set_intent(I_FLAG_HARM) - transfer_key_from_mob_to_mob(M, new_mob) - to_chat(new_mob, "Your form morphs into that of \a [choice].") + new_mob.copy_abilities_from(M) + transfer_key_from_mob_to_mob(M, new_mob) + to_chat(new_mob, "Your form morphs into that of \a [choice].") else new_mob = M if(new_mob) @@ -68,4 +65,3 @@ if(new_mob != M && !QDELETED(M)) qdel(M) - diff --git a/code/modules/projectiles/targeting/targeting_overlay.dm b/code/modules/projectiles/targeting/targeting_overlay.dm index 5d5b1f9ba654..7210efedb4c4 100644 --- a/code/modules/projectiles/targeting/targeting_overlay.dm +++ b/code/modules/projectiles/targeting/targeting_overlay.dm @@ -34,27 +34,24 @@ // Update HUD icons. if(owner.gun_move_icon) if(!(target_permissions & TARGET_CAN_MOVE)) - owner.gun_move_icon.icon_state = "no_walk0" owner.gun_move_icon.SetName("Allow Movement") else - owner.gun_move_icon.icon_state = "no_walk1" owner.gun_move_icon.SetName("Disallow Movement") + owner.gun_move_icon.update_icon() if(owner.item_use_icon) if(!(target_permissions & TARGET_CAN_CLICK)) - owner.item_use_icon.icon_state = "no_item0" owner.item_use_icon.SetName("Allow Item Use") else - owner.item_use_icon.icon_state = "no_item1" owner.item_use_icon.SetName("Disallow Item Use") + owner.item_use_icon.update_icon() if(owner.radio_use_icon) if(!(target_permissions & TARGET_CAN_RADIO)) - owner.radio_use_icon.icon_state = "no_radio0" owner.radio_use_icon.SetName("Allow Radio Use") else - owner.radio_use_icon.icon_state = "no_radio1" owner.radio_use_icon.SetName("Disallow Radio Use") + owner.radio_use_icon.update_icon() var/message = "no longer permitted to " var/use_span = "warning" @@ -206,7 +203,7 @@ if(!no_message) to_chat(owner, "You will no longer aim rather than fire.") owner.client.remove_gun_icons() - owner.gun_setting_icon.icon_state = "gun[active]" + owner.gun_setting_icon.update_icon() /obj/aiming_overlay/proc/cancel_aiming(var/no_message = 0) if(!aiming_with || !aiming_at) diff --git a/code/modules/random_map/drop/drop_types.dm b/code/modules/random_map/drop/drop_types.dm index a9f290a0aa65..1560263f9968 100644 --- a/code/modules/random_map/drop/drop_types.dm +++ b/code/modules/random_map/drop/drop_types.dm @@ -22,12 +22,6 @@ var/global/list/datum/supply_drop_loot/supply_drop /datum/supply_drop_loot/dd_SortValue() return name -/datum/supply_drop_loot/supermatter - name = "Supermatter" -/datum/supply_drop_loot/supermatter/New() - ..() - contents = list(/obj/machinery/power/supermatter) - /datum/supply_drop_loot/lasers name = "Lasers" container = /obj/structure/largecrate diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm index 67aee6ead08c..cac321522873 100644 --- a/code/modules/reagents/Chemistry-Holder.dm +++ b/code/modules/reagents/Chemistry-Holder.dm @@ -797,37 +797,55 @@ var/global/datum/reagents/sink/infinite_reagent_sink = new // Options are touch_turf(), touch_mob() and touch_obj(). This does not handle transferring reagents to things. // For example, splashing someone with water will get them wet and extinguish them if they are on fire, // even if they are wearing an impermeable suit that prevents the reagents from contacting the skin. -/datum/reagents/proc/touch_mob(var/mob/target) + +/datum/reagents/proc/touch_atom(atom/target, touch_atoms = TRUE) + if(ismob(target)) + return touch_mob(target) + if(isobj(target)) + return touch_obj(target) + if(isturf(target)) + return touch_turf(target, touch_atoms) + return FALSE + +/datum/reagents/proc/touch_mob(mob/target) if(!target || !istype(target) || !target.simulated) return for(var/rtype in reagent_volumes) var/decl/material/current = GET_DECL(rtype) current.touch_mob(target, REAGENT_VOLUME(src, rtype), src) -/datum/reagents/proc/touch_turf(var/turf/target) - if(!istype(target) || !target.simulated) +/datum/reagents/proc/touch_turf(turf/touching_turf, touch_atoms = TRUE) + + if(!istype(touching_turf) || !touching_turf.simulated) return + for(var/rtype in reagent_volumes) var/decl/material/current = GET_DECL(rtype) - current.touch_turf(target, REAGENT_VOLUME(src, rtype), src) + current.touch_turf(touching_turf, REAGENT_VOLUME(src, rtype), src) + var/dirtiness = get_dirtiness() if(dirtiness <= DIRTINESS_CLEAN) - target.clean() - target.remove_cleanables() - if(dirtiness != DIRTINESS_NEUTRAL) - if(dirtiness > DIRTINESS_NEUTRAL) - target.add_dirt(ceil(total_volume * dirtiness)) - else - if(dirtiness <= DIRTINESS_STERILE) - target.germ_level -= min(total_volume*20, target.germ_level) - for(var/obj/item/I in target.contents) - I.was_bloodied = null - for(var/obj/effect/decal/cleanable/blood/B in target) - qdel(B) - if(dirtiness <= DIRTINESS_CLEAN) - target.clean() - -/datum/reagents/proc/touch_obj(var/obj/target) + touching_turf.clean() + touching_turf.remove_cleanables() + + if(dirtiness > DIRTINESS_NEUTRAL) + touching_turf.add_dirt(ceil(total_volume * dirtiness)) + else if(dirtiness < DIRTINESS_NEUTRAL) + if(dirtiness <= DIRTINESS_STERILE) + touching_turf.germ_level -= min(total_volume*20, touching_turf.germ_level) + for(var/obj/item/I in touching_turf.contents) + I.was_bloodied = null + for(var/obj/effect/decal/cleanable/blood/B in touching_turf) + qdel(B) + if(dirtiness <= DIRTINESS_CLEAN) + touching_turf.clean() + + if(touch_atoms) + for(var/atom/movable/thing in touching_turf.get_contained_external_atoms()) + if(thing.simulated && !istype(thing, /obj/effect/effect/smoke/chem)) + touch_atom(thing) + +/datum/reagents/proc/touch_obj(obj/target) if(!target || !istype(target) || !target.simulated) return for(var/rtype in reagent_volumes) diff --git a/code/modules/reagents/Chemistry-Metabolism.dm b/code/modules/reagents/Chemistry-Metabolism.dm index e1002809b1f6..9c78f190ca2f 100644 --- a/code/modules/reagents/Chemistry-Metabolism.dm +++ b/code/modules/reagents/Chemistry-Metabolism.dm @@ -20,7 +20,7 @@ parent = null return ..() -/datum/reagents/metabolism/proc/metabolize(var/list/dosage_tracker) +/datum/reagents/metabolism/proc/metabolize(list/dosage_tracker) if(!parent || total_volume < MINIMUM_CHEMICAL_VOLUME || !length(reagent_volumes)) return for(var/rtype in reagent_volumes) diff --git a/code/modules/reagents/chems/chems_alcohol.dm b/code/modules/reagents/chems/chems_alcohol.dm index aa7ca92f847b..44384d64365f 100644 --- a/code/modules/reagents/chems/chems_alcohol.dm +++ b/code/modules/reagents/chems/chems_alcohol.dm @@ -226,8 +226,8 @@ if(M.bodytemperature > 310) M.bodytemperature = max(310, M.bodytemperature - (5 * TEMPERATURE_DAMAGE_COEFFICIENT)) -/decl/material/liquid/alcohol/coffee/affect_overdose(mob/living/M, total_dose) - ADJ_STATUS(M, STAT_JITTER, 5) +/decl/material/liquid/alcohol/coffee/affect_overdose(mob/living/victim, total_dose) + ADJ_STATUS(victim, STAT_JITTER, 5) /decl/material/liquid/alcohol/melonliquor name = "melon liqueur" diff --git a/code/modules/reagents/chems/chems_blood.dm b/code/modules/reagents/chems/chems_blood.dm index e3a08e5b8731..1e4696e3ffec 100644 --- a/code/modules/reagents/chems/chems_blood.dm +++ b/code/modules/reagents/chems/chems_blood.dm @@ -46,12 +46,12 @@ for(var/chem in other_chems) my_chems[chem] = my_chems[chem] + other_chems[chem] -/decl/material/liquid/blood/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder) +/decl/material/liquid/blood/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder) var/data = REAGENT_DATA(holder, type) - if(!istype(T) || REAGENT_VOLUME(holder, type) < 3) + if(!istype(touching_turf) || REAGENT_VOLUME(holder, type) < 3) return - var/weakref/W = LAZYACCESS(data, DATA_BLOOD_DONOR) - blood_splatter(T, W?.resolve() || holder.my_atom, 1) + var/weakref/donor = LAZYACCESS(data, DATA_BLOOD_DONOR) + blood_splatter(touching_turf, donor?.resolve() || holder.my_atom, 1) /decl/material/liquid/blood/affect_ingest(var/mob/living/M, var/removed, var/datum/reagents/holder) . = ..() diff --git a/code/modules/reagents/chems/chems_compounds.dm b/code/modules/reagents/chems/chems_compounds.dm index 42a44ac8fa12..468300ba1720 100644 --- a/code/modules/reagents/chems/chems_compounds.dm +++ b/code/modules/reagents/chems/chems_compounds.dm @@ -35,11 +35,11 @@ addtimer(CALLBACK(H, TYPE_PROC_REF(/mob/living/human, update_eyes)), 5 SECONDS) . = ..() -/decl/material/liquid/glowsap/affect_overdose(mob/living/M, total_dose) +/decl/material/liquid/glowsap/affect_overdose(mob/living/victim, total_dose) . = ..() - M.add_chemical_effect(CE_TOXIN, 1) - M.set_hallucination(60, 20) - SET_STATUS_MAX(M, STAT_DRUGGY, 10) + victim.add_chemical_effect(CE_TOXIN, 1) + victim.set_hallucination(60, 20) + SET_STATUS_MAX(victim, STAT_DRUGGY, 10) /decl/material/solid/blackpepper name = "black pepper" diff --git a/code/modules/reagents/chems/chems_drinks.dm b/code/modules/reagents/chems/chems_drinks.dm index af54d84cd623..eca5276b785f 100644 --- a/code/modules/reagents/chems/chems_drinks.dm +++ b/code/modules/reagents/chems/chems_drinks.dm @@ -379,9 +379,9 @@ ..() M.add_chemical_effect(CE_PULSE, 2) -/decl/material/liquid/drink/coffee/affect_overdose(mob/living/M, total_dose) - ADJ_STATUS(M, STAT_JITTER, 5) - M.add_chemical_effect(CE_PULSE, 1) +/decl/material/liquid/drink/coffee/affect_overdose(mob/living/victim, total_dose) + ADJ_STATUS(victim, STAT_JITTER, 5) + victim.add_chemical_effect(CE_PULSE, 1) /decl/material/liquid/drink/coffee/build_presentation_name_from_reagents(var/obj/item/prop, var/supplied) diff --git a/code/modules/reagents/chems/chems_drugs.dm b/code/modules/reagents/chems/chems_drugs.dm index 9d36a9a5ae39..e93452002971 100644 --- a/code/modules/reagents/chems/chems_drugs.dm +++ b/code/modules/reagents/chems/chems_drugs.dm @@ -61,9 +61,9 @@ LAZYSET(holder.reagent_data, type, world.time) to_chat(M, "You feel invigorated and calm.") -/decl/material/liquid/nicotine/affect_overdose(mob/living/M, total_dose) +/decl/material/liquid/nicotine/affect_overdose(mob/living/victim, total_dose) ..() - M.add_chemical_effect(CE_PULSE, 2) + victim.add_chemical_effect(CE_PULSE, 2) /decl/material/liquid/sedatives name = "sedatives" @@ -253,10 +253,9 @@ if(istype(M)) M.remove_client_color(/datum/client_color/noir/thirdeye) -/decl/material/liquid/glowsap/gleam/affect_overdose(mob/living/M, total_dose) - M.take_damage(rand(1, 5), BRAIN) - if(ishuman(M) && prob(10)) - var/mob/living/human/H = M - H.seizure() +/decl/material/liquid/glowsap/gleam/affect_overdose(mob/living/victim, total_dose) + victim.take_damage(rand(1, 5), BRAIN) + if(prob(10)) + victim.seizure() if(prob(10)) - to_chat(M, SPAN_DANGER("[pick(overdose_messages)]")) + to_chat(victim, SPAN_DANGER("[pick(overdose_messages)]")) diff --git a/code/modules/reagents/chems/chems_medicines.dm b/code/modules/reagents/chems/chems_medicines.dm index 701d2f1d4763..7b8357a17675 100644 --- a/code/modules/reagents/chems/chems_medicines.dm +++ b/code/modules/reagents/chems/chems_medicines.dm @@ -52,14 +52,12 @@ uid = "chem_styptic" var/effectiveness = 1 -/decl/material/liquid/brute_meds/affect_overdose(mob/living/M, var/datum/reagents/holder) +/decl/material/liquid/brute_meds/affect_overdose(mob/living/victim, total_dose) ..() - if(ishuman(M)) - M.add_chemical_effect(CE_BLOCKAGE, (15 + REAGENT_VOLUME(holder, type))/100) - var/mob/living/human/H = M - for(var/obj/item/organ/external/E in H.get_external_organs()) - if(E.status & ORGAN_ARTERY_CUT && prob(2 + REAGENT_VOLUME(holder, type) / overdose)) - E.status &= ~ORGAN_ARTERY_CUT + victim.add_chemical_effect(CE_BLOCKAGE, (15 + total_dose) / 100) + for(var/obj/item/organ/external/limb in victim.get_external_organs()) + if((limb.status & ORGAN_ARTERY_CUT) && prob(2 + total_dose / overdose)) + limb.status &= ~ORGAN_ARTERY_CUT //This is a logistic function that effectively doubles the healing rate as brute amounts get to around 200. Any injury below 60 is essentially unaffected and there's a scaling inbetween. #define ADJUSTED_REGEN_VAL(X) (6+(6/(1+200*2.71828**(-0.05*(X))))) @@ -169,12 +167,10 @@ if(immunity_to_add > 0) M.adjust_immunity(immunity_to_add) // Rapidly brings someone up to half immunity. -/decl/material/liquid/immunobooster/affect_overdose(mob/living/M, total_dose) +/decl/material/liquid/immunobooster/affect_overdose(mob/living/victim, total_dose) ..() - M.add_chemical_effect(CE_TOXIN, 1) - var/mob/living/human/H = M - if(istype(H)) - M.adjust_immunity(-0.5) + victim.add_chemical_effect(CE_TOXIN, 1) + victim.adjust_immunity(-0.5) /decl/material/liquid/stimulants name = "stimulants" @@ -240,12 +236,12 @@ exoplanet_rarity_gas = MAT_RARITY_EXOTIC uid = "chem_antibiotics" -/decl/material/liquid/antibiotics/affect_overdose(mob/living/M, total_dose) +/decl/material/liquid/antibiotics/affect_overdose(mob/living/victim, total_dose) ..() - M.adjust_immunity(-0.5) - M.immunity = max(M.immunity - 0.25, 0) + victim.adjust_immunity(-0.5) + victim.immunity = max(victim.immunity - 0.25, 0) if(prob(2)) - M.immunity_norm = max(M.immunity_norm - 1, 0) + victim.immunity_norm = max(victim.immunity_norm - 1, 0) /decl/material/liquid/retrovirals name = "retrovirals" @@ -258,14 +254,12 @@ exoplanet_rarity_gas = MAT_RARITY_EXOTIC uid = "chem_retrovirals" -/decl/material/liquid/retrovirals/affect_overdose(mob/living/M, total_dose) +/decl/material/liquid/retrovirals/affect_overdose(mob/living/victim, total_dose) . = ..() - if(ishuman(M)) - var/mob/living/human/H = M - for(var/obj/item/organ/external/E in H.get_external_organs()) - if(!BP_IS_PROSTHETIC(E) && prob(25) && !(E.status & ORGAN_MUTATED)) - E.mutate() - E.limb_flags |= ORGAN_FLAG_DEFORMED + for(var/obj/item/organ/external/limb in victim.get_external_organs()) + if(!BP_IS_PROSTHETIC(limb) && prob(25) && !(limb.status & ORGAN_MUTATED)) + limb.mutate() + limb.limb_flags |= ORGAN_FLAG_DEFORMED /decl/material/liquid/retrovirals/affect_blood(var/mob/living/M, var/removed, var/datum/reagents/holder) . = ..() @@ -404,8 +398,8 @@ break ..() -/decl/material/liquid/clotting_agent/affect_overdose(mob/living/M, total_dose) - var/obj/item/organ/internal/heart = GET_INTERNAL_ORGAN(M, BP_HEART) +/decl/material/liquid/clotting_agent/affect_overdose(mob/living/victim, total_dose) + var/obj/item/organ/internal/heart = GET_INTERNAL_ORGAN(victim, BP_HEART) if(heart && prob(25)) heart.take_general_damage(rand(1,3)) return ..() diff --git a/code/modules/reagents/chems/chems_nutriment.dm b/code/modules/reagents/chems/chems_nutriment.dm index d96d2b840d70..cc0774431ca6 100644 --- a/code/modules/reagents/chems/chems_nutriment.dm +++ b/code/modules/reagents/chems/chems_nutriment.dm @@ -83,9 +83,9 @@ uid = "chem_nutriment_flour" allergen_flags = ALLERGEN_GLUTEN -/decl/material/liquid/nutriment/flour/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder) +/decl/material/liquid/nutriment/flour/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder) ..() - new /obj/effect/decal/cleanable/flour(T) + new /obj/effect/decal/cleanable/flour(touching_turf) /decl/material/liquid/nutriment/batter name = "batter" @@ -102,9 +102,9 @@ boiling_point = 373 allergen_flags = ALLERGEN_EGG | ALLERGEN_GLUTEN -/decl/material/liquid/nutriment/batter/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder) +/decl/material/liquid/nutriment/batter/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder) ..() - new /obj/effect/decal/cleanable/pie_smudge(T) + new /obj/effect/decal/cleanable/pie_smudge(touching_turf) /decl/material/liquid/nutriment/batter/cakebatter name = "cake batter" diff --git a/code/modules/reagents/chems/chems_painkillers.dm b/code/modules/reagents/chems/chems_painkillers.dm index 6647c2afed2d..8ab62f4048fa 100644 --- a/code/modules/reagents/chems/chems_painkillers.dm +++ b/code/modules/reagents/chems/chems_painkillers.dm @@ -112,17 +112,17 @@ M.add_chemical_effect(CE_ALCOHOL_TOXIC, 1) M.add_chemical_effect(CE_BREATHLOSS, 1 * boozed) //drinking and opiating suppresses breathing. -/decl/material/liquid/painkillers/affect_overdose(mob/living/M, total_dose) +/decl/material/liquid/painkillers/affect_overdose(mob/living/victim, total_dose) ..() - M.add_chemical_effect(CE_PAINKILLER, pain_power*0.5) //extra painkilling for extra trouble + victim.add_chemical_effect(CE_PAINKILLER, pain_power*0.5) //extra painkilling for extra trouble if(narcotic) - SET_STATUS_MAX(M, STAT_DRUGGY, 10) - M.set_hallucination(120, 30) - M.add_chemical_effect(CE_BREATHLOSS, breathloss_severity*2) //ODing on opiates can be deadly. - if(isboozed(M)) - M.add_chemical_effect(CE_BREATHLOSS, breathloss_severity*4) //Don't drink and OD on opiates folks + SET_STATUS_MAX(victim, STAT_DRUGGY, 10) + victim.set_hallucination(120, 30) + victim.add_chemical_effect(CE_BREATHLOSS, breathloss_severity*2) //ODing on opiates can be deadly. + if(isboozed(victim)) + victim.add_chemical_effect(CE_BREATHLOSS, breathloss_severity*4) //Don't drink and OD on opiates folks else - M.add_chemical_effect(CE_TOXIN, 1) + victim.add_chemical_effect(CE_TOXIN, 1) /decl/material/liquid/painkillers/proc/isboozed(var/mob/living/M) . = 0 diff --git a/code/modules/reagents/chems/chems_pigments.dm b/code/modules/reagents/chems/chems_pigments.dm index c5fc41928620..55c6be4c47cb 100644 --- a/code/modules/reagents/chems/chems_pigments.dm +++ b/code/modules/reagents/chems/chems_pigments.dm @@ -85,9 +85,9 @@ painting.reset_color() painting.set_alpha(keep_alpha) -/decl/material/liquid/paint_stripper/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder) - if(istype(T) && !isspaceturf(T)) - remove_paint(T, holder) +/decl/material/liquid/paint_stripper/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder) + if(istype(touching_turf) && !isspaceturf(touching_turf)) + remove_paint(touching_turf, holder) /decl/material/liquid/paint_stripper/touch_obj(var/obj/O, var/amount, var/datum/reagents/holder) if(istype(O)) @@ -113,9 +113,9 @@ painting.set_color(holder.get_color()) painting.set_alpha(keep_alpha) -/decl/material/liquid/paint/touch_turf(var/turf/T, var/amount, var/datum/reagents/holder) - if(istype(T) && !isspaceturf(T)) - apply_paint(T, holder, FLUID_MINIMUM_TRANSFER) +/decl/material/liquid/paint/touch_turf(var/turf/touching_turf, var/amount, var/datum/reagents/holder) + if(istype(touching_turf) && !isspaceturf(touching_turf)) + apply_paint(touching_turf, holder, FLUID_MINIMUM_TRANSFER) /decl/material/liquid/paint/touch_obj(var/obj/O, var/amount, var/datum/reagents/holder) if(istype(O)) diff --git a/code/modules/reagents/heat_sources/_heat_source.dm b/code/modules/reagents/heat_sources/_heat_source.dm index b92953137078..eb5b3cebf445 100644 --- a/code/modules/reagents/heat_sources/_heat_source.dm +++ b/code/modules/reagents/heat_sources/_heat_source.dm @@ -5,8 +5,8 @@ #define HEATER_MODE_COOL "cool" /obj/machinery/reagent_temperature - name = "chemical heater" - desc = "A small electric Bunsen, used to heat beakers and vials of chemicals." + name = "hotplate" + desc = "A small electric hotplate, used to heat cookware, beakers, or vials of chemicals." icon = 'icons/obj/machines/heat_sources.dmi' icon_state = "hotplate" atom_flags = ATOM_FLAG_CLIMBABLE @@ -70,6 +70,7 @@ /obj/machinery/reagent_temperature/ProcessAtomTemperature() if(use_power >= POWER_USE_ACTIVE) + var/last_temperature = temperature if(heater_mode == HEATER_MODE_HEAT && temperature < target_temperature) temperature = min(target_temperature, temperature + heating_power) @@ -79,10 +80,25 @@ if(container) queue_temperature_atoms(container) queue_icon_update() + + // Hackery to heat pots placed onto a hotplate without also grilling/baking stuff. + if(isturf(loc)) + var/datum/gas_mixture/environment = loc.return_air() + for(var/obj/item/chems/cooking_vessel/pot in loc.get_contained_external_atoms()) + pot.fire_act(environment, temperature, 500) + return TRUE // Don't kill this processing loop unless we're not powered. . = ..() /obj/machinery/reagent_temperature/attackby(var/obj/item/thing, var/mob/user) + + if(istype(thing, /obj/item/chems/cooking_vessel)) + if(!user.try_unequip(thing, get_turf(src))) + return TRUE + thing.reset_offsets(anim_time = 0) + user.visible_message(SPAN_NOTICE("\The [user] places \the [thing] onto \the [src].")) + return TRUE + if(IS_WRENCH(thing)) if(use_power == POWER_USE_ACTIVE) to_chat(user, SPAN_WARNING("Turn \the [src] off first!")) diff --git a/code/modules/reagents/reactions/_reaction.dm b/code/modules/reagents/reactions/_reaction.dm index e743ecf0ab2b..fbc2eaa85d68 100644 --- a/code/modules/reagents/reactions/_reaction.dm +++ b/code/modules/reagents/reactions/_reaction.dm @@ -38,7 +38,7 @@ return 1 -/decl/chemical_reaction/proc/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/proc/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) var/atom/location = holder.get_reaction_loc(chemical_reaction_flags) if(thermal_product && location && ATOM_SHOULD_TEMPERATURE_ENQUEUE(location)) ADJUST_ATOM_TEMPERATURE(location, location.temperature + (location.get_thermal_mass_coefficient() * thermal_product)) @@ -61,8 +61,6 @@ if(reaction_volume > A) reaction_volume = A - var/alt_reaction_indicator = get_alternate_reaction_indicator(holder) - for(var/reactant in required_reagents) holder.remove_reagent(reactant, reaction_volume * required_reagents[reactant], safety = 1) @@ -71,7 +69,7 @@ if(result) holder.add_reagent(result, amt_produced, data, safety = 1) - on_reaction(holder, amt_produced, alt_reaction_indicator, data) + on_reaction(holder, amt_produced, data) //called after processing reactions, if they occurred /decl/chemical_reaction/proc/post_reaction(var/datum/reagents/holder) diff --git a/code/modules/reagents/reactions/reaction_compounds.dm b/code/modules/reagents/reactions/reaction_compounds.dm index 8e530dacaa58..a334f65b6ff9 100644 --- a/code/modules/reagents/reactions/reaction_compounds.dm +++ b/code/modules/reagents/reactions/reaction_compounds.dm @@ -155,10 +155,20 @@ required_reagents = list(/decl/material/liquid/capsaicin = 2) result = list(/decl/material/liquid/capsaicin/condensed = 1) -/decl/chemical_reaction/compound/condensed_capsaicin/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/compound/condensed_capsaicin/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) . = ..() holder?.add_reagent(/decl/material/liquid/water, created_volume) +/decl/chemical_reaction/compound/nanitefluid + name = "Nanite Fluid Synthesis" + result = /decl/material/liquid/nanitefluid + required_reagents = list(/decl/material/liquid/plasticide = 1, /decl/material/solid/metal/aluminium = 1, /decl/material/liquid/lube = 1) + catalysts = list(/decl/material/liquid/crystal_agent = 1) + result_amount = 3 + minimum_temperature = (-25 CELSIUS) - 100 + maximum_temperature = -25 CELSIUS + mix_message = "The solution becomes a metallic slime." + // This is a bit silly, but we need a way to unify oil types until someone rewrites lanterns. /decl/chemical_reaction/compound/fuel_oil name = "Plant Fuel Oil" diff --git a/code/modules/reagents/reactions/reaction_drugs.dm b/code/modules/reagents/reactions/reaction_drugs.dm index 8f10b625a3c2..a4f85cb3fa73 100644 --- a/code/modules/reagents/reactions/reaction_drugs.dm +++ b/code/modules/reagents/reactions/reaction_drugs.dm @@ -111,16 +111,6 @@ required_reagents = list(/decl/material/liquid/antirads = 1, /decl/material/solid/carbon = 1) result_amount = 2 -/decl/chemical_reaction/compound/nanitefluid - name = "Nanite Fluid" - result = /decl/material/liquid/nanitefluid - required_reagents = list(/decl/material/liquid/plasticide = 1, /decl/material/solid/metal/aluminium = 1, /decl/material/liquid/lube = 1) - catalysts = list(/decl/material/liquid/crystal_agent = 1) - result_amount = 3 - minimum_temperature = (-25 CELSIUS) - 100 - maximum_temperature = -25 CELSIUS - mix_message = "The solution becomes a metallic slime." - /decl/chemical_reaction/drug/antibiotics name = "Antibiotics" result = /decl/material/liquid/antibiotics diff --git a/code/modules/reagents/reactions/reaction_grenade_reaction.dm b/code/modules/reagents/reactions/reaction_grenade_reaction.dm index ec529bef717f..7827c6ac0548 100644 --- a/code/modules/reagents/reactions/reaction_grenade_reaction.dm +++ b/code/modules/reagents/reactions/reaction_grenade_reaction.dm @@ -11,7 +11,7 @@ required_reagents = list(/decl/material/liquid/water = 1, /decl/material/solid/potassium = 1) mix_message = "The solution bubbles vigorously!" -/decl/chemical_reaction/grenade_reaction/explosion_potassium/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/grenade_reaction/explosion_potassium/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/atom/location = holder.get_reaction_loc(chemical_reaction_flags) if(location) @@ -32,7 +32,7 @@ result_amount = null mix_message = "The solution bubbles vigorously!" -/decl/chemical_reaction/grenade_reaction/flash_powder/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/grenade_reaction/flash_powder/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) if(location) @@ -58,7 +58,7 @@ mix_message = "The solution bubbles vigorously!" maximum_temperature = T100C -/decl/chemical_reaction/grenade_reaction/emp_pulse/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/grenade_reaction/emp_pulse/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/turf/location = holder.get_reaction_loc(chemical_reaction_flags) if(location) @@ -79,7 +79,7 @@ reaction_sound = 'sound/items/Welder.ogg' mix_message = "The solution suddenly ignites!" -/decl/chemical_reaction/grenade_reaction/flash_fire/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/grenade_reaction/flash_fire/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) if(istype(location)) @@ -93,7 +93,7 @@ result_amount = 0.4 mix_message = "The solution bubbles vigorously!" -/decl/chemical_reaction/grenade_reaction/chemsmoke/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/grenade_reaction/chemsmoke/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) if(location) @@ -112,7 +112,7 @@ result_amount = 2 mix_message = "The solution bubbles vigorously!" -/decl/chemical_reaction/grenade_reaction/foam/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/grenade_reaction/foam/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) if(location) @@ -129,7 +129,7 @@ result_amount = 5 mix_message = "The solution foams up violently!" -/decl/chemical_reaction/grenade_reaction/metalfoam/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/grenade_reaction/metalfoam/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/atom/location = holder.get_reaction_loc(chemical_reaction_flags) if(location) @@ -151,7 +151,7 @@ result_amount = 5 mix_message = "The solution bubbles vigorously!" -/decl/chemical_reaction/grenade_reaction/ironfoam/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/grenade_reaction/ironfoam/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/turf/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) if(location) diff --git a/code/modules/reagents/reactions/reaction_herbal.dm b/code/modules/reagents/reactions/reaction_herbal.dm index b8a02ca07fec..62950dd1d64c 100644 --- a/code/modules/reagents/reactions/reaction_herbal.dm +++ b/code/modules/reagents/reactions/reaction_herbal.dm @@ -3,7 +3,7 @@ result_amount = 2 minimum_temperature = 100 CELSIUS -/decl/chemical_reaction/drug/herbal/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/drug/herbal/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) . = ..() // Add plant matter to represent the herbs that the medicine has been leached out of. holder?.add_reagent(/decl/material/solid/organic/plantmatter, created_volume) diff --git a/code/modules/reagents/reactions/reaction_other.dm b/code/modules/reagents/reactions/reaction_other.dm index 19c5613ea7ec..dca52f041f62 100644 --- a/code/modules/reagents/reactions/reaction_other.dm +++ b/code/modules/reagents/reactions/reaction_other.dm @@ -10,7 +10,7 @@ return ..() return 0 -/decl/chemical_reaction/soap_key/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/soap_key/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) var/obj/item/soap/S = holder.get_reaction_loc(chemical_reaction_flags) if(istype(S) && S.key_data) new /obj/item/key/temporary(get_turf(S), /decl/material/liquid/cleaner, S.key_data, strength) diff --git a/code/modules/reagents/reactions/reaction_recipe_food.dm b/code/modules/reagents/reactions/reaction_recipe_food.dm index bc052960e913..0ece0daefd2a 100644 --- a/code/modules/reagents/reactions/reaction_recipe_food.dm +++ b/code/modules/reagents/reactions/reaction_recipe_food.dm @@ -4,7 +4,7 @@ abstract_type = /decl/chemical_reaction/recipe/food var/obj_result -/decl/chemical_reaction/recipe/food/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/recipe/food/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) if(obj_result && isturf(location)) diff --git a/code/modules/reagents/reactions/reaction_synthesis.dm b/code/modules/reagents/reactions/reaction_synthesis.dm index 57192c726ae5..79695861328a 100644 --- a/code/modules/reagents/reactions/reaction_synthesis.dm +++ b/code/modules/reagents/reactions/reaction_synthesis.dm @@ -19,7 +19,7 @@ ) . = ..() -/decl/chemical_reaction/synthesis/fiberglass/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/synthesis/fiberglass/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) if(location) @@ -44,7 +44,7 @@ if(rtype != /decl/material/liquid/crystal_agent && REAGENT_VOLUME(holder, rtype) >= REAGENT_UNITS_PER_MATERIAL_SHEET) return TRUE -/decl/chemical_reaction/synthesis/crystalization/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/synthesis/crystalization/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) if(location) var/list/removing_reagents = list() @@ -78,7 +78,7 @@ continue return TRUE -/decl/chemical_reaction/synthesis/aerogel/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/synthesis/aerogel/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) if(location) var/list/removing_reagents = list() @@ -97,7 +97,7 @@ required_reagents = list(/decl/material/liquid/acid = 1, /decl/material/liquid/plasticide = 2) mix_message = "The solution solidifies into a grey-white mass." -/decl/chemical_reaction/synthesis/plastication/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/synthesis/plastication/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) if(location) @@ -112,7 +112,7 @@ result_amount = 3 mix_message = "The solution hardens and begins to crystallize." -/decl/chemical_reaction/synthesis/resin_pack/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/synthesis/resin_pack/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/turf/T = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) if(!istype(T)) @@ -133,7 +133,7 @@ mix_message = "The solution thickens and solidifies." minimum_temperature = 100 CELSIUS -/decl/chemical_reaction/synthesis/soap/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/synthesis/soap/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/turf/T = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) if(!istype(T)) @@ -164,7 +164,7 @@ minimum_temperature = 100 CELSIUS var/chipboard_type = /decl/material/solid/organic/wood/chipboard -/decl/chemical_reaction/synthesis/chipboard/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) +/decl/chemical_reaction/synthesis/chipboard/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) ..() var/turf/T = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) if(!istype(T)) diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 99ec47811aa7..db9048920333 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -27,6 +27,8 @@ /obj/item/chems/on_update_icon() . = ..() + if(detail_state) + add_overlay(overlay_image(icon, "[initial(icon_state)][detail_state]", detail_color || COLOR_WHITE, RESET_COLOR)) var/image/contents_overlay = get_reagents_overlay(use_single_icon ? icon_state : null) if(contents_overlay) add_overlay(contents_overlay) @@ -204,6 +206,7 @@ /decl/interaction_handler/set_transfer/chems expected_target_type = /obj/item/chems + examine_desc = "set the transfer volume" /decl/interaction_handler/set_transfer/chems/is_possible(var/atom/target, var/mob/user) . = ..() @@ -220,6 +223,7 @@ name = "Empty On Floor" expected_target_type = /obj/item/chems interaction_flags = INTERACTION_NEEDS_INVENTORY | INTERACTION_NEEDS_PHYSICAL_INTERACTION | INTERACTION_NEVER_AUTOMATIC + examine_desc = "empty $TARGET_THEM$ onto the floor" /decl/interaction_handler/empty/chems/invoked(atom/target, mob/user, obj/item/prop) var/turf/T = get_turf(user) diff --git a/code/modules/reagents/reagent_containers/_glass.dm b/code/modules/reagents/reagent_containers/_glass.dm index 50c6024ac0b7..aee39d399219 100644 --- a/code/modules/reagents/reagent_containers/_glass.dm +++ b/code/modules/reagents/reagent_containers/_glass.dm @@ -114,12 +114,6 @@ . = ..() // Drinking out of bowls. -/obj/item/chems/glass/get_food_default_transfer_amount(mob/eater) - return eater?.get_eaten_transfer_amount(amount_per_transfer_from_this) - -/obj/item/chems/glass/get_food_consumption_method(mob/eater) - return EATING_METHOD_DRINK - /obj/item/chems/glass/get_edible_material_amount(mob/eater) return reagents?.total_volume @@ -155,3 +149,28 @@ LAZYADD(., /decl/interaction_handler/fill_from) if(user?.get_active_held_item()) LAZYADD(., /decl/interaction_handler/empty_into) + if(can_lid()) + LAZYADD(., /decl/interaction_handler/toggle_lid) + +/decl/interaction_handler/toggle_lid + name = "Toggle Lid" + expected_target_type = /obj/item/chems/glass + +/decl/interaction_handler/toggle_lid/is_possible(atom/target, mob/user, obj/item/prop) + . = ..() + if(. && !istype(prop)) + var/obj/item/chems/glass/glass = target + return glass.can_lid() + +/decl/interaction_handler/toggle_lid/invoked(atom/target, mob/user, obj/item/prop) + var/obj/item/chems/glass/glass = target + if(istype(glass) && glass.can_lid()) + if(ATOM_IS_OPEN_CONTAINER(glass)) + to_chat(user, SPAN_NOTICE("You put the lid on \the [glass].")) + glass.atom_flags ^= ATOM_FLAG_OPEN_CONTAINER + else + to_chat(user, SPAN_NOTICE("You take the lid off \the [glass].")) + glass.atom_flags |= ATOM_FLAG_OPEN_CONTAINER + glass.update_icon() + return TRUE + diff --git a/code/modules/reagents/reagent_containers/beaker.dm b/code/modules/reagents/reagent_containers/beaker.dm index 3b1ad5be0422..ab42e686e931 100644 --- a/code/modules/reagents/reagent_containers/beaker.dm +++ b/code/modules/reagents/reagent_containers/beaker.dm @@ -178,5 +178,5 @@ matter = list(/decl/material/solid/organic/plastic = MATTER_AMOUNT_REINFORCEMENT) volume = 120 -/obj/item/chems/glass/beaker/sulphuric/populate_reagents() +/obj/item/chems/glass/beaker/sulfuric/populate_reagents() add_to_reagents(/decl/material/liquid/acid, reagents.maximum_volume) diff --git a/code/modules/reagents/reagent_containers/drinks.dm b/code/modules/reagents/reagent_containers/drinks.dm index 46c56514eee4..695412409f84 100644 --- a/code/modules/reagents/reagent_containers/drinks.dm +++ b/code/modules/reagents/reagent_containers/drinks.dm @@ -57,7 +57,7 @@ return return ..() -/obj/item/chems/drinks/standard_dispenser_refill(var/mob/user, var/obj/structure/reagent_dispensers/target, skip_container_check = FALSE) +/obj/item/chems/drinks/standard_dispenser_refill(mob/user, obj/structure/reagent_dispensers/target, skip_container_check = FALSE) return do_open_check(user) && ..() /obj/item/chems/drinks/standard_pour_into(var/mob/user, var/atom/target) diff --git a/code/modules/reagents/reagent_containers/food/sliceable/pizza/pizza_box.dm b/code/modules/reagents/reagent_containers/food/sliceable/pizza/pizza_box.dm index a048bb7eac31..6c6cf548fe68 100644 --- a/code/modules/reagents/reagent_containers/food/sliceable/pizza/pizza_box.dm +++ b/code/modules/reagents/reagent_containers/food/sliceable/pizza/pizza_box.dm @@ -304,6 +304,7 @@ /decl/interaction_handler/open_pizza_box expected_target_type = /obj/item/pizzabox + examine_desc = "open or close $TARGET_THEM$" /decl/interaction_handler/open_pizza_box/is_possible(atom/target, mob/user, obj/item/prop) . = ..() diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 9cd81a4c4375..c3b4cbd9ff8e 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -36,9 +36,6 @@ if(A?.storage || istype(A, /obj/structure/table) || istype(A, /obj/structure/closet) || istype(A, /obj/item/chems) || istype(A, /obj/structure/hygiene/sink) || istype(A, /obj/structure/janitorialcart)) return - if(istype(A, /spell)) - return - if(proximity) if(standard_dispenser_refill(user, A)) return @@ -50,7 +47,7 @@ Spray_at(A, user, proximity) if(reagents.has_reagent(/decl/material/liquid/acid)) - log_and_message_admins("fired sulphuric acid from \a [src].", user) + log_and_message_admins("fired sulfuric acid from \a [src].", user) if(reagents.has_reagent(/decl/material/liquid/acid/polyacid)) log_and_message_admins("fired polyacid from \a [src].", user) if(reagents.has_reagent(/decl/material/liquid/lube)) @@ -119,6 +116,7 @@ name = "Next Nozzle Setting" expected_target_type = /obj/item/chems/spray interaction_flags = INTERACTION_NEEDS_INVENTORY | INTERACTION_NEEDS_PHYSICAL_INTERACTION + examine_desc = "select the next nozzle spray amount" /decl/interaction_handler/next_spray_amount/is_possible(obj/item/chems/spray/target, mob/user, obj/item/prop) . = ..() diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index d8d5d4e5e06c..778ed37be452 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -10,6 +10,7 @@ matter = list(/decl/material/solid/metal/steel = MATTER_AMOUNT_SECONDARY) max_health = 100 tool_interaction_flags = TOOL_INTERACTION_DECONSTRUCT + var/wrenchable = TRUE var/unwrenched = FALSE var/tmp/volume = 1000 @@ -102,6 +103,7 @@ log_and_message_admins("opened a tank at [get_area_name(loc)].") leak() return TRUE + . = ..() /obj/structure/reagent_dispensers/verb/set_amount_dispensed() @@ -317,11 +319,12 @@ add_to_reagents(/decl/material/liquid/alcohol/beer, reagents.maximum_volume) /obj/structure/reagent_dispensers/acid - name = "sulphuric acid dispenser" + name = "sulfuric acid dispenser" desc = "A dispenser of acid for industrial processes." icon_state = "acidtank" amount_dispensed = 10 anchored = TRUE + density = FALSE /obj/structure/reagent_dispensers/acid/populate_reagents() add_to_reagents(/decl/material/liquid/acid, reagents.maximum_volume) @@ -351,6 +354,7 @@ /decl/interaction_handler/toggle_open/reagent_dispenser name = "Toggle refilling cap" expected_target_type = /obj/structure/reagent_dispensers + examine_desc = "open or close the refilling cap" /decl/interaction_handler/toggle_open/reagent_dispenser/invoked(atom/target, mob/user, obj/item/prop) if(target.atom_flags & ATOM_FLAG_OPEN_CONTAINER) diff --git a/code/modules/sealant_gun/sealant_injector.dm b/code/modules/sealant_gun/sealant_injector.dm index a3e89a44343e..99f8553586d8 100644 --- a/code/modules/sealant_gun/sealant_injector.dm +++ b/code/modules/sealant_gun/sealant_injector.dm @@ -103,6 +103,7 @@ /decl/interaction_handler/sealant_try_inject name = "Inject Sealant" expected_target_type = /obj/structure/sealant_injector + examine_desc = "inject sealant from a held item" /decl/interaction_handler/sealant_try_inject/invoked(atom/target, mob/user, obj/item/prop) var/obj/structure/sealant_injector/SI = target diff --git a/code/modules/shuttles/landmarks.dm b/code/modules/shuttles/landmarks.dm index 82cde0c759be..661bab8cf891 100644 --- a/code/modules/shuttles/landmarks.dm +++ b/code/modules/shuttles/landmarks.dm @@ -135,7 +135,7 @@ var/global/list/shuttle_landmarks = list() /obj/effect/shuttle_landmark/automatic/sector_set(var/obj/effect/overmap/visitable/O) ..() - SetName("[initial(name)] ([x],[y])") + SetName("[initial(name)] ([x],[y],[z])") //Subtype that calls explosion on init to clear space for shuttles /obj/effect/shuttle_landmark/automatic/clearing diff --git a/code/modules/species/species.dm b/code/modules/species/species.dm index 5c615ad31b3d..32980d3c189e 100644 --- a/code/modules/species/species.dm +++ b/code/modules/species/species.dm @@ -57,9 +57,6 @@ var/global/const/DEFAULT_SPECIES_HEALTH = 200 var/flesh_color = "#ffc896" // Pink. var/blood_oxy = 1 - // Preview in prefs positioning. If null, uses defaults set on a static list in preferences.dm. - var/list/character_preview_screen_locs - var/organs_icon //species specific internal organs icons var/strength = STR_MEDIUM diff --git a/code/modules/spells/aoe_turf/aoe_turf.dm b/code/modules/spells/aoe_turf/aoe_turf.dm deleted file mode 100644 index 0f7a721de803..000000000000 --- a/code/modules/spells/aoe_turf/aoe_turf.dm +++ /dev/null @@ -1,23 +0,0 @@ -/* -Aoe turf spells target a ring of tiles around the user -This ring has an outer radius (range) and an inner radius (inner_radius) -Aoe turf spells have a useful flag: IGNOREDENSE. It is explained in setup.dm -*/ - -/spell/aoe_turf //affects all turfs in view or range (depends) - spell_flags = IGNOREDENSE - var/inner_radius = -1 //for all your ring spell needs - -/spell/aoe_turf/choose_targets(mob/user = usr) - var/list/targets = list() - - for(var/turf/target in view_or_range(range, holder, selection_type)) - if(!(target in view_or_range(inner_radius, holder, selection_type))) - if(target.density && (spell_flags & IGNOREDENSE)) - continue - targets += target - - if(!targets.len) //doesn't waste the spell - return - - return targets \ No newline at end of file diff --git a/code/modules/spells/aoe_turf/conjure/conjure.dm b/code/modules/spells/aoe_turf/conjure/conjure.dm deleted file mode 100644 index 8dd91146310c..000000000000 --- a/code/modules/spells/aoe_turf/conjure/conjure.dm +++ /dev/null @@ -1,73 +0,0 @@ -/* -Conjure spells spawn things (mobs, objs, turfs) in their summon_type -How they spawn stuff is decided by behaviour vars, which are explained below -*/ - -/spell/aoe_turf/conjure - name = "Conjure" - desc = "This spell conjures objs of the specified types in range." - - school = "conjuration" //funny, that - - var/list/summon_type = list() //determines what exactly will be summoned - //should NOT be text, like list(/obj/machinery/bot/ed209) - - range = 0 //default values: only spawn on the player tile - selection_type = "view" - - duration = 0 // 0=permanent, any other time in deciseconds - how long the summoned objects last for - var/summon_amt = 1 //amount of objects summoned - var/summon_exclusive = 0 //spawn one of everything, instead of random things - - var/list/newVars = list() //vars of the summoned objects will be replaced with those where they meet - //should have format of list("emagged" = 1,"name" = "Justicebot"), for example - - cast_sound = 'sound/magic/castsummon.ogg' - -/spell/aoe_turf/conjure/cast(list/targets, mob/user) - - for(var/i=1,i <= summon_amt,i++) - if(!targets.len) - break - var/summoned_object_type - if(summon_exclusive) - if(!summon_type.len) - break - summoned_object_type = summon_type[1] - summon_type -= summoned_object_type - else - summoned_object_type = pick(summon_type) - var/turf/spawn_place = pick(targets) - var/atom/summoned_object - if(ispath(summoned_object_type,/turf)) - spawn_place.ChangeTurf(summoned_object_type) - summoned_object = spawn_place - else - summoned_object = new summoned_object_type(spawn_place) - var/atom/movable/overlay/animation = new /atom/movable/overlay(summoned_object) - animation.SetName("conjure") - animation.set_density(0) - animation.anchored = TRUE - animation.icon = 'icons/effects/effects.dmi' - animation.layer = BASE_HUMAN_LAYER - if(ismob(summoned_object)) //we want them to NOT attack us. - var/mob/M = summoned_object - M.faction = user.faction - apply_vars(summoned_object, user) - - if(duration) - spawn(duration) - if(summoned_object && !isturf(summoned_object)) - qdel(summoned_object) - conjure_animation(animation, spawn_place) - return - -/spell/aoe_turf/conjure/proc/conjure_animation(var/atom/movable/overlay/animation, var/turf/target) - qdel(animation) - -/spell/aoe_turf/conjure/proc/apply_vars(atom/summoned_object, mob/caster) - if(!istype(summoned_object) || !length(newVars)) - return - for(var/varName in newVars) - if(varName in summoned_object.vars) - summoned_object.vars[varName] = newVars[varName] diff --git a/code/modules/spells/construct_spells.dm b/code/modules/spells/construct_spells.dm deleted file mode 100644 index 0c705aff4fc0..000000000000 --- a/code/modules/spells/construct_spells.dm +++ /dev/null @@ -1,10 +0,0 @@ -//////////////////////////////Construct Spells///////////////////////// - -/proc/findNullRod(var/atom/target) - if(istype(target,/obj/item/nullrod)) - return 1 - else if(target.contents) - for(var/atom/A in target.contents) - if(findNullRod(A)) - return 1 - return 0 diff --git a/code/modules/spells/spell_code.dm b/code/modules/spells/spell_code.dm deleted file mode 100644 index bfcf1f4d8f6c..000000000000 --- a/code/modules/spells/spell_code.dm +++ /dev/null @@ -1,385 +0,0 @@ -var/global/list/spells = typesof(/spell) //needed for the badmin verb for now - -/spell - var/name - var/desc - var/feedback = "" //what gets sent if this spell gets chosen by the spellbook. - parent_type = /datum - var/panel = "Spells"//What panel the proc holder needs to go on. - - var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit? - /*Spell schools as follows: - Racial - Only tagged to spells gained for being a certain race - Conjuration - Creating an object or transporting it. - Transmutation - Modifying an object or transforming it. - Illusion - Altering perception or thought. - */ - var/charge_type = Sp_RECHARGE //can be recharge or charges, see charge_max and charge_counter descriptions; can also be based on the holder's vars now, use "holder_var" for that - - var/charge_max = 100 //recharge time in deciseconds if charge_type = Sp_RECHARGE or starting charges if charge_type = Sp_CHARGES - var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = Sp_RECHARGE or -- each cast if charge_type = Sp_CHARGES - var/still_recharging_msg = "The spell is still recharging." - - var/silenced = 0 //not a binary - the length of time we can't cast this for - var/processing = 0 //are we processing already? Mainly used so that silencing a spell doesn't call process() again. (and inadvertedly making it run twice as fast) - - var/holder_var_type = "bruteloss" //only used if charge_type equals to "holder_var" - var/holder_var_amount = 20 //same. The amount adjusted with the mob's var when the spell is used - - var/spell_flags = 0 - var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell - var/invocation_type = SpI_NONE //can be none, whisper, shout, and emote - var/range = 7 //the range of the spell; outer radius for aoe spells - var/message = "" //whatever it says to the guy affected by it - var/selection_type = "view" //can be "range" or "view" - var/atom/movable/holder //where the spell is. Normally the user, can be an item - var/duration = 0 //how long the spell lasts - - var/list/spell_levels = list(Sp_SPEED = 0, Sp_POWER = 0) //the current spell levels - total spell levels can be obtained by just adding the two values - var/list/level_max = list(Sp_TOTAL = 4, Sp_SPEED = 4, Sp_POWER = 0) //maximum possible levels in each category. Total does cover both. - var/cooldown_reduc = 0 //If set, defines how much charge_max drops by every speed upgrade - var/delay_reduc = 0 - var/cooldown_min = 0 //minimum possible cooldown for a charging spell - - var/overlay = 0 - var/overlay_icon = 'icons/obj/wizard.dmi' - var/overlay_icon_state = "spell" - var/overlay_lifespan = 0 - - var/sparks_spread = 0 - var/sparks_amt = 0 //cropped at 10 - var/smoke_spread = 0 //1 - harmless, 2 - harmful - var/smoke_amt = 0 //cropped at 10 - - var/critfailchance = 0 - var/time_between_channels = 0 //Delay between casts - var/number_of_channels = 1 //How many times can we channel? - - var/cast_delay = 1 - var/cast_sound = "" - - var/hud_state = "" //name of the icon used in generating the spell hud object - var/override_base = "" - - - var/obj/screen/connected_button - - var/hidden_from_codex = FALSE - -/////////////////////// -///SETUP AND PROCESS/// -/////////////////////// - -/spell/New() - ..() - - //still_recharging_msg = "[name] is still recharging." - charge_counter = charge_max - -/spell/proc/process() - if(processing) - return - processing = 1 - spawn(0) - while(charge_counter < charge_max || silenced > 0) - charge_counter = min(charge_max,charge_counter+1) - silenced = max(0,silenced-1) - sleep(1) - if(connected_button) - var/obj/screen/ability/spell/S = connected_button - if(!istype(S)) - return - S.update_charge(1) - processing = 0 - return - -///////////////// -/////CASTING///// -///////////////// - -/spell/proc/choose_targets(mob/user = usr) //depends on subtype - see targeted.dm, aoe_turf.dm, dumbfire.dm, or code in general folder - return - -/spell/proc/perform(mob/user = usr, skipcharge = 0) //if recharge is started is important for the trigger spells - if(!holder) - holder = user //just in case - if(!cast_check(skipcharge, user)) - return - to_chat(user, SPAN_NOTICE("You start casting \the [name]...")) - if(cast_delay && !spell_do_after(user, cast_delay)) - return - var/list/targets = choose_targets(user) - if(!check_valid_targets(targets)) - to_chat(user, SPAN_WARNING("\The [name] fizzles. There are no valid targets nearby.")) - return - var/time = 0 - admin_attacker_log(user, "attempted to cast the spell [name]") - do - time++ - if(!check_valid_targets(targets)) //make sure we HAVE something - break - if(cast_check(1,user, targets)) //we check again, otherwise you can choose a target and then wait for when you are no longer able to cast (I.E. Incapacitated) to use it. - invocation(user, targets) - take_charge(user, skipcharge) - before_cast(targets) //applies any overlays and effects - if(prob(critfailchance)) - critfail(targets, user) - else - cast(targets, user, time) - after_cast(targets) //generates the sparks, smoke, target messages etc. - else - break - while(time != number_of_channels && do_after(user, time_between_channels, incapacitation_flags = INCAPACITATION_KNOCKOUT|INCAPACITATION_FORCELYING|INCAPACITATION_STUNNED, same_direction=1)) - after_spell(targets, user, time) //When we are done with the spell completely. - - - -/spell/proc/cast(list/targets, mob/user, var/channel_duration) //the actual meat of the spell - return - -/spell/proc/critfail(list/targets, mob/user) //the wizman has fucked up somehow - return - -/spell/proc/after_spell(var/list/targets, var/mob/user, var/channel_duration) //After everything else is done. - return - -/spell/proc/adjust_var(mob/living/target = usr, type, amount) //handles the adjustment of the var when the spell is used. has some hardcoded types - switch(type) - if("bruteloss") - target.take_damage(amount) - if("fireloss") - target.take_damage(amount, BURN) - if("toxloss") - target.take_damage(amount, TOX) - if("oxyloss") - target.take_damage(amount, OXY) - if("brainloss") - target.take_damage(amount, BRAIN) - if("stunned") - ADJ_STATUS(target, STAT_STUN, amount) - if("weakened") - ADJ_STATUS(target, STAT_WEAK, amount) - if("paralysis") - ADJ_STATUS(target, STAT_PARA, amount) - else - target.vars[type] += amount //I bear no responsibility for the runtimes that'll happen if you try to adjust non-numeric or even non-existant vars - return - -/////////////////////////// -/////CASTING WRAPPERS////// -/////////////////////////// - -/spell/proc/before_cast(list/targets) - for(var/atom/target in targets) - if(overlay) - var/location - if(isliving(target)) - location = target.loc - else if(isturf(target)) - location = target - var/obj/effect/overlay/spell = new /obj/effect/overlay(location) - spell.icon = overlay_icon - spell.icon_state = overlay_icon_state - spell.anchored = TRUE - spell.set_density(0) - spawn(overlay_lifespan) - qdel(spell) - -/spell/proc/after_cast(list/targets) - if(cast_sound) - playsound(get_turf(holder),cast_sound,50,1) - for(var/atom/target in targets) - var/location = get_turf(target) - if(isliving(target) && message) - to_chat(target, text("[message]")) - if(sparks_spread) - spark_at(location, amount = sparks_amt) - if(smoke_spread) - if(smoke_spread == 1) - var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread() - smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is - smoke.start() - else if(smoke_spread == 2) - var/datum/effect/effect/system/smoke_spread/bad/smoke = new /datum/effect/effect/system/smoke_spread/bad() - smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is - smoke.start() - -///////////////////// -////CASTING TOOLS//// -///////////////////// -/*Checkers, cost takers, message makers, etc*/ - -/spell/proc/cast_check(skipcharge = 0,mob/user = usr, var/list/targets) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell - - if(silenced > 0) - return 0 - - if(!(src in user.mind.learned_spells) && holder == user && !(isanimal(user))) - error("[user] utilized the spell '[src]' without having it.") - to_chat(user, "You shouldn't have this spell! Something's wrong.") - return 0 - - var/turf/user_turf = get_turf(user) - if(!user_turf) - to_chat(user, "You cannot cast spells in null space!") - - if((spell_flags & Z2NOCAST) && isAdminLevel(user_turf.z)) //Certain spells are not allowed on the centcomm zlevel - return 0 - - if(spell_flags & CONSTRUCT_CHECK) - for(var/turf/T in range(holder, 1)) - if(findNullRod(T)) - return 0 - - if(!src.check_charge(skipcharge, user)) //sees if we can cast based on charges alone - return 0 - - if(holder == user) - if(isanimal(user)) - var/mob/living/simple_animal/SA = user - if(SA.purge) - to_chat(SA, "The null sceptre's power interferes with your own!") - return 0 - - var/mob/living/L = user - if(L.incapacitated(INCAPACITATION_STUNNED|INCAPACITATION_RESTRAINED|INCAPACITATION_BUCKLED_FULLY|INCAPACITATION_FORCELYING|INCAPACITATION_KNOCKOUT)) - to_chat(user, "You can't cast spells while incapacitated!") - return 0 - - if(ishuman(user) && !(invocation_type in list(SpI_EMOTE, SpI_NONE)) && user.get_item_blocking_speech()) - to_chat(user, "Mmmf mrrfff!") - return 0 - - return 1 - -/spell/proc/check_charge(var/skipcharge, mob/user) - if(!skipcharge) - switch(charge_type) - if(Sp_RECHARGE) - if(charge_counter < charge_max) - to_chat(user, still_recharging_msg) - return 0 - if(Sp_CHARGES) - if(!charge_counter) - to_chat(user, "[name] has no charges left.") - return 0 - return 1 - -/spell/proc/take_charge(mob/user = user, var/skipcharge) - if(!skipcharge) - switch(charge_type) - if(Sp_RECHARGE) - charge_counter = 0 //doesn't start recharging until the targets selecting ends - src.process() - return 1 - if(Sp_CHARGES) - charge_counter-- //returns the charge if the targets selecting fails - return 1 - if(Sp_HOLDVAR) - adjust_var(user, holder_var_type, holder_var_amount) - return 1 - return 0 - return 1 - -/spell/proc/check_valid_targets(var/list/targets) - if(!targets) - return 0 - if(!islist(targets)) - targets = list(targets) - else if(!targets.len) - return 0 - - var/list/valid_targets = view_or_range(range, holder, selection_type) - for(var/target in targets) - if(!(target in valid_targets)) - return 0 - return 1 - -/spell/proc/invocation(mob/user = usr, var/list/targets) //spelling the spell out and setting it on recharge/reducing charges amount - - switch(invocation_type) - if(SpI_SHOUT) - if(prob(50))//Auto-mute? Fuck that noise - user.say(invocation) - else - user.say(replacetext(invocation," ","`")) - if(SpI_WHISPER) - if(prob(50)) - user.whisper(invocation) - else - user.whisper(replacetext(invocation," ","`")) - if(SpI_EMOTE) - user.custom_emote(VISIBLE_MESSAGE, invocation) - -///////////////////// -///UPGRADING PROCS/// -///////////////////// - -/spell/proc/can_improve(var/upgrade_type) - if(level_max[Sp_TOTAL] <= ( spell_levels[Sp_SPEED] + spell_levels[Sp_POWER] )) //too many levels, can't do it - return 0 - - //if(upgrade_type && spell_levels[upgrade_type] && level_max[upgrade_type]) - if(upgrade_type && spell_levels[upgrade_type] >= level_max[upgrade_type]) - return 0 - - return 1 - -/spell/proc/empower_spell() - if(!can_improve(Sp_POWER)) - return 0 - - spell_levels[Sp_POWER]++ - - return 1 - -/spell/proc/quicken_spell() - if(!can_improve(Sp_SPEED)) - return 0 - - spell_levels[Sp_SPEED]++ - - if(delay_reduc && cast_delay) - cast_delay = max(0, cast_delay - delay_reduc) - else if(cast_delay) - cast_delay = round( max(0, initial(cast_delay) * ((level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) / level_max[Sp_SPEED] ) ) ) - - if(charge_type == Sp_RECHARGE) - if(cooldown_reduc) - charge_max = max(cooldown_min, charge_max - cooldown_reduc) - else - charge_max = round( max(cooldown_min, initial(charge_max) * ((level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) / level_max[Sp_SPEED] ) ) ) //the fraction of the way you are to max speed levels is the fraction you lose - if(charge_max < charge_counter) - charge_counter = charge_max - - var/temp = "" - name = initial(name) - switch(level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) - if(3) - temp = "You have improved [name] into Efficient [name]." - name = "Efficient [name]" - if(2) - temp = "You have improved [name] into Quickened [name]." - name = "Quickened [name]" - if(1) - temp = "You have improved [name] into Free [name]." - name = "Free [name]" - if(0) - temp = "You have improved [name] into Instant [name]." - name = "Instant [name]" - - return temp - -/spell/proc/spell_do_after(var/mob/user, delay, var/numticks = 5) - if(!user || isnull(user)) - return 0 - - var/incap_flags = INCAPACITATION_STUNNED|INCAPACITATION_RESTRAINED|INCAPACITATION_BUCKLED_FULLY|INCAPACITATION_FORCELYING|INCAPACITATION_KNOCKOUT - return do_after(user,delay, incapacitation_flags = incap_flags) - -/proc/view_or_range(distance = world.view , center = usr , type) - switch(type) - if("view") - . = view(distance,center) - if("range") - . = range(distance,center) \ No newline at end of file diff --git a/code/modules/spells/spells.dm b/code/modules/spells/spells.dm deleted file mode 100644 index ad550747a7ff..000000000000 --- a/code/modules/spells/spells.dm +++ /dev/null @@ -1,60 +0,0 @@ -/datum/mind - var/list/learned_spells - -/mob/Stat() - . = ..() - if(. && ability_master && ability_master.spell_objects) - for(var/obj/screen/ability/spell/screen in ability_master.spell_objects) - var/spell/S = screen.spell - if((!S.connected_button) || !statpanel(S.panel)) - continue //Not showing the noclothes spell - switch(S.charge_type) - if(Sp_RECHARGE) - statpanel(S.panel,"[S.charge_counter/10.0]/[S.charge_max/10]",S.connected_button) - if(Sp_CHARGES) - statpanel(S.panel,"[S.charge_counter]/[S.charge_max]",S.connected_button) - if(Sp_HOLDVAR) - statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S.connected_button) - -/proc/restore_spells(var/mob/H) - if(H.mind && H.mind.learned_spells) - var/list/spells = list() - for(var/spell/spell_to_remove in H.mind.learned_spells) //remove all the spells from other people. - if(ismob(spell_to_remove.holder)) - var/mob/M = spell_to_remove.holder - spells += spell_to_remove - M.remove_spell(spell_to_remove) - - for(var/spell/spell_to_add in spells) - H.add_spell(spell_to_add) - H.ability_master.update_abilities(0,H) - -/mob/proc/add_spell(var/spell/spell_to_add, var/spell_base = "wiz_spell_ready") - if(!ability_master) - ability_master = new(null, src) - spell_to_add.holder = src - if(mind) - if(!mind.learned_spells) - mind.learned_spells = list() - mind.learned_spells |= spell_to_add - ability_master.add_spell(spell_to_add, spell_base) - return 1 - -/mob/proc/remove_spell(var/spell/spell_to_remove) - if(!spell_to_remove || !istype(spell_to_remove)) - return - - if(mind) - mind.learned_spells -= spell_to_remove - if (ability_master) - ability_master.remove_ability(ability_master.get_ability_by_spell(spell_to_remove)) - return 1 - -/mob/proc/silence_spells(var/amount = 0) - if(amount < 0) - return - - if(!ability_master) - return - - ability_master.silence_spells(amount) \ No newline at end of file diff --git a/code/modules/spells/targeted/ethereal_jaunt.dm b/code/modules/spells/targeted/ethereal_jaunt.dm deleted file mode 100644 index 55a0ed83359d..000000000000 --- a/code/modules/spells/targeted/ethereal_jaunt.dm +++ /dev/null @@ -1,120 +0,0 @@ -/spell/targeted/ethereal_jaunt - name = "Ethereal Jaunt" - desc = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls." - feedback = "EJ" - school = "transmutation" - charge_max = 30 SECONDS - spell_flags = Z2NOCAST | INCLUDEUSER - invocation = "none" - invocation_type = SpI_NONE - range = 0 - max_targets = 1 - level_max = list(Sp_TOTAL = 4, Sp_SPEED = 4, Sp_POWER = 3) - cooldown_min = 10 SECONDS //50 deciseconds reduction per rank - duration = 5 SECONDS - - hud_state = "wiz_jaunt" - -/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded - for(var/mob/living/target in targets) - if(HAS_TRANSFORMATION_MOVEMENT_HANDLER(target)) - continue - - if(target.buckled) - target.buckled.unbuckle_mob() - spawn(0) - var/mobloc = get_turf(target.loc) - var/obj/effect/dummy/spell_jaunt/holder = new /obj/effect/dummy/spell_jaunt( mobloc ) - var/atom/movable/overlay/animation = new /atom/movable/overlay(holder) - animation.SetName("water") - animation.set_density(0) - animation.anchored = TRUE - animation.icon = 'icons/mob/mob.dmi' - animation.layer = FLY_LAYER - target.extinguish_fire() - if(target.buckled) - target.buckled = null - jaunt_disappear(animation, target) - target.forceMove(holder) - jaunt_steam(mobloc) - sleep(duration) - mobloc = holder.last_valid_turf - animation.forceMove(mobloc) - jaunt_steam(mobloc) - holder.reappearing = 1 - sleep(20) - jaunt_reappear(animation, target) - sleep(5) - if(!target.forceMove(mobloc)) - for(var/direction in list(1,2,4,8,5,6,9,10)) - var/turf/T = get_step(mobloc, direction) - if(T) - if(target.forceMove(T)) - break - target.client.eye = target - qdel(animation) - qdel(holder) - -/spell/targeted/ethereal_jaunt/empower_spell() - if(!..()) - return 0 - duration += 2 SECONDS - - return "[src] now lasts longer." - -/spell/targeted/ethereal_jaunt/proc/jaunt_disappear(var/atom/movable/overlay/animation, var/mob/living/target) - animation.icon_state = "liquify" - flick("liquify",animation) - playsound(get_turf(target), 'sound/magic/ethereal_enter.ogg', 30) - -/spell/targeted/ethereal_jaunt/proc/jaunt_reappear(var/atom/movable/overlay/animation, var/mob/living/target) - flick("reappear",animation) - playsound(get_turf(target), 'sound/magic/ethereal_exit.ogg', 30) - -/spell/targeted/ethereal_jaunt/proc/jaunt_steam(var/mobloc) - var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread() - steam.set_up(10, 0, mobloc) - steam.start() - -/obj/effect/dummy/spell_jaunt - name = "water" - icon = 'icons/effects/effects.dmi' - icon_state = "nothing" - var/canmove = 1 - var/reappearing = 0 - density = FALSE - anchored = TRUE - var/turf/last_valid_turf - -/obj/effect/dummy/spell_jaunt/Initialize() - . = ..() - last_valid_turf = get_turf(loc) - -/obj/effect/dummy/spell_jaunt/Destroy() - // Eject contents if deleted somehow - for(var/atom/movable/AM in src) - AM.dropInto(loc) - return ..() - -/obj/effect/dummy/spell_jaunt/relaymove(var/mob/user, direction) - if (!canmove || reappearing) return - var/turf/newLoc = get_step(src, direction) - if(!(newLoc.turf_flags & TURF_FLAG_NOJAUNT)) - forceMove(newLoc) - var/turf/T = get_turf(loc) - if(!T.contains_dense_objects()) - last_valid_turf = T - else - to_chat(user, "Some strange aura is blocking the way!") - canmove = 0 - addtimer(CALLBACK(src, PROC_REF(allow_move)), 2) - -/obj/effect/dummy/spell_jaunt/proc/allow_move() - canmove = TRUE - -/obj/effect/dummy/spell_jaunt/explosion_act(blah) - SHOULD_CALL_PARENT(FALSE) - return - -/obj/effect/dummy/spell_jaunt/bullet_act(blah) - return diff --git a/code/modules/spells/targeted/shift.dm b/code/modules/spells/targeted/shift.dm deleted file mode 100644 index 2bcc684939a6..000000000000 --- a/code/modules/spells/targeted/shift.dm +++ /dev/null @@ -1,24 +0,0 @@ -/spell/targeted/ethereal_jaunt/shift - name = "Phase Shift" - desc = "This spell allows you to pass through walls" - - charge_max = 200 - spell_flags = Z2NOCAST | INCLUDEUSER | CONSTRUCT_CHECK - invocation_type = SpI_NONE - range = -1 - duration = 50 //in deciseconds - - hud_state = "const_shift" - -/spell/targeted/ethereal_jaunt/shift/jaunt_disappear(var/atom/movable/overlay/animation, var/mob/living/target) - animation.icon_state = "phase_shift" - animation.set_dir(target.dir) - flick("phase_shift",animation) - -/spell/targeted/ethereal_jaunt/shift/jaunt_reappear(var/atom/movable/overlay/animation, var/mob/living/target) - animation.icon_state = "phase_shift2" - animation.set_dir(target.dir) - flick("phase_shift2",animation) - -/spell/targeted/ethereal_jaunt/shift/jaunt_steam(var/mobloc) - return diff --git a/code/modules/spells/targeted/targeted.dm b/code/modules/spells/targeted/targeted.dm deleted file mode 100644 index 733bbf1e5403..000000000000 --- a/code/modules/spells/targeted/targeted.dm +++ /dev/null @@ -1,152 +0,0 @@ -/* -Targeted spells (with the exception of dumbfire) select from all the mobs in the defined range -Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are explained in setup.dm -*/ - -/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob - var/max_targets = 1 //leave 0 for unlimited targets in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range - var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast - - - var/amt_weakened = 0 - var/amt_paralysis = 0 - var/amt_stunned = 0 - - var/amt_dizziness = 0 - var/amt_confused = 0 - var/amt_stuttering = 0 - - //set to negatives for healing unless commented otherwise - var/amt_dam_fire = 0 - var/amt_dam_brute = 0 - var/amt_dam_oxy = 0 - var/amt_dam_tox = 0 - var/amt_dam_robo = 0 - var/amt_brain = 0 - var/amt_radiation = 0 - var/amt_blood = 0 //Positive numbers to add blood - var/amt_organ = 0 //Positive numbers for healing - - var/amt_eye_blind = 0 - var/amt_eye_blurry = 0 - - var/effect_state = null //What effect to show on each, if any - var/effect_duration = 0 - var/effect_color = "#ffffff" - - var/list/compatible_mobs = list() - - -/spell/targeted/choose_targets(mob/user = usr) - var/list/targets = list() - - if(max_targets == 0) //unlimited - if(range == -2) - targets = global.living_mob_list_ - else - for(var/mob/living/target in view_or_range(range, holder, selection_type)) - targets += target - - else if(max_targets == 1) //single target can be picked - if((range == 0 || range == -1) && spell_flags & INCLUDEUSER) - targets += user - else - var/list/possible_targets = list() - var/list/starting_targets - if(range == -2) - starting_targets = global.living_mob_list_ - else - starting_targets = view_or_range(range, holder, selection_type) - - for(var/mob/living/M in starting_targets) - if(!(spell_flags & INCLUDEUSER) && M == user) - continue - if(compatible_mobs && compatible_mobs.len) - if(!is_type_in_list(M, compatible_mobs)) continue - if(compatible_mobs && compatible_mobs.len && !is_type_in_list(M, compatible_mobs)) - continue - possible_targets += M - - if(possible_targets.len) - targets += pick(possible_targets) - //Adds a safety check post-input to make sure those targets are actually in range. - - - else - var/list/possible_targets = list() - var/list/starting_targets - - if(range == -2) - starting_targets = global.living_mob_list_ - else - starting_targets = view_or_range(range, holder, selection_type) - - for(var/mob/living/target in starting_targets) - if(!(spell_flags & INCLUDEUSER) && target == user) - continue - if(compatible_mobs && !is_type_in_list(target, compatible_mobs)) - continue - possible_targets += target - - for(var/i=1,i<=max_targets,i++) - if(!possible_targets.len) - break - if(target_ignore_prev) - var/target = pick(possible_targets) - possible_targets -= target - targets += target - else - targets += pick(possible_targets) - - if(!(spell_flags & INCLUDEUSER) && (user in targets)) - targets -= user - - if(compatible_mobs && compatible_mobs.len) - for(var/mob/living/target in targets) //filters out all the non-compatible mobs - if(!is_type_in_list(target, compatible_mobs)) - targets -= target - - return targets - -/spell/targeted/cast(var/list/targets, mob/user) - for(var/mob/living/target in targets) - if(range >= 0) - if(!(target in view_or_range(range, holder, selection_type))) //filter at time of casting - targets -= target - continue - apply_spell_damage(target) - -/spell/targeted/proc/apply_spell_damage(mob/living/target) - target.take_damage(amt_dam_brute, do_update_health = FALSE) - target.take_damage(amt_dam_fire, BURN, do_update_health = FALSE) - target.take_damage(amt_dam_tox, TOX, do_update_health = FALSE) - target.take_damage(amt_dam_oxy, OXY) - if(ishuman(target)) - var/mob/living/human/H = target - for(var/obj/item/organ/internal/affecting in H.get_internal_organs()) - if(affecting && istype(affecting)) - affecting.heal_damage(amt_organ, amt_organ) - for(var/obj/item/organ/external/affecting in H.get_external_organs()) - if(affecting && istype(affecting)) - var/dam = BP_IS_PROSTHETIC(affecting) ? -amt_dam_robo : amt_organ - affecting.heal_damage(dam, dam, robo_repair = BP_IS_PROSTHETIC(affecting)) - H.adjust_blood(amt_blood) - H.take_damage(amt_brain, BRAIN) - H.radiation += min(H.radiation, amt_radiation) - - target.update_icon() - //disabling - SET_STATUS_MAX(target, STAT_WEAK, amt_weakened) - SET_STATUS_MAX(target, STAT_PARA, amt_paralysis) - SET_STATUS_MAX(target, STAT_STUN, amt_stunned) - if(amt_weakened || amt_paralysis || amt_stunned) - if(target.buckled) - target.buckled = null - ADJ_STATUS(target, STAT_BLIND, amt_eye_blind) - ADJ_STATUS(target, STAT_BLURRY, amt_eye_blurry) - ADJ_STATUS(target, STAT_DIZZY, amt_dizziness) - ADJ_STATUS(target, STAT_CONFUSE, amt_confused) - ADJ_STATUS(target, STAT_STUTTER, amt_stuttering) - if(effect_state) - var/obj/o = new /obj/effect/temporary(get_turf(target), effect_duration, 'icons/effects/effects.dmi', effect_state) - o.color = effect_color diff --git a/code/modules/submaps/submap_job.dm b/code/modules/submaps/submap_job.dm index 9bc3687a1aed..89d8b2f38718 100644 --- a/code/modules/submaps/submap_job.dm +++ b/code/modules/submaps/submap_job.dm @@ -7,7 +7,8 @@ create_record = FALSE total_positions = 4 outfit_type = /decl/outfit/job/survivor - hud_icon = "hudblank" + hud_icon_state = "hudblank" + hud_icon = null available_by_default = FALSE allowed_ranks = null allowed_branches = null @@ -55,7 +56,12 @@ if(islist(blacklisted_species) && !length(blacklisted_species)) blacklisted_species |= SSmodpacks.default_submap_blacklisted_species - if(!abstract_job) + if(abstract_job) + if(!hud_icon) + hud_icon = global.using_map.hud_icons + if(!hud_icon_state) + hud_icon_state = "hud[ckey(title)]" + else spawnpoints = list() owner = _owner ..() diff --git a/code/modules/tools/components/head.dm b/code/modules/tools/components/head.dm index 5d7aa85f5120..e8e408c7c761 100644 --- a/code/modules/tools/components/head.dm +++ b/code/modules/tools/components/head.dm @@ -40,6 +40,11 @@ var/global/list/_tool_properties_cache = list() desc = "The head of a hoe." icon_state = "hoe" +/obj/item/tool_component/head/chisel + name = "chisel head" + desc = "The head of a chisel." + icon_state = "hoe" + /obj/item/tool_component/head/handaxe name = "hand axe head" desc = "The head of a hand axe." @@ -58,3 +63,8 @@ var/global/list/_tool_properties_cache = list() icon_state = "sledgehammer" w_class = ITEM_SIZE_NORMAL +/obj/item/tool_component/head/forging_hammer + name = "forging hammer head" + desc = "The head of a forging hammer." + icon_state = "forging" + w_class = ITEM_SIZE_NORMAL diff --git a/code/modules/tools/subtypes/axes.dm b/code/modules/tools/subtypes/axes.dm index d2de61af41bc..495350175640 100644 --- a/code/modules/tools/subtypes/axes.dm +++ b/code/modules/tools/subtypes/axes.dm @@ -22,6 +22,9 @@ material = /decl/material/solid/metal/iron handle_material = /decl/material/solid/organic/wood/ebony +/obj/item/tool/axe/iron + material = /decl/material/solid/metal/iron + /obj/item/tool/axe/ebony/bronze material = /decl/material/solid/metal/bronze diff --git a/code/modules/tools/subtypes/hammers.dm b/code/modules/tools/subtypes/hammers.dm index bb1c9ee58cd5..79e5e26956dc 100644 --- a/code/modules/tools/subtypes/hammers.dm +++ b/code/modules/tools/subtypes/hammers.dm @@ -79,3 +79,18 @@ TOOL_SHOVEL = TOOL_QUALITY_DECENT ) return tool_qualities + +/obj/item/tool/hammer/forge + name = "forging hammer" + desc = "A heavy hammer, used to forge hot metal at an anvil." + icon = 'icons/obj/items/tool/hammers/forge.dmi' + w_class = ITEM_SIZE_NORMAL + +// Forging hammers are not great at general hammer tasks (too heavy I guess), +// and also don't work as crowbars due to missing the nail ripper/flange, +// but will be more effective at forging when blacksmithy is merged. +/obj/item/tool/hammer/forge/get_initial_tool_qualities() + var/static/list/tool_qualities = list( + TOOL_HAMMER = TOOL_QUALITY_MEDIOCRE + ) + return tool_qualities diff --git a/code/modules/xenoarcheaology/artifacts/standalone/gigadrill.dm b/code/modules/xenoarcheaology/artifacts/standalone/gigadrill.dm index e41572bbd635..22e68e9011e4 100644 --- a/code/modules/xenoarcheaology/artifacts/standalone/gigadrill.dm +++ b/code/modules/xenoarcheaology/artifacts/standalone/gigadrill.dm @@ -1,7 +1,7 @@ /obj/machinery/giga_drill name = "alien drill" desc = "A giant, alien drill mounted on long treads." - icon = 'icons/obj/mining.dmi' + icon = 'icons/obj/machines/gigadrill.dmi' icon_state = "gigadrill" var/active = 0 var/drill_time = 10 diff --git a/code/modules/xenoarcheaology/boulder.dm b/code/modules/xenoarcheaology/boulder.dm index ad492eb65ef1..ba7a38c2f3d2 100644 --- a/code/modules/xenoarcheaology/boulder.dm +++ b/code/modules/xenoarcheaology/boulder.dm @@ -1,8 +1,8 @@ /obj/structure/boulder name = "boulder" desc = "A large boulder, somewhat bigger than a small boulder." - icon = 'icons/obj/mining.dmi' - icon_state = "boulder1" + icon = 'icons/obj/structures/boulder.dmi' + icon_state = ICON_STATE_WORLD density = TRUE opacity = TRUE anchored = TRUE @@ -30,7 +30,7 @@ /obj/structure/boulder/Initialize(var/ml, var/_mat, var/coloration) . = ..() - icon_state = "boulder[rand(1,6)]" + icon_state = "[initial(icon_state)][rand(1,6)]" if(coloration) color = coloration excavation_level = rand(5, 50) diff --git a/code/modules/xenoarcheaology/datums/artifact_find.dm b/code/modules/xenoarcheaology/datums/artifact_find.dm index b70f17112e8f..242af56502d5 100644 --- a/code/modules/xenoarcheaology/datums/artifact_find.dm +++ b/code/modules/xenoarcheaology/datums/artifact_find.dm @@ -2,8 +2,6 @@ var/artifact_id var/artifact_find_type var/static/potential_finds = list( - /obj/machinery/power/supermatter = 5, - /obj/machinery/power/supermatter/shard = 25, /obj/machinery/auto_cloner = 100, /obj/machinery/giga_drill = 100, /obj/machinery/replicator = 100, diff --git a/code/modules/xenoarcheaology/tools/tools.dm b/code/modules/xenoarcheaology/tools/tools.dm index 213d77ff1288..813f424e7f14 100644 --- a/code/modules/xenoarcheaology/tools/tools.dm +++ b/code/modules/xenoarcheaology/tools/tools.dm @@ -10,8 +10,8 @@ /obj/item/bag/fossils name = "fossil satchel" desc = "Transports delicate fossils in suspension so they don't break during transit." - icon = 'icons/obj/mining.dmi' - icon_state = "satchel" + icon = 'icons/obj/items/mining_satchel.dmi' + icon_state = ICON_STATE_WORLD slot_flags = SLOT_LOWER_BODY | SLOT_POCKET w_class = ITEM_SIZE_NORMAL storage = /datum/storage/bag/fossils diff --git a/code/unit_tests/icon_tests.dm b/code/unit_tests/icon_tests.dm index 3c003aba22da..58783a20f51c 100644 --- a/code/unit_tests/icon_tests.dm +++ b/code/unit_tests/icon_tests.dm @@ -299,3 +299,64 @@ else pass("All vendors have all icons and icon states.") return 1 + + +/datum/unit_test/HUDS_shall_have_icon_states + name = "ICON STATE: HUD overlays shall have appropriate icon_states" + +/datum/unit_test/HUDS_shall_have_icon_states/start_test() + var/failed_jobs = 0 + var/failed_sanity_checks = 0 + + // Throwing implants and health HUDs in here. + // Antag HUDs are tested by special role validation. + + var/static/list/implant_hud_states = list( + "hud_imp_blank" = "Blank", + "hud_imp_loyal" = "Loyalty", + "hud_imp_unknown" = "Unknown", + "hud_imp_tracking" = "Tracking", + "hud_imp_chem" = "Chemical", + ) + for(var/implant_hud_state in implant_hud_states) + if(!check_state_in_icon(implant_hud_state, global.using_map.implant_hud_icons)) + log_bad("Sanity Check - Missing map [implant_hud_states[implant_hud_state]] implant HUD icon_state '[implant_hud_state]' from icon [global.using_map.implant_hud_icons]") + failed_sanity_checks++ + + var/static/list/med_hud_states = list( + "blank" = "Blank", + "flatline" = "Flatline", + "0" = "Dead", + "1" = "Healthy", + "2" = "Lightly injured", + "3" = "Moderately injured", + "4" = "Severely injured", + "5" = "Dying", + ) + for(var/med_hud_state in med_hud_states) + if(!check_state_in_icon(med_hud_state, global.using_map.med_hud_icons)) + log_bad("Sanity Check - Missing map [med_hud_states[med_hud_state]] medical HUD icon_state '[med_hud_state]' from icon [global.using_map.med_hud_icons]") + failed_sanity_checks++ + var/static/list/global_states = list( + "" = "Default/unnamed", + "hudunknown" = "Unknown role", + "hudhealthy" = "Healthy mob", + "hudill" = "Diseased mob", + "huddead" = "Dead mob" + ) + for(var/global_state in global_states) + if(!check_state_in_icon(global_state, global.using_map.hud_icons)) + log_bad("Sanity Check - Missing map [global_states[global_state]] HUD icon_state '[global_state]' from icon [global.using_map.hud_icons]") + failed_sanity_checks++ + + for(var/job_name in SSjobs.titles_to_datums) + var/datum/job/job = SSjobs.titles_to_datums[job_name] + if(!check_state_in_icon(job.hud_icon_state, job.hud_icon)) + log_bad("[job.title] - Missing HUD icon: [job.hud_icon_state] in icon [job.hud_icon]") + failed_jobs++ + + if(failed_sanity_checks || failed_jobs) + fail("[global.using_map.type] - [failed_sanity_checks] failed sanity check\s, [failed_jobs] job\s with missing HUD icon.") + else + pass("All jobs have a HUD icon.") + return 1 diff --git a/code/unit_tests/job_tests.dm b/code/unit_tests/job_tests.dm index 858063c9bad5..b6b652731f82 100644 --- a/code/unit_tests/job_tests.dm +++ b/code/unit_tests/job_tests.dm @@ -35,36 +35,6 @@ pass("All jobs had outfit types.") return 1 -/datum/unit_test/jobs_shall_have_a_HUD_icon - name = "JOB: Shall have a HUD icon" - -/datum/unit_test/jobs_shall_have_a_HUD_icon/start_test() - var/failed_jobs = 0 - var/failed_sanity_checks = 0 - - var/list/job_huds = get_states_in_icon_cached(global.using_map.id_hud_icons) - - if(!job_huds[""]) - log_bad("Sanity Check - Missing default/unnamed HUD icon") - failed_sanity_checks++ - - if(!job_huds["hudunknown"]) - log_bad("Sanity Check - Missing HUD icon: hudunknown") - failed_sanity_checks++ - - for(var/job_name in SSjobs.titles_to_datums) - var/datum/job/J = SSjobs.titles_to_datums[job_name] - var/hud_icon_state = J.hud_icon - if(!job_huds[hud_icon_state]) - log_bad("[J.title] - Missing HUD icon: [hud_icon_state]") - failed_jobs++ - - if(failed_sanity_checks || failed_jobs) - fail("[global.using_map.id_hud_icons] - [failed_sanity_checks] failed sanity check\s, [failed_jobs] job\s with missing HUD icon.") - else - pass("All jobs have a HUD icon.") - return 1 - /datum/unit_test/jobs_shall_have_a_unique_title name = "JOBS: All Job Datums Shall Have A Unique Title" diff --git a/code/unit_tests/turf_icons.dm b/code/unit_tests/turf_icons.dm index 5cf5cb9dce72..3319864ee2a7 100644 --- a/code/unit_tests/turf_icons.dm +++ b/code/unit_tests/turf_icons.dm @@ -8,8 +8,7 @@ /turf/unsimulated ) var/list/excepted_types = list( - /turf/unsimulated/map, - /turf/unsimulated/wall/cascade + /turf/unsimulated/map ) /datum/unit_test/turf_floor_icons_shall_be_valid/setup_test() diff --git a/html/changelog.html b/html/changelog.html index daa00b874bd0..58aeb978adc1 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -52,6 +52,20 @@ -->
    +

    16 January 2025

    +

    MistakeNot4892 updated:

    + + +

    15 January 2025

    +

    MistakeNot4892 updated:

    + +

    08 January 2025

    MistakeNot4892 updated:

    diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index e0665a0e73fe..65ecf2cbcfd8 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -14948,3 +14948,14 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. 2025-01-08: MistakeNot4892: - tweak: Mud and blood can now leave footprints. +2025-01-15: + MistakeNot4892: + - tweak: The way you interact with barrels and well has been significantly reworked; + clicking with a bucket or tool should give a list of options to pick from. Please + report bugs with this on the tracker. +2025-01-16: + MistakeNot4892: + - tweak: The White and Minimalist HUD styles can now be customised to use a specific + overlay color. + - tweak: The Shaded Hills river now flows north. + - tweak: Snow, mud and sand will now show footprints. diff --git a/html/changelogs/AutoChangeLog-pr-4748.yml b/html/changelogs/AutoChangeLog-pr-4748.yml new file mode 100644 index 000000000000..36462616a457 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-4748.yml @@ -0,0 +1,5 @@ +author: MistakeNot4892 +changes: + - {tweak: 'Intents have been rewritten and moved, please report any issues with + intent selection.'} +delete-after: true diff --git a/icons/effects/crayondecal.dmi b/icons/effects/crayondecal.dmi index e1966e9bb5ae..3642e8ed8f4d 100644 Binary files a/icons/effects/crayondecal.dmi and b/icons/effects/crayondecal.dmi differ diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 78c4315424ac..5502343f0d55 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/effects/landmarks.dmi b/icons/effects/landmarks.dmi index 7c5729455bf6..28317726409f 100644 Binary files a/icons/effects/landmarks.dmi and b/icons/effects/landmarks.dmi differ diff --git a/icons/effects/liquids.dmi b/icons/effects/liquids.dmi index 965e319bc4af..7cdf5d1b0067 100644 Binary files a/icons/effects/liquids.dmi and b/icons/effects/liquids.dmi differ diff --git a/icons/effects/projectiles/trail.dmi b/icons/effects/projectiles/trail.dmi new file mode 100644 index 000000000000..4e058a3f1bfd Binary files /dev/null and b/icons/effects/projectiles/trail.dmi differ diff --git a/icons/mob/footprints/footprints.dmi b/icons/mob/footprints/footprints.dmi new file mode 100644 index 000000000000..2d9699e82c8d Binary files /dev/null and b/icons/mob/footprints/footprints.dmi differ diff --git a/icons/mob/footprints/footprints_paw.dmi b/icons/mob/footprints/footprints_paw.dmi new file mode 100644 index 000000000000..08fac62a016c Binary files /dev/null and b/icons/mob/footprints/footprints_paw.dmi differ diff --git a/icons/mob/footprints/footprints_snake.dmi b/icons/mob/footprints/footprints_snake.dmi new file mode 100644 index 000000000000..6e913803eb12 Binary files /dev/null and b/icons/mob/footprints/footprints_snake.dmi differ diff --git a/icons/mob/footprints/footprints_trail.dmi b/icons/mob/footprints/footprints_trail.dmi new file mode 100644 index 000000000000..944ed4e175b4 Binary files /dev/null and b/icons/mob/footprints/footprints_trail.dmi differ diff --git a/icons/mob/footprints/footprints_wheelchair.dmi b/icons/mob/footprints/footprints_wheelchair.dmi new file mode 100644 index 000000000000..4a2e800cf76b Binary files /dev/null and b/icons/mob/footprints/footprints_wheelchair.dmi differ diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi deleted file mode 100644 index ed608471041b..000000000000 Binary files a/icons/mob/hud.dmi and /dev/null differ diff --git a/icons/mob/hud_med.dmi b/icons/mob/hud_med.dmi deleted file mode 100644 index 705886a5490f..000000000000 Binary files a/icons/mob/hud_med.dmi and /dev/null differ diff --git a/icons/mob/screen/abilities.dmi b/icons/mob/screen/abilities.dmi new file mode 100644 index 000000000000..ca7d904bd71d Binary files /dev/null and b/icons/mob/screen/abilities.dmi differ diff --git a/icons/mob/screen/ability_inhand.dmi b/icons/mob/screen/ability_inhand.dmi new file mode 100644 index 000000000000..63e1b630dc06 Binary files /dev/null and b/icons/mob/screen/ability_inhand.dmi differ diff --git a/icons/mob/screen/phenomena.dmi b/icons/mob/screen/phenomena.dmi deleted file mode 100644 index f1d05fa97306..000000000000 Binary files a/icons/mob/screen/phenomena.dmi and /dev/null differ diff --git a/icons/mob/screen/spells.dmi b/icons/mob/screen/spells.dmi deleted file mode 100644 index d574921544df..000000000000 Binary files a/icons/mob/screen/spells.dmi and /dev/null differ diff --git a/icons/mob/screen/styles/intents.dmi b/icons/mob/screen/styles/intents.dmi deleted file mode 100644 index 3b0b33f84909..000000000000 Binary files a/icons/mob/screen/styles/intents.dmi and /dev/null differ diff --git a/icons/mob/screen/styles/intents_wide.dmi b/icons/mob/screen/styles/intents_wide.dmi deleted file mode 100644 index fc26d305f6b0..000000000000 Binary files a/icons/mob/screen/styles/intents_wide.dmi and /dev/null differ diff --git a/icons/mob/screen/styles/minimalist/attack_selector.dmi b/icons/mob/screen/styles/minimalist/attack_selector.dmi index c5a7e57c5220..2e3d66fd059a 100644 Binary files a/icons/mob/screen/styles/minimalist/attack_selector.dmi and b/icons/mob/screen/styles/minimalist/attack_selector.dmi differ diff --git a/icons/mob/screen/styles/minimalist/fire_intent.dmi b/icons/mob/screen/styles/minimalist/fire_intent.dmi index 62efd8ca8676..02a311ec4e88 100644 Binary files a/icons/mob/screen/styles/minimalist/fire_intent.dmi and b/icons/mob/screen/styles/minimalist/fire_intent.dmi differ diff --git a/icons/mob/screen/styles/minimalist/hands.dmi b/icons/mob/screen/styles/minimalist/hands.dmi index 28264b0635f1..05840e72af8e 100644 Binary files a/icons/mob/screen/styles/minimalist/hands.dmi and b/icons/mob/screen/styles/minimalist/hands.dmi differ diff --git a/icons/mob/screen/styles/minimalist/interaction.dmi b/icons/mob/screen/styles/minimalist/interaction.dmi index 8a4875e964fa..b8c4a0b80fe8 100644 Binary files a/icons/mob/screen/styles/minimalist/interaction.dmi and b/icons/mob/screen/styles/minimalist/interaction.dmi differ diff --git a/icons/mob/screen/styles/minimalist/inventory.dmi b/icons/mob/screen/styles/minimalist/inventory.dmi index d2d055fe7533..169c66eefdd0 100644 Binary files a/icons/mob/screen/styles/minimalist/inventory.dmi and b/icons/mob/screen/styles/minimalist/inventory.dmi differ diff --git a/icons/mob/screen/styles/minimalist/movement.dmi b/icons/mob/screen/styles/minimalist/movement.dmi index 3a3115d5b882..fa354873156d 100644 Binary files a/icons/mob/screen/styles/minimalist/movement.dmi and b/icons/mob/screen/styles/minimalist/movement.dmi differ diff --git a/icons/mob/screen/styles/minimalist/uphint.dmi b/icons/mob/screen/styles/minimalist/uphint.dmi index fc54e68b933e..412cab2b32dc 100644 Binary files a/icons/mob/screen/styles/minimalist/uphint.dmi and b/icons/mob/screen/styles/minimalist/uphint.dmi differ diff --git a/icons/mob/screen/styles/minimalist/zone_selector.dmi b/icons/mob/screen/styles/minimalist/zone_selector.dmi index 9a35a9acd278..2cdd0893f6ae 100644 Binary files a/icons/mob/screen/styles/minimalist/zone_selector.dmi and b/icons/mob/screen/styles/minimalist/zone_selector.dmi differ diff --git a/icons/mob/screen/styles/underworld/attack_selector.dmi b/icons/mob/screen/styles/underworld/attack_selector.dmi new file mode 100644 index 000000000000..2df7a24c30db Binary files /dev/null and b/icons/mob/screen/styles/underworld/attack_selector.dmi differ diff --git a/icons/mob/screen/styles/underworld/fire_intent.dmi b/icons/mob/screen/styles/underworld/fire_intent.dmi new file mode 100644 index 000000000000..1f7c93487fd0 Binary files /dev/null and b/icons/mob/screen/styles/underworld/fire_intent.dmi differ diff --git a/icons/mob/screen/styles/underworld/hands.dmi b/icons/mob/screen/styles/underworld/hands.dmi new file mode 100644 index 000000000000..fd37369cc082 Binary files /dev/null and b/icons/mob/screen/styles/underworld/hands.dmi differ diff --git a/icons/mob/screen/styles/underworld/interaction.dmi b/icons/mob/screen/styles/underworld/interaction.dmi new file mode 100644 index 000000000000..ce806127f530 Binary files /dev/null and b/icons/mob/screen/styles/underworld/interaction.dmi differ diff --git a/icons/mob/screen/styles/underworld/inventory.dmi b/icons/mob/screen/styles/underworld/inventory.dmi new file mode 100644 index 000000000000..b576bd3b4df9 Binary files /dev/null and b/icons/mob/screen/styles/underworld/inventory.dmi differ diff --git a/icons/mob/screen/styles/underworld/movement.dmi b/icons/mob/screen/styles/underworld/movement.dmi new file mode 100644 index 000000000000..6890efd9fa4e Binary files /dev/null and b/icons/mob/screen/styles/underworld/movement.dmi differ diff --git a/icons/mob/screen/styles/underworld/uphint.dmi b/icons/mob/screen/styles/underworld/uphint.dmi new file mode 100644 index 000000000000..4d78c55da726 Binary files /dev/null and b/icons/mob/screen/styles/underworld/uphint.dmi differ diff --git a/icons/mob/screen/styles/underworld/zone_selector.dmi b/icons/mob/screen/styles/underworld/zone_selector.dmi new file mode 100644 index 000000000000..e482039b230f Binary files /dev/null and b/icons/mob/screen/styles/underworld/zone_selector.dmi differ diff --git a/icons/mob/screen/styles/white/attack_selector.dmi b/icons/mob/screen/styles/white/attack_selector.dmi index 6aa6118a7438..02f97413e1a4 100644 Binary files a/icons/mob/screen/styles/white/attack_selector.dmi and b/icons/mob/screen/styles/white/attack_selector.dmi differ diff --git a/icons/mob/screen/styles/white/fire_intent.dmi b/icons/mob/screen/styles/white/fire_intent.dmi index 5ab217edcd5c..64af8d1e0789 100644 Binary files a/icons/mob/screen/styles/white/fire_intent.dmi and b/icons/mob/screen/styles/white/fire_intent.dmi differ diff --git a/icons/mob/screen/styles/white/hands.dmi b/icons/mob/screen/styles/white/hands.dmi index 59702d43b992..0f65b9904670 100644 Binary files a/icons/mob/screen/styles/white/hands.dmi and b/icons/mob/screen/styles/white/hands.dmi differ diff --git a/icons/mob/screen/styles/white/interaction.dmi b/icons/mob/screen/styles/white/interaction.dmi index e11d10d2c137..8511d73937a2 100644 Binary files a/icons/mob/screen/styles/white/interaction.dmi and b/icons/mob/screen/styles/white/interaction.dmi differ diff --git a/icons/mob/screen/styles/white/inventory.dmi b/icons/mob/screen/styles/white/inventory.dmi index 0ce80198e6bc..f8cfa9cbbc54 100644 Binary files a/icons/mob/screen/styles/white/inventory.dmi and b/icons/mob/screen/styles/white/inventory.dmi differ diff --git a/icons/mob/screen/styles/white/movement.dmi b/icons/mob/screen/styles/white/movement.dmi index 17faaf9413df..b3a61c63a9be 100644 Binary files a/icons/mob/screen/styles/white/movement.dmi and b/icons/mob/screen/styles/white/movement.dmi differ diff --git a/icons/mob/screen/styles/white/uphint.dmi b/icons/mob/screen/styles/white/uphint.dmi index d3e9075d7042..ee795947c302 100644 Binary files a/icons/mob/screen/styles/white/uphint.dmi and b/icons/mob/screen/styles/white/uphint.dmi differ diff --git a/icons/mob/screen/styles/white/zone_selector.dmi b/icons/mob/screen/styles/white/zone_selector.dmi index fe86e824f98b..1e768fdd53d2 100644 Binary files a/icons/mob/screen/styles/white/zone_selector.dmi and b/icons/mob/screen/styles/white/zone_selector.dmi differ diff --git a/icons/obj/items/chain.dmi b/icons/obj/items/chain.dmi new file mode 100644 index 000000000000..95d5c71b70f3 Binary files /dev/null and b/icons/obj/items/chain.dmi differ diff --git a/icons/obj/items/hook.dmi b/icons/obj/items/hook.dmi new file mode 100644 index 000000000000..602683208c76 Binary files /dev/null and b/icons/obj/items/hook.dmi differ diff --git a/icons/obj/items/horseshoe.dmi b/icons/obj/items/horseshoe.dmi new file mode 100644 index 000000000000..15f6f5f2482a Binary files /dev/null and b/icons/obj/items/horseshoe.dmi differ diff --git a/icons/obj/items/mining_satchel.dmi b/icons/obj/items/mining_satchel.dmi new file mode 100644 index 000000000000..64d0ded92578 Binary files /dev/null and b/icons/obj/items/mining_satchel.dmi differ diff --git a/icons/obj/items/sheet_snatcher.dmi b/icons/obj/items/sheet_snatcher.dmi new file mode 100644 index 000000000000..7a898ac6f09c Binary files /dev/null and b/icons/obj/items/sheet_snatcher.dmi differ diff --git a/icons/obj/items/shield/buckler.dmi b/icons/obj/items/shield/buckler.dmi deleted file mode 100644 index ff53a0e14e07..000000000000 Binary files a/icons/obj/items/shield/buckler.dmi and /dev/null differ diff --git a/icons/obj/items/shield/buckler_base_metal.dmi b/icons/obj/items/shield/buckler_base_metal.dmi new file mode 100644 index 000000000000..41372efa755f Binary files /dev/null and b/icons/obj/items/shield/buckler_base_metal.dmi differ diff --git a/icons/obj/items/shield/buckler_base_wood.dmi b/icons/obj/items/shield/buckler_base_wood.dmi new file mode 100644 index 000000000000..03e9bc34a6dc Binary files /dev/null and b/icons/obj/items/shield/buckler_base_wood.dmi differ diff --git a/icons/obj/items/shield/buckler_metal.dmi b/icons/obj/items/shield/buckler_metal.dmi new file mode 100644 index 000000000000..0d27f07c23eb Binary files /dev/null and b/icons/obj/items/shield/buckler_metal.dmi differ diff --git a/icons/obj/items/shield/buckler_wood.dmi b/icons/obj/items/shield/buckler_wood.dmi new file mode 100644 index 000000000000..94e4563a342b Binary files /dev/null and b/icons/obj/items/shield/buckler_wood.dmi differ diff --git a/icons/obj/items/shield_fasteners.dmi b/icons/obj/items/shield_fasteners.dmi new file mode 100644 index 000000000000..e4c289ffc0c0 Binary files /dev/null and b/icons/obj/items/shield_fasteners.dmi differ diff --git a/icons/obj/items/tool/chisel.dmi b/icons/obj/items/tool/chisel.dmi new file mode 100644 index 000000000000..e277e1ba44b6 Binary files /dev/null and b/icons/obj/items/tool/chisel.dmi differ diff --git a/icons/obj/items/tool/components/tool_head.dmi b/icons/obj/items/tool/components/tool_head.dmi index dbb7e7db2bcf..cc9a43d99710 100644 Binary files a/icons/obj/items/tool/components/tool_head.dmi and b/icons/obj/items/tool/components/tool_head.dmi differ diff --git a/icons/obj/items/tool/hammers/forge.dmi b/icons/obj/items/tool/hammers/forge.dmi new file mode 100644 index 000000000000..a7b0a4e06110 Binary files /dev/null and b/icons/obj/items/tool/hammers/forge.dmi differ diff --git a/icons/obj/machines/gigadrill.dmi b/icons/obj/machines/gigadrill.dmi new file mode 100644 index 000000000000..bcbda6a51446 Binary files /dev/null and b/icons/obj/machines/gigadrill.dmi differ diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi deleted file mode 100644 index 0bf325c1efba..000000000000 Binary files a/icons/obj/mining.dmi and /dev/null differ diff --git a/icons/obj/structures/boulder.dmi b/icons/obj/structures/boulder.dmi new file mode 100644 index 000000000000..dc83a3022396 Binary files /dev/null and b/icons/obj/structures/boulder.dmi differ diff --git a/icons/obj/structures/forging/bellows.dmi b/icons/obj/structures/forging/bellows.dmi new file mode 100644 index 000000000000..9e6031422efe Binary files /dev/null and b/icons/obj/structures/forging/bellows.dmi differ diff --git a/icons/obj/structures/ore_box.dmi b/icons/obj/structures/ore_box.dmi new file mode 100644 index 000000000000..c9eea92cfd2d Binary files /dev/null and b/icons/obj/structures/ore_box.dmi differ diff --git a/icons/obj/structures/snowmen/snowbot.dmi b/icons/obj/structures/snowmen/snowbot.dmi new file mode 100644 index 000000000000..c209cf5e8687 Binary files /dev/null and b/icons/obj/structures/snowmen/snowbot.dmi differ diff --git a/icons/obj/structures/snowmen/snowman.dmi b/icons/obj/structures/snowmen/snowman.dmi new file mode 100644 index 000000000000..c174da4bb4d0 Binary files /dev/null and b/icons/obj/structures/snowmen/snowman.dmi differ diff --git a/icons/obj/structures/snowmen/snowspider.dmi b/icons/obj/structures/snowmen/snowspider.dmi new file mode 100644 index 000000000000..bc7af6f5b8cf Binary files /dev/null and b/icons/obj/structures/snowmen/snowspider.dmi differ diff --git a/icons/obj/wizard.dmi b/icons/obj/wizard.dmi index 49d879d47d83..b8ebfc011088 100644 Binary files a/icons/obj/wizard.dmi and b/icons/obj/wizard.dmi differ diff --git a/icons/screen/hud.dmi b/icons/screen/hud.dmi new file mode 100644 index 000000000000..b8d981293699 Binary files /dev/null and b/icons/screen/hud.dmi differ diff --git a/icons/screen/hud_antag.dmi b/icons/screen/hud_antag.dmi new file mode 100644 index 000000000000..07840ff2614e Binary files /dev/null and b/icons/screen/hud_antag.dmi differ diff --git a/icons/screen/hud_implants.dmi b/icons/screen/hud_implants.dmi new file mode 100644 index 000000000000..5899f696f70d Binary files /dev/null and b/icons/screen/hud_implants.dmi differ diff --git a/icons/screen/hud_med.dmi b/icons/screen/hud_med.dmi new file mode 100644 index 000000000000..280097c8166c Binary files /dev/null and b/icons/screen/hud_med.dmi differ diff --git a/icons/screen/intents.dmi b/icons/screen/intents.dmi index 23e147992e03..3e7992ed2c99 100644 Binary files a/icons/screen/intents.dmi and b/icons/screen/intents.dmi differ diff --git a/icons/screen/intents_wide.dmi b/icons/screen/intents_wide.dmi index 9f210bc1c2d9..a89c5ee023dd 100644 Binary files a/icons/screen/intents_wide.dmi and b/icons/screen/intents_wide.dmi differ diff --git a/maps/away/liberia/hud.dmi b/maps/away/liberia/hud.dmi new file mode 100644 index 000000000000..01fe4cbfcd4f Binary files /dev/null and b/maps/away/liberia/hud.dmi differ diff --git a/maps/away/liberia/liberia_jobs.dm b/maps/away/liberia/liberia_jobs.dm index 4d3b627143f2..34269ce2cd3a 100644 --- a/maps/away/liberia/liberia_jobs.dm +++ b/maps/away/liberia/liberia_jobs.dm @@ -11,7 +11,8 @@ info = "You are free traders who have drifted into unknown distances in search of profit. Travel, trade, make profit!" supervisors = "the invisible hand of the market" selection_color = "#515151" - + hud_icon = 'maps/away/liberia/hud.dmi' + hud_icon_state = "hudmerchant" ideal_character_age = 20 minimal_player_age = 7 diff --git a/maps/away/unishi/unishi.dm b/maps/away/unishi/unishi.dm index a1670a3978c6..de64aad2f44c 100644 --- a/maps/away/unishi/unishi.dm +++ b/maps/away/unishi/unishi.dm @@ -1,6 +1,7 @@ #include "unishi_areas.dm" #include "unishi_jobs.dm" #include "../../../mods/content/xenobiology/_xenobiology.dme" +#include "../../../mods/content/supermatter/_supermatter.dme" /obj/abstract/submap_landmark/joinable_submap/unishi name = "SRV Verne" diff --git a/maps/example/example_jobs.dm b/maps/example/example_jobs.dm index e3ad5c0c4884..28d5cf504c67 100644 --- a/maps/example/example_jobs.dm +++ b/maps/example/example_jobs.dm @@ -1,7 +1,6 @@ /datum/map/example default_job_type = /datum/job/example default_department_type = /decl/department/example - id_hud_icons = 'maps/example/hud.dmi' /datum/job/example title = "Tourist" @@ -13,9 +12,10 @@ access = list() minimal_access = list() outfit_type = /decl/outfit/job/tourist + hud_icon = 'maps/example/hud.dmi' department_types = list( /decl/department/example - ) + ) /decl/outfit/job/tourist name = "Job - Testing Site Tourist" diff --git a/maps/example/hud.dmi b/maps/example/hud.dmi index 89dd2f9a079e..c2c456e9d507 100644 Binary files a/maps/example/hud.dmi and b/maps/example/hud.dmi differ diff --git a/maps/exodus/exodus-1.dmm b/maps/exodus/exodus-1.dmm index df58cbab4de9..bd953735089c 100644 --- a/maps/exodus/exodus-1.dmm +++ b/maps/exodus/exodus-1.dmm @@ -3496,8 +3496,7 @@ department = "Atmospherics"; name = "Atmos RC"; pixel_y = 32; - dir = 1; - + dir = 1 }, /obj/structure/table/steel, /turf/floor/tiled/steel_grid, @@ -5467,6 +5466,10 @@ }, /turf/floor/lino, /area/exodus/maintenance/telecomms) +"rd" = ( +/obj/effect/shuttle_landmark/automatic, +/turf/space, +/area/space) "rj" = ( /obj/effect/floor_decal/industrial/outline/grey, /obj/machinery/camera/network/command{ @@ -16599,7 +16602,7 @@ aa aa aa aa -aa +rd aa aa aa @@ -44175,7 +44178,7 @@ aa aa aa aa -aa +rd aa aa aa @@ -49205,7 +49208,7 @@ aa aa aa aa -aa +rd aa aa aa diff --git a/maps/exodus/exodus-2.dmm b/maps/exodus/exodus-2.dmm index 2490837e9935..059f7cec3441 100644 --- a/maps/exodus/exodus-2.dmm +++ b/maps/exodus/exodus-2.dmm @@ -30766,7 +30766,7 @@ /obj/machinery/fabricator/imprinter{ id_tag = "science" }, -/obj/item/chems/glass/beaker/sulphuric, +/obj/item/chems/glass/beaker/sulfuric, /obj/structure/reagent_dispensers/acid{ density = 0; pixel_y = 32 @@ -32579,7 +32579,7 @@ /obj/machinery/fabricator/imprinter{ id_tag = "science" }, -/obj/item/chems/glass/beaker/sulphuric, +/obj/item/chems/glass/beaker/sulfuric, /turf/floor/tiled/dark, /area/exodus/research/lab) "bqQ" = ( @@ -63545,6 +63545,10 @@ /obj/item/radio/beacon, /turf/floor/plating, /area/ship/exodus_pod_research) +"eYg" = ( +/obj/effect/shuttle_landmark/automatic, +/turf/space, +/area/space) "eZK" = ( /obj/effect/floor_decal/corner/purple, /obj/machinery/light, @@ -75579,7 +75583,7 @@ cLU cLU cLU cLU -cLU +eYg cLU cLU cLU @@ -87506,7 +87510,7 @@ cLU cLU cLU cLU -cLU +eYg cLU cLU cLU @@ -107479,7 +107483,7 @@ cLU cLU cLU cLU -cLU +eYg cLU cLU cLU @@ -115429,7 +115433,7 @@ cLU cLU cLU cLU -cLU +eYg cLU cLU cLU diff --git a/maps/exodus/exodus-admin.dmm b/maps/exodus/exodus-admin.dmm index 9fcc6687e4de..f8b0550efc0d 100644 --- a/maps/exodus/exodus-admin.dmm +++ b/maps/exodus/exodus-admin.dmm @@ -2422,7 +2422,8 @@ /turf/unsimulated/floor/vault, /area/tdome) "lSj" = ( -/obj/effect/forcefield{ +/obj/effect{ + density = 1; desc = "You can't get in. Heh."; name = "Blocker" }, @@ -2434,7 +2435,8 @@ /turf/unsimulated/floor/dark, /area/tdome) "mgi" = ( -/obj/effect/forcefield{ +/obj/effect{ + density = 1; desc = "You can't get in. Heh."; name = "Blocker" }, @@ -2799,7 +2801,8 @@ /turf/floor/tiled, /area/shuttle/escape_shuttle) "xSD" = ( -/obj/effect/forcefield{ +/obj/effect{ + density = 1; desc = "You can't get in. Heh."; name = "Blocker" }, diff --git a/maps/exodus/exodus.dm b/maps/exodus/exodus.dm index 9372a9368a76..67ca1974ecce 100644 --- a/maps/exodus/exodus.dm +++ b/maps/exodus/exodus.dm @@ -1,38 +1,37 @@ #if !defined(USING_MAP_DATUM) - #include "../../mods/gamemodes/cult/_cult.dme" - #include "../../mods/gamemodes/heist/_heist.dme" - #include "../../mods/gamemodes/meteor/_meteor.dme" - #include "../../mods/gamemodes/ninja/_ninja.dme" - #include "../../mods/gamemodes/revolution/_revolution.dme" - #include "../../mods/gamemodes/traitor/_traitor.dme" - #include "../../mods/gamemodes/spyvspy/_spyvspy.dme" - #include "../../mods/gamemodes/mixed/_mixed.dme" - #include "../../mods/content/mundane.dm" + #include "../../mods/content/scaling_descriptors.dm" + #include "../../mods/content/bigpharma/_bigpharma.dme" #include "../../mods/content/corporate/_corporate.dme" #include "../../mods/content/government/_government.dme" #include "../../mods/content/matchmaking/_matchmaking.dme" #include "../../mods/content/modern_earth/_modern_earth.dme" #include "../../mods/content/mouse_highlights/_mouse_highlight.dme" - #include "../../mods/content/scaling_descriptors.dm" + #include "../../mods/content/pheromones/_pheromones.dme" + #include "../../mods/content/psionics/_psionics.dme" + #include "../../mods/content/standard_jobs/_standard_jobs.dme" + #include "../../mods/content/supermatter/_supermatter.dme" #include "../../mods/content/xenobiology/_xenobiology.dme" + #include "../../mods/content/tabloids/_tabloids.dme" - #include "../../mods/mobs/dionaea/_dionaea.dme" - #include "../../mods/mobs/borers/_borers.dme" - - // Must come after borers for compatibility. - #include "../../mods/content/psionics/_psionics.dme" + #include "../../mods/gamemodes/cult/_cult.dme" + #include "../../mods/gamemodes/heist/_heist.dme" + #include "../../mods/gamemodes/meteor/_meteor.dme" + #include "../../mods/gamemodes/ninja/_ninja.dme" + #include "../../mods/gamemodes/revolution/_revolution.dme" + #include "../../mods/gamemodes/spyvspy/_spyvspy.dme" + #include "../../mods/gamemodes/traitor/_traitor.dme" + #include "../../mods/gamemodes/mixed.dm" - // Must come after psionics for counsellor compatibility. - #include "../../mods/content/standard_jobs/_standard_jobs.dme" + #include "../../mods/mobs/borers/_borers.dme" + #include "../../mods/mobs/dionaea/_dionaea.dme" #include "../../mods/species/ascent/_ascent.dme" - #include "../../mods/content/pheromones/_pheromones.dme" + #include "../../mods/species/bayliens/_bayliens.dme" #include "../../mods/species/serpentid/_serpentid.dme" #include "../../mods/species/utility_frames/_utility_frames.dme" - #include "../../mods/species/bayliens/_bayliens.dme" #include "../random_ruins/exoplanet_ruins/playablecolony/playablecolony.dm" diff --git a/maps/exodus/exodus_antagonism.dm b/maps/exodus/exodus_antagonism.dm index 322bebbf1d34..e09d2ddc9002 100644 --- a/maps/exodus/exodus_antagonism.dm +++ b/maps/exodus/exodus_antagonism.dm @@ -1,16 +1,16 @@ /decl/special_role/traitor/Initialize() . = ..() LAZYINITLIST(protected_jobs) - protected_jobs |= list(/datum/job/officer, /datum/job/warden, /datum/job/detective, /datum/job/captain, /datum/job/lawyer, /datum/job/hos) + protected_jobs |= list(/datum/job/standard/officer, /datum/job/standard/warden, /datum/job/standard/detective, /datum/job/standard/captain, /datum/job/standard/lawyer, /datum/job/standard/hos) /decl/special_role/cultist/Initialize() . = ..() LAZYINITLIST(restricted_jobs) - restricted_jobs |= list(/datum/job/lawyer, /datum/job/captain, /datum/job/hos) + restricted_jobs |= list(/datum/job/standard/lawyer, /datum/job/standard/captain, /datum/job/standard/hos) LAZYINITLIST(protected_jobs) - protected_jobs |= list(/datum/job/officer, /datum/job/warden, /datum/job/detective) + protected_jobs |= list(/datum/job/standard/officer, /datum/job/standard/warden, /datum/job/standard/detective) LAZYINITLIST(blacklisted_jobs) - blacklisted_jobs |= list(/datum/job/chaplain, /datum/job/counselor) + blacklisted_jobs |= list(/datum/job/standard/chaplain, /datum/job/standard/counselor) /decl/special_role/loyalist command_department_id = /decl/department/command diff --git a/maps/exodus/exodus_goals.dm b/maps/exodus/exodus_goals.dm index 72c324b5c1d5..8275bc4173bb 100644 --- a/maps/exodus/exodus_goals.dm +++ b/maps/exodus/exodus_goals.dm @@ -29,12 +29,12 @@ var/global/list/exodus_paperwork_end_areas = list() /datum/goal/department/paperwork/exodus paperwork_types = list(/obj/item/paperwork/exodus) signatory_job_list = list( - /datum/job/captain, - /datum/job/hop, - /datum/job/cmo, - /datum/job/chief_engineer, - /datum/job/rd, - /datum/job/hos + /datum/job/standard/captain, + /datum/job/standard/hop, + /datum/job/standard/cmo, + /datum/job/standard/chief_engineer, + /datum/job/standard/rd, + /datum/job/standard/hos ) /datum/goal/department/paperwork/exodus/get_paper_spawn_turfs() diff --git a/maps/exodus/exodus_jobs.dm b/maps/exodus/exodus_jobs.dm index df6c7b54782c..6ca8b4d8ab41 100644 --- a/maps/exodus/exodus_jobs.dm +++ b/maps/exodus/exodus_jobs.dm @@ -7,82 +7,81 @@ spawn_decl = /decl/spawnpoint/gateway /datum/map/exodus - default_job_type = /datum/job/assistant + default_job_type = /datum/job/standard/assistant default_department_type = /decl/department/civilian - id_hud_icons = 'maps/exodus/hud.dmi' allowed_jobs = list( - /datum/job/captain, - /datum/job/hop, - /datum/job/chaplain, - /datum/job/bartender, - /datum/job/chef, - /datum/job/hydro, - /datum/job/qm, - /datum/job/cargo_tech, - /datum/job/mining, - /datum/job/janitor, - /datum/job/librarian, - /datum/job/lawyer, - /datum/job/chief_engineer, - /datum/job/engineer, - /datum/job/cmo, - /datum/job/doctor, - /datum/job/chemist, - /datum/job/counselor, - /datum/job/rd, - /datum/job/scientist, - /datum/job/roboticist, - /datum/job/hos, - /datum/job/detective, - /datum/job/warden, - /datum/job/officer, - /datum/job/robot, - /datum/job/computer + /datum/job/standard/captain, + /datum/job/standard/hop, + /datum/job/standard/chaplain, + /datum/job/standard/bartender, + /datum/job/standard/chef, + /datum/job/standard/hydro, + /datum/job/standard/qm, + /datum/job/standard/cargo_tech, + /datum/job/standard/mining, + /datum/job/standard/janitor, + /datum/job/standard/librarian, + /datum/job/standard/lawyer, + /datum/job/standard/chief_engineer, + /datum/job/standard/engineer, + /datum/job/standard/cmo, + /datum/job/standard/doctor, + /datum/job/standard/chemist, + /datum/job/standard/counselor, + /datum/job/standard/rd, + /datum/job/standard/scientist, + /datum/job/standard/roboticist, + /datum/job/standard/hos, + /datum/job/standard/detective, + /datum/job/standard/warden, + /datum/job/standard/officer, + /datum/job/standard/robot, + /datum/job/standard/computer ) species_to_job_whitelist = list( /decl/species/adherent = list( - /datum/job/computer, - /datum/job/robot, - /datum/job/assistant, - /datum/job/janitor, - /datum/job/chef, - /datum/job/bartender, - /datum/job/cargo_tech, - /datum/job/engineer, - /datum/job/roboticist, - /datum/job/chemist, - /datum/job/scientist, - /datum/job/mining + /datum/job/standard/computer, + /datum/job/standard/robot, + /datum/job/standard/assistant, + /datum/job/standard/janitor, + /datum/job/standard/chef, + /datum/job/standard/bartender, + /datum/job/standard/cargo_tech, + /datum/job/standard/engineer, + /datum/job/standard/roboticist, + /datum/job/standard/chemist, + /datum/job/standard/scientist, + /datum/job/standard/mining ), /decl/species/utility_frame = list( - /datum/job/computer, - /datum/job/robot, - /datum/job/assistant, - /datum/job/janitor, - /datum/job/chef, - /datum/job/bartender, - /datum/job/cargo_tech, - /datum/job/engineer, - /datum/job/roboticist, - /datum/job/chemist, - /datum/job/scientist, - /datum/job/mining + /datum/job/standard/computer, + /datum/job/standard/robot, + /datum/job/standard/assistant, + /datum/job/standard/janitor, + /datum/job/standard/chef, + /datum/job/standard/bartender, + /datum/job/standard/cargo_tech, + /datum/job/standard/engineer, + /datum/job/standard/roboticist, + /datum/job/standard/chemist, + /datum/job/standard/scientist, + /datum/job/standard/mining ), /decl/species/serpentid = list( - /datum/job/computer, - /datum/job/robot, - /datum/job/assistant, - /datum/job/janitor, - /datum/job/chef, - /datum/job/bartender, - /datum/job/cargo_tech, - /datum/job/roboticist, - /datum/job/chemist + /datum/job/standard/computer, + /datum/job/standard/robot, + /datum/job/standard/assistant, + /datum/job/standard/janitor, + /datum/job/standard/chef, + /datum/job/standard/bartender, + /datum/job/standard/cargo_tech, + /datum/job/standard/roboticist, + /datum/job/standard/chemist ) ) -#define HUMAN_ONLY_JOBS /datum/job/captain, /datum/job/hop, /datum/job/hos +#define HUMAN_ONLY_JOBS /datum/job/standard/captain, /datum/job/standard/hop, /datum/job/standard/hos species_to_job_blacklist = list( /decl/species/unathi = list( HUMAN_ONLY_JOBS diff --git a/maps/exodus/exodus_loadout.dm b/maps/exodus/exodus_loadout.dm index 107fa0ae8c99..d5f70fdf9571 100644 --- a/maps/exodus/exodus_loadout.dm +++ b/maps/exodus/exodus_loadout.dm @@ -2,7 +2,7 @@ name = "religious insignia" path = /obj/item/clothing/insignia cost = 1 - allowed_roles = list(/datum/job/chaplain) + allowed_roles = list(/datum/job/standard/chaplain) uid = "gear_accessory_insignia" /decl/loadout_option/accessory/insignia/Initialize() diff --git a/maps/exodus/hud.dmi b/maps/exodus/hud.dmi deleted file mode 100644 index 952d808b00e4..000000000000 Binary files a/maps/exodus/hud.dmi and /dev/null differ diff --git a/maps/karzerfeste/jobs/_job.dm b/maps/karzerfeste/jobs/_job.dm index 5c28a069c4d7..3d82f49ef494 100644 --- a/maps/karzerfeste/jobs/_job.dm +++ b/maps/karzerfeste/jobs/_job.dm @@ -1,5 +1,4 @@ /datum/map/karzerfeste - id_hud_icons = 'maps/karzerfeste/jobs/icons.dmi' default_job_type = /datum/job/karzerfeste/local/traveller allowed_jobs = list( /datum/job/karzerfeste/guild/master, @@ -49,3 +48,4 @@ skill_points = 20 spawn_positions = 1 total_positions = 1 + hud_icon_state = "hudblank" diff --git a/maps/karzerfeste/jobs/icons.dmi b/maps/karzerfeste/jobs/icons.dmi deleted file mode 100644 index 6b1401249299..000000000000 Binary files a/maps/karzerfeste/jobs/icons.dmi and /dev/null differ diff --git a/maps/karzerfeste/outfits/guild.dm b/maps/karzerfeste/outfits/guild.dm index 48dfea9b96d1..6d24c570526b 100644 --- a/maps/karzerfeste/outfits/guild.dm +++ b/maps/karzerfeste/outfits/guild.dm @@ -21,7 +21,7 @@ /decl/outfit/job/karzerfeste/adventurer name = "Karzerfeste - Adventurer" belt = /obj/item/bladed/longsword - suit_store = /obj/item/shield/buckler + suit_store = /obj/item/shield/crafted/buckler suit = /obj/item/clothing/suit/armor/forged/brigandine uniform = list( /obj/item/clothing/pants/trousers, diff --git a/maps/karzerfeste/outfits/shrine.dm b/maps/karzerfeste/outfits/shrine.dm index 5faf5ed9f1ff..999b608e9236 100644 --- a/maps/karzerfeste/outfits/shrine.dm +++ b/maps/karzerfeste/outfits/shrine.dm @@ -20,7 +20,7 @@ name = "Karzerfeste - Shrine Cleric" suit = /obj/item/clothing/suit/armor/forged/cuirass belt = /obj/item/bladed/longsword // TODO: mace and magic - suit_store = /obj/item/shield/buckler + suit_store = /obj/item/shield/crafted/buckler /decl/outfit/job/karzerfeste/shrine/gravekeeper name = "Karzerfeste - Shrine Gravekeeper" diff --git a/maps/ministation/hud.dmi b/maps/ministation/hud.dmi index d4fed05d840b..8a3e91cf3a74 100644 Binary files a/maps/ministation/hud.dmi and b/maps/ministation/hud.dmi differ diff --git a/maps/ministation/jobs/civilian.dm b/maps/ministation/jobs/civilian.dm index 3d1601530d6b..18024cc23791 100644 --- a/maps/ministation/jobs/civilian.dm +++ b/maps/ministation/jobs/civilian.dm @@ -1,15 +1,14 @@ -/datum/job/assistant/ministation +/datum/job/standard/assistant/ministation title = "Recruit" supervisors = "absolutely everyone" alt_titles = list("Technical Recruit","Medical Recruit","Research Recruit","Visitor") outfit_type = /decl/outfit/job/ministation_assistant event_categories = list(ASSIGNMENT_GARDENER) - hud_icon = "hudassistant" /decl/outfit/job/ministation_assistant name = "Job - Ministation Assistant" -/datum/job/bartender/ministation +/datum/job/standard/bartender/ministation title = "Bartender" alt_titles = list("Cook","Barista") supervisors = "the Lieutenant and the Captain" @@ -30,7 +29,7 @@ ) skill_points = 30 -/datum/job/cargo_tech/ministation +/datum/job/standard/cargo_tech/ministation title = "Cargo Technician" alt_titles = list("Shaft Miner","Drill Technician","Prospector") supervisors = "the Lieutenant and the Captain" @@ -73,7 +72,7 @@ ) skill_points = 30 -/datum/job/janitor/ministation +/datum/job/standard/janitor/ministation total_positions = 2 supervisors = "the Lieutenant and the Captain" economic_power = 3 @@ -84,7 +83,7 @@ ) skill_points = 28 -/datum/job/librarian/ministation +/datum/job/standard/librarian/ministation spawn_positions = 2 supervisors = "the Lieutenant, the Captain, and the smell of old paper" economic_power = 5 diff --git a/maps/ministation/jobs/command.dm b/maps/ministation/jobs/command.dm index a823a716095c..1a27ff0736d1 100644 --- a/maps/ministation/jobs/command.dm +++ b/maps/ministation/jobs/command.dm @@ -1,6 +1,7 @@ -/datum/job/captain/ministation +/datum/job/standard/captain/ministation supervisors = "your profit margin, your conscience, and the watchful eye of the Tradehouse Rep" outfit_type = /decl/outfit/job/ministation/captain + hud_icon = 'maps/ministation/hud.dmi' min_skill = list( SKILL_LITERACY = SKILL_ADEPT, SKILL_WEAPONS = SKILL_ADEPT, @@ -13,7 +14,7 @@ ) skill_points = 40 -/datum/job/captain/ministation/equip_job(var/mob/living/human/H, var/alt_title, var/datum/mil_branch/branch, var/datum/mil_rank/grade) +/datum/job/standard/captain/ministation/equip_job(var/mob/living/human/H, var/alt_title, var/datum/mil_branch/branch, var/datum/mil_rank/grade) . = ..() if(H) H.verbs |= /mob/proc/freetradeunion_rename_company @@ -33,10 +34,11 @@ command_announcement.Announce("Congratulations to all members of [capitalize(global.using_map.company_name)] on the new name. Their rebranding has changed the [global.using_map.company_short] market value by [0.01*rand(-10,10)]%.", "Trade Union Name Change") verbs -= /mob/proc/freetradeunion_rename_company -/datum/job/hop/ministation +/datum/job/standard/hop/ministation title = "Lieutenant" outfit_type = /decl/outfit/job/ministation/hop - hud_icon = "hudlieutenant" + hud_icon = 'maps/ministation/hud.dmi' + hud_icon_state = "hudlieutenant" min_skill = list( SKILL_LITERACY = SKILL_ADEPT, SKILL_WEAPONS = SKILL_BASIC, diff --git a/maps/ministation/jobs/engineering.dm b/maps/ministation/jobs/engineering.dm index d780f2353d28..a3cb57fbc0a9 100644 --- a/maps/ministation/jobs/engineering.dm +++ b/maps/ministation/jobs/engineering.dm @@ -1,4 +1,4 @@ -/datum/job/engineer/ministation +/datum/job/standard/engineer/ministation title = "Station Engineer" supervisors = "the Head Engineer" total_positions = 2 @@ -32,9 +32,8 @@ skill_points = 30 alt_titles = list("Atmospheric Technician", "Electrician", "Maintenance Technician") -/datum/job/chief_engineer/ministation +/datum/job/standard/chief_engineer/ministation title = "Head Engineer" - hud_icon = "hudchiefengineer" access = list( access_engine, access_engine_equip, diff --git a/maps/ministation/jobs/medical.dm b/maps/ministation/jobs/medical.dm index 0e91a2d945b4..1dd568c8176e 100644 --- a/maps/ministation/jobs/medical.dm +++ b/maps/ministation/jobs/medical.dm @@ -1,4 +1,4 @@ -/datum/job/doctor/ministation +/datum/job/standard/doctor/ministation title = "Medical Doctor" supervisors = "the Head Doctor" total_positions = 2 @@ -35,13 +35,12 @@ ) outfit_type = /decl/outfit/job/ministation/doctor -/datum/job/cmo/ministation +/datum/job/standard/cmo/ministation title = "Head Doctor" supervisors = "the Captain and your own ethics" outfit_type = /decl/outfit/job/ministation/doctor/head alt_titles = list("Chief Medical Officer", "Head Surgeon") skill_points = 38 - hud_icon = "hudheaddoctor" access = list( access_medical, access_medical_equip, diff --git a/maps/ministation/jobs/science.dm b/maps/ministation/jobs/science.dm index f2d80cbe65f1..7b8e61e4591d 100644 --- a/maps/ministation/jobs/science.dm +++ b/maps/ministation/jobs/science.dm @@ -1,14 +1,13 @@ -/datum/job/scientist/ministation +/datum/job/standard/scientist/ministation title = "Researcher" alt_titles = list("Scientist","Xenobiologist","Roboticist","Xenobotanist") supervisors = "the Head Researcher" spawn_positions = 1 total_positions = 2 outfit_type = /decl/outfit/job/ministation/scientist - hud_icon = "hudscientist" skill_points = 34 -/datum/job/rd/ministation +/datum/job/standard/rd/ministation title = "Research Director" alt_titles = list("Head Researcher", "Chief Researcher") outfit_type = /decl/outfit/job/ministation/scientist/head @@ -27,7 +26,6 @@ SKILL_SCIENCE = SKILL_MAX ) skill_points = 40 - hud_icon = "hudheadscientist" access = list( access_rd, access_bridge, diff --git a/maps/ministation/jobs/security.dm b/maps/ministation/jobs/security.dm index 55ea8e841e2f..242c665e7f31 100644 --- a/maps/ministation/jobs/security.dm +++ b/maps/ministation/jobs/security.dm @@ -1,4 +1,4 @@ -/datum/job/officer/ministation +/datum/job/standard/officer/ministation title = "Security Officer" alt_titles = list("Warden") spawn_positions = 1 @@ -22,7 +22,7 @@ ) skill_points = 30 -/datum/job/detective/ministation +/datum/job/standard/detective/ministation alt_titles = list("Inspector") supervisors = "Justice... and the Trademaster" spawn_positions = 1 @@ -55,9 +55,8 @@ ) skill_points = 34 -/datum/job/hos/ministation +/datum/job/standard/hos/ministation outfit_type = /decl/outfit/job/ministation/security/head - hud_icon = "hudhos" access = list( access_security, access_sec_doors, diff --git a/maps/ministation/jobs/tradehouse.dm b/maps/ministation/jobs/tradehouse.dm index 1e167615cf89..daa715dddd5b 100644 --- a/maps/ministation/jobs/tradehouse.dm +++ b/maps/ministation/jobs/tradehouse.dm @@ -1,7 +1,8 @@ /datum/job/tradehouse_rep title = "Tradehouse Representative" alt_titles = list("Narc") - hud_icon = "hudnarc" + hud_icon_state = "hudnarc" + hud_icon = 'maps/ministation/hud.dmi' spawn_positions = 1 total_positions = 2 req_admin_notify = 1 diff --git a/maps/ministation/ministation-0.dmm b/maps/ministation/ministation-0.dmm index 88dfa842c039..35b21cdc415d 100644 --- a/maps/ministation/ministation-0.dmm +++ b/maps/ministation/ministation-0.dmm @@ -5556,6 +5556,10 @@ }, /turf/floor/tiled/monotile, /area/ministation/atmospherics) +"yY" = ( +/obj/effect/shuttle_landmark/automatic, +/turf/space, +/area/space) "yZ" = ( /obj/structure/cable{ icon_state = "1-2" @@ -33009,7 +33013,7 @@ aa aa aa aa -aa +yY aa aa aa @@ -49102,7 +49106,7 @@ aa aa aa aa -aa +yY aa aa aa @@ -57125,7 +57129,7 @@ aa aa aa aa -aa +yY aa aa aa diff --git a/maps/ministation/ministation-1.dmm b/maps/ministation/ministation-1.dmm index 5deccebb9314..f0257f29891a 100644 --- a/maps/ministation/ministation-1.dmm +++ b/maps/ministation/ministation-1.dmm @@ -2713,6 +2713,10 @@ }, /turf/floor/tiled, /area/ministation/hall/w2) +"nt" = ( +/obj/effect/shuttle_landmark/automatic, +/turf/space, +/area/space) "nu" = ( /obj/effect/floor_decal/carpet{ dir = 8 @@ -6710,6 +6714,8 @@ }, /obj/structure/table/laminate, /obj/machinery/reagent_temperature, +/obj/item/chems/cooking_vessel/pot, +/obj/item/chems/cooking_vessel/skillet, /turf/floor/lino, /area/ministation/cafe) "Ct" = ( @@ -54008,7 +54014,7 @@ aa aa aa aa -aa +nt aa aa aa @@ -54341,7 +54347,7 @@ aa aa aa aa -aa +nt aa aa aa diff --git a/maps/ministation/ministation-2.dmm b/maps/ministation/ministation-2.dmm index 7fd20f4bff76..b087edf407c3 100644 --- a/maps/ministation/ministation-2.dmm +++ b/maps/ministation/ministation-2.dmm @@ -782,7 +782,7 @@ }, /obj/item/med_pouch/trauma, /obj/item/stack/tape_roll/duct_tape, -/obj/item/shield/buckler, +/obj/item/shield/crafted/buckler, /obj/item/gps/explorer, /obj/item/belt/holster/machete, /obj/item/tool/machete/deluxe, @@ -2164,7 +2164,7 @@ "js" = ( /obj/structure/table, /obj/item/chems/glass/beaker/large, -/obj/item/chems/glass/beaker/sulphuric, +/obj/item/chems/glass/beaker/sulfuric, /obj/item/chems/dropper, /obj/effect/floor_decal/corner/purple{ dir = 8 @@ -2275,7 +2275,7 @@ }, /obj/item/med_pouch/trauma, /obj/item/stack/tape_roll/duct_tape, -/obj/item/shield/buckler, +/obj/item/shield/crafted/buckler, /obj/item/gps/explorer, /obj/item/flashlight/lantern, /obj/item/bladed/polearm/spear/improvised/steel, @@ -3537,6 +3537,10 @@ }, /turf/floor/reinforced, /area/ministation/science) +"sq" = ( +/obj/effect/shuttle_landmark/automatic, +/turf/space, +/area/space) "sr" = ( /turf/floor/tiled/dark/monotile/telecomms, /area/ministation/telecomms) @@ -4431,7 +4435,7 @@ /obj/machinery/light, /obj/item/med_pouch/trauma, /obj/item/stack/tape_roll/duct_tape, -/obj/item/shield/buckler, +/obj/item/shield/crafted/buckler, /obj/item/gps/explorer, /obj/item/flashlight/lantern, /obj/item/bladed/polearm/spear/improvised/steel, @@ -29553,7 +29557,7 @@ vA vA vA vA -vA +sq vA vA vA @@ -45789,7 +45793,7 @@ vA vA vA vA -vA +sq vA vA vA @@ -52137,7 +52141,7 @@ vA vA vA vA -vA +sq vA vA vA diff --git a/maps/ministation/ministation-3.dmm b/maps/ministation/ministation-3.dmm index cbdd8abb5380..e5b68a7fe209 100644 --- a/maps/ministation/ministation-3.dmm +++ b/maps/ministation/ministation-3.dmm @@ -88,6 +88,10 @@ }, /turf/floor/plating, /area/ministation/maint/l4central) +"kH" = ( +/obj/effect/shuttle_landmark/automatic, +/turf/space, +/area/space) "kV" = ( /obj/machinery/atmospherics/pipe/simple/hidden/universal{ dir = 4 @@ -40459,7 +40463,7 @@ aa aa aa aa -aa +kH aa aa aa diff --git a/maps/ministation/ministation.dm b/maps/ministation/ministation.dm index 2ecca91fa60e..fca80d6d6478 100644 --- a/maps/ministation/ministation.dm +++ b/maps/ministation/ministation.dm @@ -15,31 +15,39 @@ Twice... #include "../../code/unit_tests/offset_tests.dm" #endif + #include "../random_ruins/exoplanet_ruins/playablecolony/playablecolony.dm" + + #include "../../mods/content/mundane.dm" + #include "../../mods/content/scaling_descriptors.dm" + + #include "../../mods/content/bigpharma/_bigpharma.dme" + #include "../../mods/content/corporate/_corporate.dme" + #include "../../mods/content/government/_government.dme" + #include "../../mods/content/matchmaking/_matchmaking.dme" + #include "../../mods/content/modern_earth/_modern_earth.dme" + #include "../../mods/content/mouse_highlights/_mouse_highlight.dme" + #include "../../mods/content/pheromones/_pheromones.dme" + #include "../../mods/content/psionics/_psionics.dme" + #include "../../mods/content/standard_jobs/_standard_jobs.dme" + #include "../../mods/content/supermatter/_supermatter.dme" + #include "../../mods/content/xenobiology/_xenobiology.dme" + #include "../../mods/gamemodes/cult/_cult.dme" #include "../../mods/gamemodes/heist/_heist.dme" #include "../../mods/gamemodes/ninja/_ninja.dme" #include "../../mods/gamemodes/revolution/_revolution.dme" #include "../../mods/gamemodes/traitor/_traitor.dme" #include "../../mods/gamemodes/spyvspy/_spyvspy.dme" - #include "../../mods/gamemodes/mixed/_mixed.dme" + #include "../../mods/gamemodes/mixed.dm" - #include "../random_ruins/exoplanet_ruins/playablecolony/playablecolony.dm" + #include "../../mods/mobs/dionaea/_dionaea.dme" + #include "../../mods/mobs/borers/_borers.dme" - #include "../../mods/content/standard_jobs/_standard_jobs.dme" - #include "../../mods/content/xenobiology/_xenobiology.dme" - #include "../../mods/content/corporate/_corporate.dme" - #include "../../mods/content/matchmaking/_matchmaking.dme" + #include "../../mods/content/tabloids/_tabloids.dme" #include "../../mods/species/ascent/_ascent.dme" + #include "../../mods/species/bayliens/_bayliens.dme" #include "../../mods/species/neoavians/_neoavians.dme" - #include "../../mods/content/pheromones/_pheromones.dme" #include "../../mods/species/serpentid/_serpentid.dme" - #include "../../mods/species/bayliens/_bayliens.dme" - #include "../../mods/content/mundane.dm" - #include "../../mods/content/bigpharma/_bigpharma.dme" - #include "../../mods/content/government/_government.dme" - #include "../../mods/content/modern_earth/_modern_earth.dme" - #include "../../mods/content/mouse_highlights/_mouse_highlight.dme" - #include "../../mods/content/scaling_descriptors.dm" #include "ministation_antagonists.dm" #include "ministation_areas.dm" @@ -70,12 +78,6 @@ Twice... #include "../away/yacht/yacht.dm" #include "../away/liberia/liberia.dm" - #include "../../mods/mobs/dionaea/_dionaea.dme" - #include "../../mods/mobs/borers/_borers.dme" - - // Must come after borers for compatibility. - #include "../../mods/content/psionics/_psionics.dme" - #include "ministation_overmap.dm" #include "jobs/command.dm" diff --git a/maps/ministation/ministation_jobs.dm b/maps/ministation/ministation_jobs.dm index 92e28630c1f1..17bb28b7b9e8 100644 --- a/maps/ministation/ministation_jobs.dm +++ b/maps/ministation/ministation_jobs.dm @@ -1,25 +1,24 @@ /datum/map/ministation - default_job_type = /datum/job/assistant/ministation + default_job_type = /datum/job/standard/assistant/ministation default_department_type = /decl/department/civilian - id_hud_icons = 'maps/ministation/hud.dmi' allowed_jobs = list( - /datum/job/assistant/ministation, - /datum/job/bartender/ministation, - /datum/job/captain/ministation, - /datum/job/cargo_tech/ministation, - /datum/job/robot, - /datum/job/computer, - /datum/job/detective/ministation, - /datum/job/doctor/ministation, - /datum/job/cmo/ministation, - /datum/job/engineer/ministation, - /datum/job/chief_engineer/ministation, - /datum/job/hop/ministation, - /datum/job/janitor/ministation, - /datum/job/scientist/ministation, - /datum/job/rd/ministation, - /datum/job/officer/ministation, - /datum/job/hos/ministation, - /datum/job/librarian/ministation, + /datum/job/standard/assistant/ministation, + /datum/job/standard/bartender/ministation, + /datum/job/standard/captain/ministation, + /datum/job/standard/cargo_tech/ministation, + /datum/job/standard/robot, + /datum/job/standard/computer, + /datum/job/standard/detective/ministation, + /datum/job/standard/doctor/ministation, + /datum/job/standard/cmo/ministation, + /datum/job/standard/engineer/ministation, + /datum/job/standard/chief_engineer/ministation, + /datum/job/standard/hop/ministation, + /datum/job/standard/janitor/ministation, + /datum/job/standard/scientist/ministation, + /datum/job/standard/rd/ministation, + /datum/job/standard/officer/ministation, + /datum/job/standard/hos/ministation, + /datum/job/standard/librarian/ministation, /datum/job/tradehouse_rep ) \ No newline at end of file diff --git a/maps/modpack_testing/modpack_testing.dm b/maps/modpack_testing/modpack_testing.dm index 0a9ca098454a..29613596f64c 100644 --- a/maps/modpack_testing/modpack_testing.dm +++ b/maps/modpack_testing/modpack_testing.dm @@ -3,47 +3,47 @@ #include "modpack_testing_lobby.dm" #include "blank.dmm" - #include "../../mods/gamemodes/cult/_cult.dme" - #include "../../mods/gamemodes/heist/_heist.dme" - #include "../../mods/gamemodes/meteor/_meteor.dme" - #include "../../mods/gamemodes/ninja/_ninja.dme" - #include "../../mods/gamemodes/revolution/_revolution.dme" - #include "../../mods/gamemodes/traitor/_traitor.dme" - #include "../../mods/gamemodes/spyvspy/_spyvspy.dme" - #include "../../mods/gamemodes/mixed/_mixed.dme" - #include "../../mods/content/mundane.dm" #include "../../mods/content/scaling_descriptors.dm" + #include "../../mods/content/standard_jobs/_standard_jobs.dme" + #include "../../mods/content/tabloids/_tabloids.dme" - #include "../../mods/content/dungeon_loot/_dungeon_loot.dme" #include "../../mods/content/bigpharma/_bigpharma.dme" #include "../../mods/content/byond_membership/_byond_membership.dm" #include "../../mods/content/corporate/_corporate.dme" + #include "../../mods/content/dungeon_loot/_dungeon_loot.dme" + #include "../../mods/content/fantasy/_fantasy.dme" #include "../../mods/content/generic_shuttles/_generic_shuttles.dme" #include "../../mods/content/government/_government.dme" + #include "../../mods/content/inertia/_inertia.dme" #include "../../mods/content/matchmaking/_matchmaking.dme" #include "../../mods/content/modern_earth/_modern_earth.dme" #include "../../mods/content/mouse_highlights/_mouse_highlight.dme" + #include "../../mods/content/pheromones/_pheromones.dme" + #include "../../mods/content/psionics/_psionics.dme" #include "../../mods/content/shackles/_shackles.dme" + #include "../../mods/content/supermatter/_supermatter.dme" #include "../../mods/content/xenobiology/_xenobiology.dme" - #include "../../mods/content/pheromones/_pheromones.dme" - #include "../../mods/species/drakes/_drakes.dme" // include before _fantasy.dme so overrides work - #include "../../mods/content/anima/_anima.dme" // include before _fantasy.dme so skill overrides work - #include "../../mods/content/fantasy/_fantasy.dme" #include "../../mods/pyrelight/_pyrelight.dme" // include after _fantasy.dme so overrides work - #include "../../mods/content/inertia/_inertia.dme" - #include "../../mods/mobs/dionaea/_dionaea.dme" - #include "../../mods/mobs/borers/_borers.dme" + #include "../../mods/gamemodes/cult/_cult.dme" + #include "../../mods/gamemodes/heist/_heist.dme" + #include "../../mods/gamemodes/meteor/_meteor.dme" + #include "../../mods/gamemodes/ninja/_ninja.dme" + #include "../../mods/gamemodes/revolution/_revolution.dme" + #include "../../mods/gamemodes/traitor/_traitor.dme" + #include "../../mods/gamemodes/spyvspy/_spyvspy.dme" + #include "../../mods/gamemodes/mixed.dm" - // Must come after borers for compatibility. - #include "../../mods/content/psionics/_psionics.dme" + #include "../../mods/mobs/borers/_borers.dme" + #include "../../mods/mobs/dionaea/_dionaea.dme" - #include "../../mods/species/serpentid/_serpentid.dme" #include "../../mods/species/ascent/_ascent.dme" + #include "../../mods/species/bayliens/_bayliens.dme" + #include "../../mods/species/drakes/_drakes.dme" #include "../../mods/species/neoavians/_neoavians.dme" + #include "../../mods/species/serpentid/_serpentid.dme" #include "../../mods/species/utility_frames/_utility_frames.dme" - #include "../../mods/species/bayliens/_bayliens.dme" #include "../../mods/species/vox/_vox.dme" #define USING_MAP_DATUM /datum/map/modpack_testing diff --git a/maps/shaded_hills/areas/_areas.dm b/maps/shaded_hills/areas/_areas.dm index b33bf376d846..e31eff6ce28e 100644 --- a/maps/shaded_hills/areas/_areas.dm +++ b/maps/shaded_hills/areas/_areas.dm @@ -20,13 +20,6 @@ ) sound_env = GENERIC ambience = list() - var/list/additional_fishing_results - -/area/shaded_hills/Initialize() - if(additional_fishing_results) - for(var/fish in additional_fishing_results) - fishing_results[fish] = additional_fishing_results[fish] - . = ..() /area/shaded_hills/outside name = "\improper Grasslands" diff --git a/maps/shaded_hills/areas/grassland.dm b/maps/shaded_hills/areas/grassland.dm index 9b7de6659e1b..803f9a5e9200 100644 --- a/maps/shaded_hills/areas/grassland.dm +++ b/maps/shaded_hills/areas/grassland.dm @@ -34,12 +34,15 @@ color = COLOR_BLUE description = "The soft susurration of running water mingles with the hum of insects and croak of frogs." area_blurb_category = /area/shaded_hills/outside/river - additional_fishing_results = list( + +/area/shaded_hills/outside/river/get_additional_fishing_results() + var/static/list/additional_fishing_results = list( /mob/living/simple_animal/aquatic/fish/large = 5, /mob/living/simple_animal/aquatic/fish/large/salmon = 5, /mob/living/simple_animal/aquatic/fish/large/trout = 5, /mob/living/simple_animal/aquatic/fish/large/pike = 3 ) + return additional_fishing_results /area/shaded_hills/caves name = "\improper Deep Tunnels" diff --git a/maps/shaded_hills/areas/woods.dm b/maps/shaded_hills/areas/woods.dm index 0fd8dca0685f..73c262300a6f 100644 --- a/maps/shaded_hills/areas/woods.dm +++ b/maps/shaded_hills/areas/woods.dm @@ -4,13 +4,16 @@ /area/shaded_hills/outside/river/lake name = "Woodland Lake" - additional_fishing_results = list( - /mob/living/simple_animal/aquatic/fish/large/bass = 5, - /mob/living/simple_animal/aquatic/fish/large/trout = 5, - /mob/living/simple_animal/aquatic/fish/large/javelin = 5, - /mob/living/simple_animal/hostile/aquatic/carp = 3, - /mob/living/simple_animal/aquatic/fish/large/koi = 1 + +/area/shaded_hills/outside/river/lake/get_additional_fishing_results() + var/static/list/additional_fishing_results = list( + /mob/living/simple_animal/aquatic/fish/large/bass = 5, + /mob/living/simple_animal/aquatic/fish/large/trout = 5, + /mob/living/simple_animal/aquatic/fish/large/javelin = 5, + /mob/living/simple_animal/hostile/aquatic/carp = 3, + /mob/living/simple_animal/aquatic/fish/large/koi = 1 ) + return additional_fishing_results /area/shaded_hills/outside/woods name = "Woodlands" diff --git a/maps/shaded_hills/icons/hud.dmi b/maps/shaded_hills/icons/hud.dmi deleted file mode 100644 index c8c2fcf8bd1b..000000000000 Binary files a/maps/shaded_hills/icons/hud.dmi and /dev/null differ diff --git a/maps/shaded_hills/jobs/_jobs.dm b/maps/shaded_hills/jobs/_jobs.dm index 638c6ff7bf5c..7eb2719f6615 100644 --- a/maps/shaded_hills/jobs/_jobs.dm +++ b/maps/shaded_hills/jobs/_jobs.dm @@ -1,6 +1,5 @@ /datum/map/shaded_hills - id_hud_icons = 'maps/shaded_hills/icons/hud.dmi' - allowed_jobs = list( + allowed_jobs = list( /datum/job/shaded_hills/visitor/traveller, /datum/job/shaded_hills/visitor/traveller/learned, /datum/job/shaded_hills/visitor/beggar_knight, @@ -48,6 +47,7 @@ /datum/job/shaded_hills abstract_type = /datum/job/shaded_hills + hud_icon_state = "hudblank" department_types = list( /decl/department/shaded_hills/locals ) diff --git a/maps/shaded_hills/levels/_levels.dm b/maps/shaded_hills/levels/_levels.dm index fc96452d2d1f..dc2d59ddcc52 100644 --- a/maps/shaded_hills/levels/_levels.dm +++ b/maps/shaded_hills/levels/_levels.dm @@ -16,10 +16,6 @@ daycycle_type = /datum/daycycle/shaded_hills daycycle_id = "daycycle_shaded_hills" template_edge_padding = 0 // we use a strictly delineated subarea, no need for this guard - var/submap_budget = 0 - var/submap_category = null - var/submap_area - var/list/mobs_to_spawn = list() /datum/daycycle/shaded_hills cycle_duration = 2 HOURS // 1 hour of daylight, 1 hour of night @@ -29,32 +25,6 @@ time_in_cycle = rand(cycle_duration) ..() -/datum/level_data/main_level/shaded_hills/get_subtemplate_areas(template_category, blacklist, whitelist) - return submap_area ? (islist(submap_area) ? submap_area : list(submap_area)) : null - -/datum/level_data/main_level/shaded_hills/get_subtemplate_budget() - return submap_budget - -/datum/level_data/main_level/shaded_hills/get_subtemplate_category() - return submap_category - -/datum/level_data/main_level/shaded_hills/after_generate_level() - . = ..() - if(length(mobs_to_spawn)) - for(var/list/mob_category in mobs_to_spawn) - var/list/mob_types = mob_category[1] - var/mob_turf = mob_category[2] - var/mob_count = mob_category[3] - var/sanity = 1000 - while(mob_count && sanity) - sanity-- - var/turf/place_mob_at = locate(rand(level_inner_min_x, level_inner_max_x), rand(level_inner_min_y, level_inner_max_y), level_z) - if(istype(place_mob_at, mob_turf) && !(locate(/mob/living) in place_mob_at)) - var/mob_type = pickweight(mob_types) - new mob_type(place_mob_at) - mob_count-- - CHECK_TICK - /datum/level_data/main_level/shaded_hills/grassland name = "Shaded Hills - Grassland" level_id = "shaded_hills_grassland" @@ -68,11 +38,12 @@ "shaded_hills_swamp" = SOUTH, "shaded_hills_downlands" = EAST ) - submap_budget = 5 - submap_category = MAP_TEMPLATE_CATEGORY_SH_GRASSLAND - submap_area = /area/shaded_hills/outside/poi + subtemplate_budget = 5 + subtemplate_category = MAP_TEMPLATE_CATEGORY_FANTASY_GRASSLAND + subtemplate_area = /area/shaded_hills/outside/poi - mobs_to_spawn = list( +/datum/level_data/main_level/shaded_hills/grassland/get_mobs_to_populate_level() + var/static/list/mobs_to_spawn = list( list( list( /mob/living/simple_animal/passive/mouse = 9, @@ -85,7 +56,7 @@ 10 ) ) - + return mobs_to_spawn /datum/level_data/main_level/shaded_hills/swamp name = "Shaded Hills - Swamp" @@ -97,11 +68,12 @@ /datum/random_map/noise/shaded_hills/swamp, /datum/random_map/noise/forage/shaded_hills/swamp ) - submap_budget = 5 - submap_category = MAP_TEMPLATE_CATEGORY_SH_SWAMP - submap_area = /area/shaded_hills/outside/swamp/poi + subtemplate_budget = 5 + subtemplate_category = MAP_TEMPLATE_CATEGORY_FANTASY_SWAMP + subtemplate_area = /area/shaded_hills/outside/swamp/poi - mobs_to_spawn = list( +/datum/level_data/main_level/shaded_hills/swamp/get_mobs_to_populate_level() + var/static/list/mobs_to_spawn = list( list( list( /mob/living/simple_animal/passive/mouse = 6, @@ -127,6 +99,7 @@ 10 ) ) + return mobs_to_spawn /datum/level_data/main_level/shaded_hills/woods name = "Shaded Hills - Woods" @@ -138,11 +111,12 @@ /datum/random_map/noise/shaded_hills/woods, /datum/random_map/noise/forage/shaded_hills/woods ) - submap_budget = 5 - submap_category = MAP_TEMPLATE_CATEGORY_SH_WOODS - submap_area = /area/shaded_hills/outside/woods/poi + subtemplate_budget = 5 + subtemplate_category = MAP_TEMPLATE_CATEGORY_FANTASY_WOODS + subtemplate_area = /area/shaded_hills/outside/woods/poi - mobs_to_spawn = list( +/datum/level_data/main_level/shaded_hills/woods/get_mobs_to_populate_level() + var/static/list/mobs_to_spawn = list( list( list( /mob/living/simple_animal/passive/mouse = 6, @@ -162,6 +136,7 @@ 5 ) ) + return mobs_to_spawn /datum/level_data/main_level/shaded_hills/downlands name = "Shaded Hills - Downlands" @@ -173,9 +148,9 @@ connected_levels = list( "shaded_hills_grassland" = WEST ) - submap_budget = 5 - submap_category = MAP_TEMPLATE_CATEGORY_SH_DOWNLANDS - submap_area = /area/shaded_hills/outside/downlands/poi + subtemplate_budget = 5 + subtemplate_category = MAP_TEMPLATE_CATEGORY_FANTASY_DOWNLANDS + subtemplate_area = /area/shaded_hills/outside/downlands/poi /datum/level_data/main_level/shaded_hills/caverns name = "Shaded Hills - Caverns" @@ -183,9 +158,9 @@ connected_levels = list( "shaded_hills_dungeon" = EAST ) - submap_budget = 5 - submap_category = MAP_TEMPLATE_CATEGORY_SH_CAVERNS - submap_area = /area/shaded_hills/caves/deep/poi + subtemplate_budget = 5 + subtemplate_category = MAP_TEMPLATE_CATEGORY_FANTASY_CAVERNS + subtemplate_area = /area/shaded_hills/caves/deep/poi level_generators = list( /datum/random_map/automata/cave_system/shaded_hills, /datum/random_map/noise/ore/rich @@ -198,9 +173,9 @@ connected_levels = list( "shaded_hills_caverns" = WEST ) - submap_budget = 5 - submap_category = MAP_TEMPLATE_CATEGORY_SH_DUNGEON - submap_area = /area/shaded_hills/caves/dungeon/poi + subtemplate_budget = 5 + subtemplate_category = MAP_TEMPLATE_CATEGORY_FANTASY_DUNGEON + subtemplate_area = /area/shaded_hills/caves/dungeon/poi base_turf = /turf/floor/rock/basalt /obj/abstract/level_data_spawner/shaded_hills_grassland diff --git a/maps/shaded_hills/shaded_hills-grassland.dmm b/maps/shaded_hills/shaded_hills-grassland.dmm index b885f19cf3f4..3adbafa7443c 100644 --- a/maps/shaded_hills/shaded_hills-grassland.dmm +++ b/maps/shaded_hills/shaded_hills-grassland.dmm @@ -67,7 +67,7 @@ /area/shaded_hills/outside) "kr" = ( /obj/item/tool/pickaxe/iron, -/obj/item/tool/axe, +/obj/item/tool/axe/iron, /obj/abstract/exterior_marker/inside, /obj/structure/closet/crate/chest/ebony, /turf/floor/woven, @@ -125,6 +125,10 @@ /obj/item/bag/sack, /turf/floor/woven, /area/shaded_hills/caves/unexplored/south) +"qj" = ( +/obj/abstract/force_fluid_flow/north, +/turf/floor/mud/water/deep, +/area/shaded_hills/outside/river) "qy" = ( /turf/wall/natural/basalt/shaded_hills, /area/shaded_hills/caves/river) @@ -136,6 +140,10 @@ "sS" = ( /turf/floor/mud/water, /area/shaded_hills/caves/unexplored/south) +"sT" = ( +/obj/abstract/force_fluid_flow/north, +/turf/floor/mud/water/deep, +/area/shaded_hills/outside/river) "te" = ( /turf/unsimulated/mask, /area/shaded_hills/caves/unexplored/south) @@ -19512,7 +19520,7 @@ Gh Gh My My -My +sT lC lC lC @@ -19529,8 +19537,8 @@ lC lC lC lC -My -My +qj +sT My Gh Gh @@ -19572,12 +19580,12 @@ My My My My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT My My My @@ -19662,9 +19670,9 @@ Gh Gh Gh My -My -My -My +sT +sT +sT lC lC lC @@ -19681,9 +19689,9 @@ lC lC lC lC -My -My -My +sT +sT +sT My My Gh @@ -19717,23 +19725,23 @@ Gh Gh My My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT My My Gh @@ -19753,14 +19761,14 @@ JN My My My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT My My My @@ -19771,15 +19779,15 @@ My Gh My My -My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT +sT My Gh Gh @@ -19814,9 +19822,9 @@ My My My My -My -My -My +sT +sT +sT lC lC lC @@ -19833,11 +19841,11 @@ lC lC lC lC -My -My -My -My -My +sT +sT +sT +sT +sT My My Gh @@ -19867,27 +19875,27 @@ Gh Gh My My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT My My My @@ -19901,38 +19909,38 @@ Gh Xd vX Xd +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT My My My @@ -19960,15 +19968,15 @@ My My My My -My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT +sT lC lC lC @@ -19986,12 +19994,12 @@ lC lC lC My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT My My My @@ -20017,6 +20025,13 @@ Gh Gh Gh My +sT +sT +sT +sT +sT +sT +sT My My My @@ -20028,20 +20043,13 @@ My My My My -My -My -My -My -My -My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT My My My @@ -20053,42 +20061,42 @@ My Xd vX Xd -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT My Gh Gh @@ -20107,19 +20115,19 @@ My My My My -My -My -My -My -My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT My lC lC @@ -20140,15 +20148,15 @@ lC Gh My My -My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT +sT My My My @@ -20170,10 +20178,10 @@ Gh Gh My My -My -My -My -My +sT +sT +sT +sT My My Gh @@ -20190,57 +20198,57 @@ Gh My My My -My -My -My -My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT EE EE Xd -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +My +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT My Gh Gh @@ -20252,21 +20260,21 @@ zp zp Gh My -My -My -My -My -My -My -My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT +sT My My My @@ -20299,18 +20307,18 @@ My My My My +sT +sT +sT +sT +sT +sT +sT My My My -My -My -My -My -My -My -My -My -My +sT +sT My Gh Gh @@ -20345,38 +20353,38 @@ Gh My My My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT JN EE EE EE JN +sT +sT My My My +sT +sT +sT My My -My -My -My -My -My -My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT +sT My Gh My @@ -20404,14 +20412,14 @@ zp Gh Gh My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT My My My @@ -20456,14 +20464,14 @@ My My My My -My -My -My -My -My -My -My -My +sT +sT +sT +sT +sT +sT +sT +sT My Gh Gh @@ -20501,15 +20509,15 @@ My My My My -My -My -My -My -My +sT +sT +sT +sT +sT EE vX EE -My +sT My My Gh @@ -20524,9 +20532,9 @@ My My My My -My -My -My +sT +sT +sT My My Gh diff --git a/maps/shaded_hills/shaded_hills-woods.dmm b/maps/shaded_hills/shaded_hills-woods.dmm index 66168daa63f0..06a9695d6345 100644 --- a/maps/shaded_hills/shaded_hills-woods.dmm +++ b/maps/shaded_hills/shaded_hills-woods.dmm @@ -71,9 +71,6 @@ "te" = ( /turf/floor/rock/basalt, /area/shaded_hills/outside/woods) -"ul" = ( -/turf/floor/mud/water, -/area/shaded_hills/outside/river/woods) "uA" = ( /turf/unsimulated/dark_filler, /area/shaded_hills/outside/river/woods) @@ -112,6 +109,9 @@ "DX" = ( /turf/floor/mud/water/deep, /area/shaded_hills/caves/river/woods) +"En" = ( +/turf/floor/mud/water, +/area/shaded_hills/outside/river/woods) "ES" = ( /turf/floor/grass, /area/shaded_hills/outside/river/woods) @@ -178,8 +178,9 @@ /turf/floor/wood/rough/walnut, /area/shaded_hills/forester_hut) "PO" = ( +/obj/abstract/force_fluid_flow/north, /turf/floor/mud/water/deep, -/area/shaded_hills/outside/river/woods) +/area/shaded_hills/outside/river/lake) "SI" = ( /turf/wall/log/walnut, /area/shaded_hills/forester_hut) @@ -199,6 +200,10 @@ /obj/abstract/landmark/start/shaded_hills/traveller, /turf/floor/barren, /area/shaded_hills/caves/woods) +"Wo" = ( +/obj/abstract/force_fluid_flow/north, +/turf/floor/mud/water/deep, +/area/shaded_hills/outside/river/woods) "Xt" = ( /turf/floor/mud, /area/shaded_hills/caves/woods) @@ -209,6 +214,9 @@ "YO" = ( /turf/unsimulated/mask, /area/shaded_hills/outside/river/woods) +"Zo" = ( +/turf/floor/mud/water/deep, +/area/shaded_hills/outside/river/woods) "Zs" = ( /obj/structure/wall_sconce/lantern{ dir = 1; @@ -15657,11 +15665,11 @@ zp zp zp zp -ul -ul -ul -ul -ul +En +En +En +En +En zp zp zp @@ -15806,21 +15814,21 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En zp zp zp @@ -15953,29 +15961,29 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En zp kx kx @@ -16103,32 +16111,32 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En dp JI AN @@ -16254,34 +16262,34 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En JI AN zp @@ -16405,35 +16413,35 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En JI AN zp @@ -16556,39 +16564,39 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En JI AN -ul +En zp zp zp @@ -16707,41 +16715,41 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +Zo +Zo +Zo +Zo +Zo +Zo +Zo +Zo +Zo +Zo +Zo +Zo +Zo +Zo +En +En +En +En +En +En dp JI AN dp -ul +En zp zp zp @@ -16857,44 +16865,44 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +Zo +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +Zo +En +En +En +En JI AN -ul -ul -ul +En +En +En zp zp zp @@ -17008,45 +17016,45 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul +En +En +En +En +En +En +En +En +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +Zo +En JI AN -ul -ul -ul +En +En +En zp zp zp @@ -17158,49 +17166,49 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO +En +En +En +En +En +En +En +Zo +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo JI AN -ul -ul -ul -ul -ul +En +En +En +En +En zp zp zp @@ -17310,50 +17318,50 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo dp JI AN dp -ul -ul -ul -ul -ul +En +En +En +En +En zp zp zp @@ -17460,54 +17468,54 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO +En +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +Zo +Zo +En +En +Zo +Zo +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo JI AN -PO -ul -ul -ul -ul -ul -ul -ul +Zo +En +En +En +En +En +En +En zp zp zp @@ -17611,57 +17619,57 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO +En +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +En +En +En +En +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo JI AN -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul +Zo +En +En +En +En +En +En +En +En +En zp zp zp @@ -17748,7 +17756,7 @@ ma ma ma ma -ul +En zp zp zp @@ -17762,60 +17770,60 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO +En +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +En +En +En +En +En +En +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo JI AN -PO -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +Wo +Zo +En +En +En +En +En +En +En +En +En +En zp zp zp @@ -17834,9 +17842,9 @@ zp zp zp zp -ul -ul -ul +En +En +En zp zp zp @@ -17901,9 +17909,9 @@ ma ma ma ma -ul -ul -ul +En +En +En zp zp zp @@ -17913,63 +17921,63 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO +En +En +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +En +En +En +En +En +En +En +En +En +En +En +En +En +En +Zo +Zo +Wo +Wo +Wo +Wo dp JI AN dp -PO -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +Wo +Zo +En +En +En +En +En +En +En +En +En +En +En zp zp zp @@ -17983,15 +17991,15 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En zp zp zp @@ -18053,78 +18061,78 @@ ma ma ma ma -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +En +En +En +En +En +En +En +En +En zp zp zp zp zp -ul -ul -ul -ul -PO -PO -PO -PO -PO +En +En +En +En +Zo +Wo +Wo +Wo +Wo JI AN -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +Wo +Wo +Wo +Zo +En +En +En +En +En +En +En +En +En +En +En +En +En zp zp zp @@ -18132,19 +18140,19 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En zp zp zp @@ -18206,40 +18214,40 @@ ma ma ma ma -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +En +En +En +En +En +En zp zp zp @@ -18250,55 +18258,55 @@ zp zp zp zp -ul -ul -ul -ul -PO -PO -PO -PO +En +En +En +En +Zo +Zo +Wo +Wo JI AN -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +Wo +Wo +Wo +Wo +Zo +Zo +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En zp zp uA @@ -18359,37 +18367,37 @@ ma ma ma ma -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +En +En +En +En +En zp zp zp @@ -18402,56 +18410,56 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -PO -PO +En +En +En +En +En +En +Zo +Zo JI AN -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En zp uA uA @@ -18512,35 +18520,35 @@ ma ma ma ma -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +En +En +En +En +En +En zp zp zp @@ -18555,56 +18563,56 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En dp JI AN dp -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En uA uA uA @@ -18664,34 +18672,34 @@ ma ma ma ma -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +En +En +En +En +En +En zp zp zp @@ -18707,56 +18715,56 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En JI AN -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +Zo +Zo +Zo +En +En +En +En +En +En +En +Zo +Zo +Zo +Zo +Zo +Zo +Zo +Zo +Zo +En +En +En +En +En +En +En +En +En +En uA uA uA @@ -18817,30 +18825,30 @@ ma ma ma ma -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +En +En +En +En zp zp zp @@ -18861,54 +18869,54 @@ zp zp zp zp -ul -ul -ul -ul -ul +En +En +En +En +En JI AN -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul +En +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +Zo +Zo +Zo +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +Zo +Zo +En +En +En +En +En +En uA uA uA @@ -18969,30 +18977,30 @@ ma ma ma ma -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +En +En +En +En +En zp zp zp @@ -19014,53 +19022,53 @@ zp zp zp zp -ul -ul -ul -ul +En +En +En +En JI AN -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul +En +En +En +Zo +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +Zo +En +En +En uA uA uA @@ -19112,8 +19120,8 @@ hT hT hT hT -hT -hT +PO +PO hT hT ma @@ -19122,28 +19130,28 @@ ma ma ma ma -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +En +En +En +En +En zp zp zp @@ -19168,51 +19176,51 @@ zp zp zp zp -ul +En dp JI AN dp -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO +En +En +En +En +En +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +Zo +Zo +En +En +Zo +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +Zo uA uA uA @@ -19262,40 +19270,40 @@ hT hT hT hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -ma -ma -ma -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO PO PO PO PO PO PO -ul -ul -ul -ul -ul +hT +hT +hT +ma +ma +ma +En +En +En +En +En +En +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +En +En +En +En +En zp zp zp @@ -19324,47 +19332,47 @@ zp zp JI AN -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO -PO -PO +En +En +En +En +En +En +En +En +Zo +Zo +Zo +Wo +Wo +Wo +Wo +Zo +Zo +Zo +Wo +Wo +Wo +Zo +Zo +En +En +En +En +En +En +En +En +En +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo uA uA uA @@ -19413,24 +19421,6 @@ hT hT hT hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -ul -ul -ul -PO -PO PO PO PO @@ -19441,12 +19431,30 @@ PO PO PO PO -ul -ul -ul -ul -ul -ul +hT +hT +hT +En +En +En +Zo +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +En +En +En +En +En +En zp zp zp @@ -19477,46 +19485,46 @@ zp JI AN zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -ul -ul -ul -PO -PO -PO -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO -PO -PO +En +En +En +En +En +En +En +En +En +En +Zo +Zo +Zo +Zo +En +En +En +Zo +Zo +Zo +En +En +En +En +En +En +En +En +En +En +En +En +En +Zo +Zo +Wo +Wo +Wo +Wo +Wo uA uA uA @@ -19564,20 +19572,6 @@ hT hT hT hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT PO PO PO @@ -19592,12 +19586,26 @@ PO PO PO PO -ul -ul -ul -ul -ul -ul +Zo +Zo +Zo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +En +En +En +En +En +En zp zp zp @@ -19631,44 +19639,44 @@ AN zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO -PO -PO +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +Zo +Zo +Wo +Wo +Wo uA uA uA @@ -19716,20 +19724,6 @@ hT hT hT hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT PO PO PO @@ -19743,13 +19737,27 @@ PO PO PO PO -ul -ul -ul -ul -ul -ul -ul +PO +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +En +En +En +En +En +En +En zp zp zp @@ -19784,43 +19792,43 @@ dp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En zp zp zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -PO -PO -PO +En +En +En +En +En +En +En +Zo +Zo +Wo uA uA uA @@ -19868,20 +19876,6 @@ hT hT hT hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT PO PO PO @@ -19894,13 +19888,27 @@ PO PO PO PO -ul -ul -ul -ul -ul -ul -ul +PO +PO +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Wo +Zo +Zo +En +En +En +En +En +En +En zp zp zp @@ -19940,16 +19948,16 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En zp zp zp @@ -19965,14 +19973,14 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul -ul -PO +En +En +En +En +En +En +En +Zo uA uA uA @@ -20020,19 +20028,6 @@ hT hT hT hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT PO PO PO @@ -20044,14 +20039,27 @@ PO PO PO PO -ul -ul -ul -ul -ul -ul -ul -ul +PO +PO +Wo +Wo +Zo +Zo +Zo +Wo +Wo +Wo +Zo +Zo +Zo +En +En +En +En +En +En +En +En zp zp zp @@ -20095,9 +20103,9 @@ zp zp zp zp -ul -ul -ul +En +En +En zp zp zp @@ -20119,12 +20127,12 @@ zp zp zp zp -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En uA uA uA @@ -20173,36 +20181,36 @@ hT hT hT hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT -hT PO PO -ul -ul -ul PO PO PO -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +PO +PO +PO +PO +PO +hT +hT +Zo +Zo +En +En +En +Zo +Zo +Zo +En +En +En +En +En +En +En +En +En +En zp zp zp @@ -20273,10 +20281,10 @@ zp zp zp zp -ul -ul -ul -ul +En +En +En +En uA uA uA @@ -20326,35 +20334,35 @@ hT hT hT hT +PO +PO +PO +PO +PO hT hT hT hT hT -hT -hT -hT -hT -hT -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En zp zp zp @@ -20427,8 +20435,8 @@ zp zp zp zp -ul -ul +En +En uA uA uA @@ -20480,7 +20488,7 @@ hT hT hT hT -hT +PO hT hT ma @@ -20488,24 +20496,24 @@ ma ma ma ma -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En zp zp zp @@ -20639,23 +20647,23 @@ ma ma ma ma -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En +En zp zp zp @@ -20791,22 +20799,22 @@ ma ma ma ma -ul -ul -ul +En +En +En zp zp zp -ul -ul -ul -ul -ul -ul -ul -ul -ul -ul +En +En +En +En +En +En +En +En +En +En zp zp zp @@ -20942,8 +20950,8 @@ ma ma ma ma -ul -ul +En +En zp zp zp @@ -20951,9 +20959,9 @@ zp zp zp zp -ul -ul -ul +En +En +En zp zp zp @@ -21093,8 +21101,8 @@ ma ma ma ma -ul -ul +En +En zp zp zp @@ -21244,7 +21252,7 @@ ma ma ma ma -ul +En zp zp zp diff --git a/maps/shaded_hills/shaded_hills.dm b/maps/shaded_hills/shaded_hills.dm index a4bf84f171d4..f2337434fae4 100644 --- a/maps/shaded_hills/shaded_hills.dm +++ b/maps/shaded_hills/shaded_hills.dm @@ -22,18 +22,6 @@ #include "jobs/visitors.dm" #include "jobs/wilderness.dm" - #include "submaps/_submaps.dm" - #include "submaps/downlands/_downlands.dm" - #include "submaps/grassland/_grassland.dm" - #include "submaps/swamp/_swamp.dm" - #include "submaps/woods/_woods.dm" - #include "submaps/woods/bear_den/bear_den.dm" - #include "submaps/woods/chemistry_shack/chemistry_shack.dm" - #include "submaps/woods/fairy_rings/fairy_rings.dm" - #include "submaps/woods/fox_den/fox_den.dm" - #include "submaps/woods/hunter_camp/hunter_camp.dm" - #include "submaps/woods/old_cabin/old_cabin.dm" - #include "levels/_levels.dm" #include "levels/random_map.dm" #include "levels/strata.dm" diff --git a/maps/shaded_hills/submaps/_submaps.dm b/maps/shaded_hills/submaps/_submaps.dm deleted file mode 100644 index 14b3948c9277..000000000000 --- a/maps/shaded_hills/submaps/_submaps.dm +++ /dev/null @@ -1,23 +0,0 @@ -#define MAP_TEMPLATE_CATEGORY_SH_GRASSLAND "template_sh_grassland" -#define MAP_TEMPLATE_CATEGORY_SH_SWAMP "template_sh_swamp" -#define MAP_TEMPLATE_CATEGORY_SH_WOODS "template_sh_woods" -#define MAP_TEMPLATE_CATEGORY_SH_DOWNLANDS "template_sh_downlands" -#define MAP_TEMPLATE_CATEGORY_SH_DUNGEON "template_sh_dungeon" -#define MAP_TEMPLATE_CATEGORY_SH_CAVERNS "template_sh_caverns" - -/datum/map_template/shaded_hills - abstract_type = /datum/map_template/shaded_hills - template_parent_type = /datum/map_template/shaded_hills - template_flags = TEMPLATE_FLAG_CLEAR_CONTENTS | TEMPLATE_FLAG_NO_RUINS - area_usage_test_exempted_root_areas = list( - /area/shaded_hills/outside/point_of_interest - ) - var/cost = 1 - -/datum/map_template/shaded_hills/get_template_cost() - return cost - -/area/shaded_hills/outside/point_of_interest - name = "Point Of Interest" - description = null - area_blurb_category = /area/shaded_hills/outside/point_of_interest diff --git a/maps/shaded_hills/submaps/downlands/_downlands.dm b/maps/shaded_hills/submaps/downlands/_downlands.dm deleted file mode 100644 index 22721f265b83..000000000000 --- a/maps/shaded_hills/submaps/downlands/_downlands.dm +++ /dev/null @@ -1,9 +0,0 @@ -/datum/map_template/shaded_hills/downlands - abstract_type = /datum/map_template/shaded_hills/downlands - template_categories = list(MAP_TEMPLATE_CATEGORY_SH_DOWNLANDS) - template_parent_type = /datum/map_template/shaded_hills/downlands - -/datum/map_template/shaded_hills/dungeon - abstract_type = /datum/map_template/shaded_hills/dungeon - template_categories = list(MAP_TEMPLATE_CATEGORY_SH_DUNGEON) - template_parent_type = /datum/map_template/shaded_hills/dungeon diff --git a/maps/shaded_hills/submaps/grassland/_grassland.dm b/maps/shaded_hills/submaps/grassland/_grassland.dm deleted file mode 100644 index 39f0722666b0..000000000000 --- a/maps/shaded_hills/submaps/grassland/_grassland.dm +++ /dev/null @@ -1,9 +0,0 @@ -/datum/map_template/shaded_hills/grassland - abstract_type = /datum/map_template/shaded_hills/grassland - template_categories = list(MAP_TEMPLATE_CATEGORY_SH_GRASSLAND) - template_parent_type = /datum/map_template/shaded_hills/grassland - -/datum/map_template/shaded_hills/cavern - abstract_type = /datum/map_template/shaded_hills/cavern - template_categories = list(MAP_TEMPLATE_CATEGORY_SH_CAVERNS) - template_parent_type = /datum/map_template/shaded_hills/cavern \ No newline at end of file diff --git a/maps/shaded_hills/submaps/swamp/_swamp.dm b/maps/shaded_hills/submaps/swamp/_swamp.dm deleted file mode 100644 index 9f4f963c1ee8..000000000000 --- a/maps/shaded_hills/submaps/swamp/_swamp.dm +++ /dev/null @@ -1,4 +0,0 @@ -/datum/map_template/shaded_hills/swamp - abstract_type = /datum/map_template/shaded_hills/swamp - template_categories = list(MAP_TEMPLATE_CATEGORY_SH_SWAMP) - template_parent_type = /datum/map_template/shaded_hills/swamp \ No newline at end of file diff --git a/maps/shaded_hills/submaps/woods/_woods.dm b/maps/shaded_hills/submaps/woods/_woods.dm deleted file mode 100644 index 0baea8f75c52..000000000000 --- a/maps/shaded_hills/submaps/woods/_woods.dm +++ /dev/null @@ -1,4 +0,0 @@ -/datum/map_template/shaded_hills/woods - abstract_type = /datum/map_template/shaded_hills/woods - template_categories = list(MAP_TEMPLATE_CATEGORY_SH_WOODS) - template_parent_type = /datum/map_template/shaded_hills/woods diff --git a/maps/shaded_hills/submaps/woods/bear_den/bear_den.dm b/maps/shaded_hills/submaps/woods/bear_den/bear_den.dm deleted file mode 100644 index ee4d7f308490..000000000000 --- a/maps/shaded_hills/submaps/woods/bear_den/bear_den.dm +++ /dev/null @@ -1,6 +0,0 @@ -/datum/map_template/shaded_hills/woods/bear_den - name = "bear den" - mappaths = list("maps/shaded_hills/submaps/woods/bear_den/bear_den.dmm") - -/area/shaded_hills/outside/point_of_interest/bear_den - name = "Point of Interest - Bear Den" diff --git a/maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dm b/maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dm deleted file mode 100644 index 19de9faa9788..000000000000 --- a/maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dm +++ /dev/null @@ -1,6 +0,0 @@ -/datum/map_template/shaded_hills/woods/chemistry_shack - name = "chemistry shack" - mappaths = list("maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dmm") - -/area/shaded_hills/outside/point_of_interest/chemistry_shack - name = "Point of Interest - Chemistry Shack" diff --git a/maps/shaded_hills/submaps/woods/fairy_rings/fairy_rings.dm b/maps/shaded_hills/submaps/woods/fairy_rings/fairy_rings.dm deleted file mode 100644 index 89ec23e18dc2..000000000000 --- a/maps/shaded_hills/submaps/woods/fairy_rings/fairy_rings.dm +++ /dev/null @@ -1,15 +0,0 @@ -/datum/map_template/shaded_hills/woods/fairy_ring - name = "fairy ring" - mappaths = list("maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring.dmm") - template_flags = TEMPLATE_FLAG_CLEAR_CONTENTS | TEMPLATE_FLAG_NO_RUINS | TEMPLATE_FLAG_ALLOW_DUPLICATES | TEMPLATE_FLAG_GENERIC_REPEATABLE - template_categories = list( - MAP_TEMPLATE_CATEGORY_SH_WOODS - ) - area_coherency_test_exempt_areas = list(/area/shaded_hills/outside/point_of_interest/fairy_ring) - -/datum/map_template/shaded_hills/woods/fairy_ring/glowing - name = "glowing fairy ring" - mappaths = list("maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring_glowing.dmm") - -/area/shaded_hills/outside/point_of_interest/fairy_ring - name = "Point of Interest - Fairy Ring" diff --git a/maps/shaded_hills/submaps/woods/fox_den/fox_den.dm b/maps/shaded_hills/submaps/woods/fox_den/fox_den.dm deleted file mode 100644 index de7b5dcfd5f8..000000000000 --- a/maps/shaded_hills/submaps/woods/fox_den/fox_den.dm +++ /dev/null @@ -1,6 +0,0 @@ -/datum/map_template/shaded_hills/woods/fox_den - name = "fox den" - mappaths = list("maps/shaded_hills/submaps/woods/fox_den/fox_den.dmm") - -/area/shaded_hills/outside/point_of_interest/fox_den - name = "Point of Interest - Fox Den" diff --git a/maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dm b/maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dm deleted file mode 100644 index 3cf4e2edc68d..000000000000 --- a/maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dm +++ /dev/null @@ -1,6 +0,0 @@ -/datum/map_template/shaded_hills/woods/hunter_camp - name = "hunter camp" - mappaths = list("maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dmm") - -/area/shaded_hills/outside/point_of_interest/hunter_camp - name = "Point of Interest - Hunter Camp" diff --git a/maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dm b/maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dm deleted file mode 100644 index 2d56e5161b37..000000000000 --- a/maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dm +++ /dev/null @@ -1,6 +0,0 @@ -/datum/map_template/shaded_hills/woods/old_cabin - name = "old cabin" - mappaths = list("maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dmm") - -/area/shaded_hills/outside/point_of_interest/old_cabin - name = "Point of Interest - Old Cabin" diff --git a/maps/tradeship/jobs/_goals.dm b/maps/tradeship/jobs/_goals.dm index e9d719bd2116..ac7cc4422dcd 100644 --- a/maps/tradeship/jobs/_goals.dm +++ b/maps/tradeship/jobs/_goals.dm @@ -26,7 +26,7 @@ var/global/list/tradeship_paperwork_end_areas = list() /datum/goal/department/paperwork/tradeship paperwork_types = list(/obj/item/paperwork/tradeship) signatory_job_list = list( - /datum/job/captain/tradeship, + /datum/job/standard/captain/tradeship, /datum/job/tradeship_first_mate ) diff --git a/maps/tradeship/jobs/civilian.dm b/maps/tradeship/jobs/civilian.dm index f491bc953a3c..edb03def44ac 100644 --- a/maps/tradeship/jobs/civilian.dm +++ b/maps/tradeship/jobs/civilian.dm @@ -1,4 +1,4 @@ -/datum/job/assistant/tradeship +/datum/job/standard/assistant/tradeship title = "Deck Hand" supervisors = "literally everyone, you bottom feeder" outfit_type = /decl/outfit/job/tradeship/hand diff --git a/maps/tradeship/jobs/command.dm b/maps/tradeship/jobs/command.dm index 0d124a9841e0..3647a632760c 100644 --- a/maps/tradeship/jobs/command.dm +++ b/maps/tradeship/jobs/command.dm @@ -1,4 +1,4 @@ -/datum/job/captain/tradeship +/datum/job/standard/captain/tradeship title = "Captain" supervisors = "your profit margin, your conscience, and the Trademaster" outfit_type = /decl/outfit/job/tradeship/captain @@ -11,7 +11,7 @@ ideal_character_age = 70 forced_spawnpoint = /decl/spawnpoint/cryo/captain -/datum/job/captain/tradeship/equip_job(var/mob/living/human/H, var/alt_title, var/datum/mil_branch/branch, var/datum/mil_rank/grade) +/datum/job/standard/captain/tradeship/equip_job(var/mob/living/human/H, var/alt_title, var/datum/mil_branch/branch, var/datum/mil_rank/grade) . = ..() if(H) H.verbs |= /mob/proc/tradehouse_rename_ship @@ -55,6 +55,7 @@ /datum/job/tradeship_first_mate title = "First Mate" supervisors = "the Captain" + hud_icon = 'maps/tradeship/hud.dmi' outfit_type = /decl/outfit/job/tradeship/mate head_position = 1 department_types = list( diff --git a/maps/tradeship/jobs/engineering.dm b/maps/tradeship/jobs/engineering.dm index 1938f034a310..62a9c6659c46 100644 --- a/maps/tradeship/jobs/engineering.dm +++ b/maps/tradeship/jobs/engineering.dm @@ -1,10 +1,10 @@ -/datum/job/engineer/tradeship +/datum/job/standard/engineer/tradeship title = "Junior Engineer" supervisors = "the Head Engineer" outfit_type = /decl/outfit/job/tradeship/hand/engine alt_titles = list() -/datum/job/chief_engineer/tradeship +/datum/job/standard/chief_engineer/tradeship title = "Head Engineer" outfit_type = /decl/outfit/job/tradeship/chief_engineer alt_titles = list() diff --git a/maps/tradeship/jobs/medical.dm b/maps/tradeship/jobs/medical.dm index 03b480321b82..bedcf5584533 100644 --- a/maps/tradeship/jobs/medical.dm +++ b/maps/tradeship/jobs/medical.dm @@ -1,4 +1,4 @@ -/datum/job/doctor/tradeship +/datum/job/standard/doctor/tradeship title = "Junior Doctor" supervisors = "the Head Doctor and the Captain" alt_titles = list() @@ -33,7 +33,7 @@ outfit_type = /decl/outfit/job/tradeship/doc/junior event_categories = list(ASSIGNMENT_MEDICAL) -/datum/job/cmo/tradeship +/datum/job/standard/cmo/tradeship title = "Head Doctor" supervisors = "the Captain and your own ethics" outfit_type = /decl/outfit/job/tradeship/doc diff --git a/maps/tradeship/jobs/science.dm b/maps/tradeship/jobs/science.dm index c14bb9e5b928..d941587b27dc 100644 --- a/maps/tradeship/jobs/science.dm +++ b/maps/tradeship/jobs/science.dm @@ -1,4 +1,4 @@ -/datum/job/scientist/tradeship +/datum/job/standard/scientist/tradeship title = "Junior Researcher" supervisors = "the Head Researcher and the Captain" total_positions = 2 @@ -8,7 +8,7 @@ // Smaller crew, more points. skill_points = 24 -/datum/job/rd/tradeship +/datum/job/standard/rd/tradeship title = "Head Researcher" alt_titles = list() outfit_type = /decl/outfit/job/tradeship/hand/researcher diff --git a/maps/tradeship/tradeship-0.dmm b/maps/tradeship/tradeship-0.dmm index f68f5a6eeb97..1de29f1d0ba1 100644 --- a/maps/tradeship/tradeship-0.dmm +++ b/maps/tradeship/tradeship-0.dmm @@ -1197,6 +1197,10 @@ /obj/item/stack/cable_coil/random/three, /turf/floor, /area/ship/trade/loading_bay) +"lG" = ( +/obj/effect/shuttle_landmark/automatic, +/turf/space, +/area/space) "ne" = ( /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/machinery/atmospherics/pipe/simple/hidden/supply, @@ -3507,7 +3511,7 @@ aa aa aa aa -aa +lG aa aa aa @@ -7360,7 +7364,7 @@ aa aa aa aa -aa +lG aa aa aa diff --git a/maps/tradeship/tradeship-1.dmm b/maps/tradeship/tradeship-1.dmm index 8a068ace688f..fd28e95fb89d 100644 --- a/maps/tradeship/tradeship-1.dmm +++ b/maps/tradeship/tradeship-1.dmm @@ -1763,6 +1763,10 @@ }, /turf/floor/plating, /area/ship/trade/maintenance/eva) +"eH" = ( +/obj/effect/shuttle_landmark/automatic, +/turf/space, +/area/space) "eJ" = ( /obj/machinery/vending/materials{ dir = 4 @@ -4589,7 +4593,7 @@ aa aa aa aa -aa +eH aa aa aa @@ -8689,7 +8693,7 @@ aa aa aa aa -aa +eH aa aa aa diff --git a/maps/tradeship/tradeship-2.dmm b/maps/tradeship/tradeship-2.dmm index 2eb597a678c5..f7a673962651 100644 --- a/maps/tradeship/tradeship-2.dmm +++ b/maps/tradeship/tradeship-2.dmm @@ -2002,6 +2002,15 @@ /obj/structure/cable{ icon_state = "4-8" }, +/obj/item/chems/glass/beaker{ + pixel_x = 5 + }, +/obj/item/chems/condiment/small/peppermill{ + pixel_x = 3 + }, +/obj/item/chems/condiment/enzyme, +/obj/item/chems/glass/rag, +/obj/item/chems/cooking_vessel/pot, /turf/floor/tiled, /area/ship/trade/crew/kitchen) "eQ" = ( @@ -4684,14 +4693,8 @@ "nH" = ( /obj/structure/table, /obj/effect/floor_decal/corner/red/diagonal, -/obj/item/chems/glass/beaker{ - pixel_x = 5 - }, -/obj/item/chems/condiment/small/peppermill{ - pixel_x = 3 - }, -/obj/item/chems/condiment/enzyme, -/obj/item/chems/glass/rag, +/obj/machinery/reagent_temperature, +/obj/item/chems/cooking_vessel/skillet, /turf/floor/tiled, /area/ship/trade/crew/kitchen) "nR" = ( @@ -5412,6 +5415,10 @@ }, /turf/floor/plating/airless, /area/ship/trade/maintenance/engine/aft) +"vN" = ( +/obj/effect/shuttle_landmark/automatic, +/turf/space, +/area/space) "vP" = ( /obj/machinery/light{ dir = 8; @@ -9045,7 +9052,7 @@ aa aa aa aa -aa +vN aa aa aa @@ -9259,7 +9266,7 @@ aa aa aa aa -aa +vN aa aa aa @@ -13196,7 +13203,7 @@ aa aa aa aa -aa +vN aa aa aa @@ -13639,7 +13646,7 @@ aa aa aa aa -aa +vN aa aa aa diff --git a/maps/tradeship/tradeship-3.dmm b/maps/tradeship/tradeship-3.dmm index 1a4f81e3fb31..bc596cfeecd4 100644 --- a/maps/tradeship/tradeship-3.dmm +++ b/maps/tradeship/tradeship-3.dmm @@ -1181,6 +1181,10 @@ /obj/machinery/commsrelay, /turf/floor/bluegrid, /area/ship/trade/comms) +"UX" = ( +/obj/effect/shuttle_landmark/automatic, +/turf/space, +/area/space) "UY" = ( /obj/structure/cable/yellow{ icon_state = "1-2" @@ -2382,7 +2386,7 @@ aa aa aa aa -aa +UX aa aa aa @@ -6665,7 +6669,7 @@ aa aa aa aa -aa +UX aa aa aa diff --git a/maps/tradeship/tradeship.dm b/maps/tradeship/tradeship.dm index 32eeb975e2ca..739a2948bae7 100644 --- a/maps/tradeship/tradeship.dm +++ b/maps/tradeship/tradeship.dm @@ -4,44 +4,46 @@ #include "../../code/unit_tests/offset_tests.dm" #endif - #include "../../mods/gamemodes/cult/_cult.dme" - #include "../../mods/gamemodes/heist/_heist.dme" - #include "../../mods/gamemodes/ninja/_ninja.dme" - #include "../../mods/gamemodes/revolution/_revolution.dme" - #include "../../mods/gamemodes/traitor/_traitor.dme" - #include "../../mods/gamemodes/spyvspy/_spyvspy.dme" - #include "../../mods/gamemodes/mixed/_mixed.dme" + #include "../../mods/content/tabloids/_tabloids.dme" #include "../random_ruins/exoplanet_ruins/playablecolony/playablecolony.dm" #include "../../mods/content/government/away_sites/icarus/icarus.dm" #include "../../mods/content/corporate/away_sites/lar_maria/lar_maria.dm" - #include "../../mods/content/standard_jobs/_standard_jobs.dme" - #include "../../mods/content/dungeon_loot/_dungeon_loot.dme" #include "../../mods/content/mundane.dm" + #include "../../mods/content/scaling_descriptors.dm" + #include "../../mods/content/bigpharma/_bigpharma.dme" #include "../../mods/content/corporate/_corporate.dme" + #include "../../mods/content/dungeon_loot/_dungeon_loot.dme" #include "../../mods/content/government/_government.dme" + #include "../../mods/content/matchmaking/_matchmaking.dme" #include "../../mods/content/modern_earth/_modern_earth.dme" #include "../../mods/content/mouse_highlights/_mouse_highlight.dme" - #include "../../mods/content/scaling_descriptors.dm" - #include "../../mods/content/xenobiology/_xenobiology.dme" - #include "../../mods/content/matchmaking/_matchmaking.dme" #include "../../mods/content/pheromones/_pheromones.dme" + #include "../../mods/content/psionics/_psionics.dme" + #include "../../mods/content/standard_jobs/_standard_jobs.dme" + #include "../../mods/content/supermatter/_supermatter.dme" + #include "../../mods/content/xenobiology/_xenobiology.dme" - #include "../../mods/mobs/dionaea/_dionaea.dme" - #include "../../mods/mobs/borers/_borers.dme" + #include "../../mods/gamemodes/cult/_cult.dme" + #include "../../mods/gamemodes/heist/_heist.dme" + #include "../../mods/gamemodes/ninja/_ninja.dme" + #include "../../mods/gamemodes/revolution/_revolution.dme" + #include "../../mods/gamemodes/spyvspy/_spyvspy.dme" + #include "../../mods/gamemodes/traitor/_traitor.dme" + #include "../../mods/gamemodes/mixed.dm" - // Must come after borers for compatibility. - #include "../../mods/content/psionics/_psionics.dme" + #include "../../mods/mobs/borers/_borers.dme" + #include "../../mods/mobs/dionaea/_dionaea.dme" #include "../../mods/species/ascent/_ascent.dme" + #include "../../mods/species/bayliens/_bayliens.dme" #include "../../mods/species/drakes/_drakes.dme" + #include "../../mods/species/neoavians/_neoavians.dme" #include "../../mods/species/serpentid/_serpentid.dme" #include "../../mods/species/utility_frames/_utility_frames.dme" - #include "../../mods/species/neoavians/_neoavians.dme" - #include "../../mods/species/bayliens/_bayliens.dme" #include "../../mods/species/vox/_vox.dme" #include "../away/bearcat/bearcat.dm" diff --git a/maps/tradeship/tradeship_jobs.dm b/maps/tradeship/tradeship_jobs.dm index 61b526624e0d..71ba7143cc3a 100644 --- a/maps/tradeship/tradeship_jobs.dm +++ b/maps/tradeship/tradeship_jobs.dm @@ -1,19 +1,18 @@ /datum/map/tradeship - default_job_type = /datum/job/assistant/tradeship + default_job_type = /datum/job/standard/assistant/tradeship default_department_type = /decl/department/civilian default_law_type = /datum/ai_laws/corporate - id_hud_icons = 'maps/tradeship/hud.dmi' allowed_jobs = list( - /datum/job/assistant/tradeship, - /datum/job/captain/tradeship, + /datum/job/standard/assistant/tradeship, + /datum/job/standard/captain/tradeship, /datum/job/tradeship_first_mate, - /datum/job/cmo/tradeship, - /datum/job/doctor/tradeship, - /datum/job/chief_engineer/tradeship, - /datum/job/engineer/tradeship, - /datum/job/rd/tradeship, - /datum/job/scientist/tradeship, - /datum/job/robot + /datum/job/standard/cmo/tradeship, + /datum/job/standard/doctor/tradeship, + /datum/job/standard/chief_engineer/tradeship, + /datum/job/standard/engineer/tradeship, + /datum/job/standard/rd/tradeship, + /datum/job/standard/scientist/tradeship, + /datum/job/standard/robot ) /obj/machinery/suit_cycler/tradeship diff --git a/maps/tradeship/tradeship_spawnpoints.dm b/maps/tradeship/tradeship_spawnpoints.dm index c4be5d21c350..36e4d8acdb7c 100644 --- a/maps/tradeship/tradeship_spawnpoints.dm +++ b/maps/tradeship/tradeship_spawnpoints.dm @@ -9,7 +9,7 @@ /decl/spawnpoint/cryo name = "Port Cryogenic Storage" spawn_announcement = "has completed revival in the port cryogenics bay" - disallow_job = list(/datum/job/robot) + disallow_job = list(/datum/job/standard/robot) /decl/spawnpoint/cryo/two name = "Starboard Cryogenic Storage" @@ -22,7 +22,7 @@ /decl/spawnpoint/cryo/captain name = "Captain Compartment" spawn_announcement = "has completed revival in the captain compartment" - restrict_job = list(/datum/job/captain/tradeship) + restrict_job = list(/datum/job/standard/captain/tradeship) uid = "spawn_cryo_captain" /obj/abstract/landmark/latejoin/cryo_captain diff --git a/maps/~mapsystem/maps.dm b/maps/~mapsystem/maps.dm index 673a2e15ef4f..4347eed54197 100644 --- a/maps/~mapsystem/maps.dm +++ b/maps/~mapsystem/maps.dm @@ -113,7 +113,9 @@ var/global/const/MAP_HAS_RANK = 2 //Rank system, also togglable var/default_law_type = /datum/ai_laws/asimov // The default lawset use by synth units, if not overriden by their laws var. var/security_state = /decl/security_state/default // The default security state system to use. - var/id_hud_icons = 'icons/mob/hud.dmi' // Used by the ID HUD (primarily sechud) overlay. + var/hud_icons = 'icons/screen/hud.dmi' // Used by the ID HUD (primarily sechud) overlay. + var/implant_hud_icons = 'icons/screen/hud_implants.dmi' + var/med_hud_icons = 'icons/screen/hud_med.dmi' var/num_exoplanets = 0 var/force_exoplanet_type // Used to override exoplanet weighting and always pick the same exoplanet. @@ -194,6 +196,12 @@ var/global/const/MAP_HAS_RANK = 2 //Rank system, also togglable var/background_categories_generated = FALSE var/list/_background_categories + var/default_ui_style + +/datum/map/New() + ..() + default_ui_style ||= DEFAULT_UI_STYLE + /datum/map/proc/get_background_categories() if(!background_categories_generated) if(isnull(_background_categories)) @@ -268,10 +276,9 @@ var/global/const/MAP_HAS_RANK = 2 //Rank system, also togglable if(!allowed_jobs) allowed_jobs = list() - for(var/jtype in subtypesof(/datum/job)) - var/datum/job/job = jtype - if(initial(job.available_by_default)) - allowed_jobs += jtype + for(var/datum/job/job as anything in subtypesof(/datum/job)) + if(!TYPE_IS_ABSTRACT(job) && job::available_by_default) + allowed_jobs += job if(ispath(default_job_type, /datum/job)) var/datum/job/J = default_job_type diff --git a/mods/_modpack.dm b/mods/_modpack.dm index 81c16e69f7a0..0fb1d5d79089 100644 --- a/mods/_modpack.dm +++ b/mods/_modpack.dm @@ -8,7 +8,11 @@ var/secrets_directory /// The folder to load additional NanoUI templates from. Must be relative to the DME's location (root game folder). var/nanoui_directory - var/list/dreams //! A list of strings to be added to the random dream proc. + + var/list/dreams //! A list of strings to be added to the random dream proc. + + var/list/tabloid_headlines //! A list of headline and article data used by the tabloids modpack. + var/list/tabloid_publishers //! A list of name strings used by the tabloids modpack. var/list/credits_other //! A list of strings that are used by the end of round credits roll. var/list/credits_adventure_names //! A list of strings that are used by the end of round credits roll. diff --git a/mods/content/fantasy/_fantasy.dme b/mods/content/fantasy/_fantasy.dme index 2dcfaa8cde52..87b99cb04e98 100644 --- a/mods/content/fantasy/_fantasy.dme +++ b/mods/content/fantasy/_fantasy.dme @@ -37,5 +37,16 @@ #include "items\clothing\loincloth.dm" #include "items\clothing\trousers.dm" #include "props\signpost.dm" +#include "submaps\_submaps.dm" +#include "submaps\downlands\_downlands.dm" +#include "submaps\grassland\_grassland.dm" +#include "submaps\swamp\_swamp.dm" +#include "submaps\woods\_woods.dm" +#include "submaps\woods\bear_den\bear_den.dm" +#include "submaps\woods\chemistry_shack\chemistry_shack.dm" +#include "submaps\woods\fairy_rings\fairy_rings.dm" +#include "submaps\woods\fox_den\fox_den.dm" +#include "submaps\woods\hunter_camp\hunter_camp.dm" +#include "submaps\woods\old_cabin\old_cabin.dm" // END_INCLUDE #endif diff --git a/mods/content/fantasy/datum/hnoll/bodytypes.dm b/mods/content/fantasy/datum/hnoll/bodytypes.dm index 218068362ced..1edda9e8e998 100644 --- a/mods/content/fantasy/datum/hnoll/bodytypes.dm +++ b/mods/content/fantasy/datum/hnoll/bodytypes.dm @@ -16,6 +16,7 @@ base_color = "#ae7d32" base_eye_color = "#00aa00" uid = "bodytype_hnoll" + footprints_icon = 'icons/mob/footprints/footprints_paw.dmi' default_sprite_accessories = list( SAC_HAIR = list( diff --git a/mods/content/fantasy/datum/overrides.dm b/mods/content/fantasy/datum/overrides.dm index 532c1e749978..2c9e6b417eff 100644 --- a/mods/content/fantasy/datum/overrides.dm +++ b/mods/content/fantasy/datum/overrides.dm @@ -31,28 +31,6 @@ /decl/background_category/religion = /decl/background_detail/religion/other ) -// Rename grafadreka -/decl/species/grafadreka - name = "Meredrake" - name_plural = "Meredrakes" - description = "Meredrakes, sometimes called mire-drakes, are large reptillian pack predators, widely assumed to be cousins to true dragons. \ - They are commonly found living in caves or burrows bordering grassland or forest, and while they prefer to hunt deer or rabbits, they will sometimes attack travellers if pickings are slim enough. \ - While they are not domesticated, they can be habituated and trained as working animals if captured young enough." - -/decl/sprite_accessory/marking/grafadreka - species_allowed = list("Meredrake") - -/decl/language/grafadreka - desc = "Hiss hiss, feed me rabbits." - -/decl/material/liquid/sifsap - name = "drake spittle" - lore_text = "A complex chemical slurry brewed up in the gullet of meredrakes." - -/obj/aura/sifsap_salve - name = "Drakespittle Salve" - descriptor = "glowing spittle" - // Rename wooden prostheses /decl/bodytype/prosthetic/wooden name = "carved wooden" // weird to call it 'crude' when it's cutting-edge for the setting diff --git a/mods/content/fantasy/icons/areas.dmi b/mods/content/fantasy/icons/areas.dmi new file mode 100644 index 000000000000..9849d6f87d8d Binary files /dev/null and b/mods/content/fantasy/icons/areas.dmi differ diff --git a/mods/content/fantasy/submaps/_submaps.dm b/mods/content/fantasy/submaps/_submaps.dm new file mode 100644 index 000000000000..71cfb9e98a05 --- /dev/null +++ b/mods/content/fantasy/submaps/_submaps.dm @@ -0,0 +1,53 @@ +#define MAP_TEMPLATE_CATEGORY_FANTASY_GRASSLAND "template_fantasy_grassland" +#define MAP_TEMPLATE_CATEGORY_FANTASY_SWAMP "template_fantasy_swamp" +#define MAP_TEMPLATE_CATEGORY_FANTASY_WOODS "template_fantasy_woods" +#define MAP_TEMPLATE_CATEGORY_FANTASY_DOWNLANDS "template_fantasy_downlands" +#define MAP_TEMPLATE_CATEGORY_FANTASY_DUNGEON "template_fantasy_dungeon" +#define MAP_TEMPLATE_CATEGORY_FANTASY_CAVERNS "template_fantasy_caverns" + +/datum/map_template/fantasy + abstract_type = /datum/map_template/fantasy + template_parent_type = /datum/map_template/fantasy + template_flags = TEMPLATE_FLAG_CLEAR_CONTENTS | TEMPLATE_FLAG_NO_RUINS + area_usage_test_exempted_root_areas = list( + /area/fantasy/outside/point_of_interest + ) + var/cost = 1 + +/datum/map_template/fantasy/get_template_cost() + return cost + +/datum/map/New() + LAZYSET(apc_test_exempt_areas, /area/fantasy, NO_SCRUBBER|NO_VENT|NO_APC) + ..() + +/area/fantasy + abstract_type = /area/fantasy + allow_xenoarchaeology_finds = FALSE + icon = 'mods/content/fantasy/icons/areas.dmi' + icon_state = "area" + base_turf = /turf/floor/rock/basalt + sound_env = GENERIC + ambience = list() + +/area/fantasy/outside + name = "\improper Wilderness" + abstract_type = /area/fantasy/outside + color = COLOR_GREEN + is_outside = OUTSIDE_YES + sound_env = PLAIN + ambience = list( + 'sound/effects/wind/wind_2_1.ogg', + 'sound/effects/wind/wind_2_2.ogg', + 'sound/effects/wind/wind_3_1.ogg', + 'sound/effects/wind/wind_4_1.ogg', + 'sound/effects/wind/wind_4_2.ogg', + 'sound/effects/wind/wind_5_1.ogg' + ) + interior_ambient_light_modifier = -0.3 + area_flags = AREA_FLAG_EXTERNAL | AREA_FLAG_IS_BACKGROUND + +/area/fantasy/outside/point_of_interest + name = "Point Of Interest" + description = null + area_blurb_category = /area/fantasy/outside/point_of_interest diff --git a/mods/content/fantasy/submaps/downlands/_downlands.dm b/mods/content/fantasy/submaps/downlands/_downlands.dm new file mode 100644 index 000000000000..c97d04705d06 --- /dev/null +++ b/mods/content/fantasy/submaps/downlands/_downlands.dm @@ -0,0 +1,9 @@ +/datum/map_template/fantasy/downlands + abstract_type = /datum/map_template/fantasy/downlands + template_categories = list(MAP_TEMPLATE_CATEGORY_FANTASY_DOWNLANDS) + template_parent_type = /datum/map_template/fantasy/downlands + +/datum/map_template/fantasy/dungeon + abstract_type = /datum/map_template/fantasy/dungeon + template_categories = list(MAP_TEMPLATE_CATEGORY_FANTASY_DUNGEON) + template_parent_type = /datum/map_template/fantasy/dungeon diff --git a/mods/content/fantasy/submaps/grassland/_grassland.dm b/mods/content/fantasy/submaps/grassland/_grassland.dm new file mode 100644 index 000000000000..57fcd595c5f3 --- /dev/null +++ b/mods/content/fantasy/submaps/grassland/_grassland.dm @@ -0,0 +1,9 @@ +/datum/map_template/fantasy/grassland + abstract_type = /datum/map_template/fantasy/grassland + template_categories = list(MAP_TEMPLATE_CATEGORY_FANTASY_GRASSLAND) + template_parent_type = /datum/map_template/fantasy/grassland + +/datum/map_template/fantasy/cavern + abstract_type = /datum/map_template/fantasy/cavern + template_categories = list(MAP_TEMPLATE_CATEGORY_FANTASY_CAVERNS) + template_parent_type = /datum/map_template/fantasy/cavern \ No newline at end of file diff --git a/mods/content/fantasy/submaps/swamp/_swamp.dm b/mods/content/fantasy/submaps/swamp/_swamp.dm new file mode 100644 index 000000000000..60ece589b4af --- /dev/null +++ b/mods/content/fantasy/submaps/swamp/_swamp.dm @@ -0,0 +1,4 @@ +/datum/map_template/fantasy/swamp + abstract_type = /datum/map_template/fantasy/swamp + template_categories = list(MAP_TEMPLATE_CATEGORY_FANTASY_SWAMP) + template_parent_type = /datum/map_template/fantasy/swamp \ No newline at end of file diff --git a/mods/content/fantasy/submaps/woods/_woods.dm b/mods/content/fantasy/submaps/woods/_woods.dm new file mode 100644 index 000000000000..657ce2c6b269 --- /dev/null +++ b/mods/content/fantasy/submaps/woods/_woods.dm @@ -0,0 +1,4 @@ +/datum/map_template/fantasy/woods + abstract_type = /datum/map_template/fantasy/woods + template_categories = list(MAP_TEMPLATE_CATEGORY_FANTASY_WOODS) + template_parent_type = /datum/map_template/fantasy/woods diff --git a/mods/content/fantasy/submaps/woods/bear_den/bear_den.dm b/mods/content/fantasy/submaps/woods/bear_den/bear_den.dm new file mode 100644 index 000000000000..cb4da036c7c2 --- /dev/null +++ b/mods/content/fantasy/submaps/woods/bear_den/bear_den.dm @@ -0,0 +1,6 @@ +/datum/map_template/fantasy/woods/bear_den + name = "bear den" + mappaths = list("mods/content/fantasy/submaps/woods/bear_den/bear_den.dmm") + +/area/fantasy/outside/point_of_interest/bear_den + name = "Point of Interest - Bear Den" diff --git a/maps/shaded_hills/submaps/woods/bear_den/bear_den.dmm b/mods/content/fantasy/submaps/woods/bear_den/bear_den.dmm similarity index 76% rename from maps/shaded_hills/submaps/woods/bear_den/bear_den.dmm rename to mods/content/fantasy/submaps/woods/bear_den/bear_den.dmm index 01ac1b5988a3..021df578e9b0 100644 --- a/maps/shaded_hills/submaps/woods/bear_den/bear_den.dmm +++ b/mods/content/fantasy/submaps/woods/bear_den/bear_den.dmm @@ -8,19 +8,19 @@ "k" = ( /obj/abstract/exterior_marker/inside, /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) "n" = ( /turf/floor/rock/basalt, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) "o" = ( /turf/floor/grass, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) "p" = ( /turf/floor/grass, /area/template_noop) "r" = ( /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) "w" = ( /obj/item/bladed/knife, /obj/item/cash/imperial/crown, @@ -29,20 +29,20 @@ /obj/abstract/exterior_marker/inside, /obj/abstract/exterior_marker/inside, /turf/floor/rock/basalt, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) "y" = ( /obj/abstract/exterior_marker/inside, /turf/floor/rock/basalt, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) "z" = ( /obj/abstract/exterior_marker/inside, /turf/wall/natural/dirt, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) "C" = ( /obj/abstract/exterior_marker/inside, /obj/abstract/exterior_marker/inside, /turf/floor/rock/basalt, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) "G" = ( /obj/item/bone/skull/deer, /obj/item/food/butchery/stomach, @@ -50,7 +50,7 @@ /obj/abstract/exterior_marker/inside, /obj/abstract/exterior_marker/inside, /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) "J" = ( /turf/floor/grass/wild, /area/template_noop) @@ -61,16 +61,16 @@ /mob/living/simple_animal/hostile/bear, /obj/abstract/exterior_marker/inside, /turf/floor/rock/basalt, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) "O" = ( /obj/abstract/exterior_marker/inside, /turf/wall/natural/basalt, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) "U" = ( /obj/abstract/exterior_marker/inside, /obj/abstract/exterior_marker/inside, /turf/wall/natural/basalt, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) "V" = ( /obj/item/cash/imperial/quin, /obj/item/cash/imperial/quin, @@ -79,12 +79,12 @@ /obj/item/cash/imperial/crown, /obj/abstract/exterior_marker/inside, /turf/floor/rock/basalt, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) "W" = ( /obj/abstract/exterior_marker/inside, /obj/abstract/exterior_marker/inside, /turf/wall/natural/dirt, -/area/shaded_hills/outside/point_of_interest/bear_den) +/area/fantasy/outside/point_of_interest/bear_den) (1,1,1) = {" K diff --git a/mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dm b/mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dm new file mode 100644 index 000000000000..158824c417b0 --- /dev/null +++ b/mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dm @@ -0,0 +1,6 @@ +/datum/map_template/fantasy/woods/chemistry_shack + name = "chemistry shack" + mappaths = list("mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dmm") + +/area/fantasy/outside/point_of_interest/chemistry_shack + name = "Point of Interest - Chemistry Shack" diff --git a/maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dmm b/mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dmm similarity index 75% rename from maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dmm rename to mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dmm index fa4f65d3fd71..6ed42c835894 100644 --- a/maps/shaded_hills/submaps/woods/chemistry_shack/chemistry_shack.dmm +++ b/mods/content/fantasy/submaps/woods/chemistry_shack/chemistry_shack.dmm @@ -5,7 +5,7 @@ dir = 4 }, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "h" = ( /obj/abstract/exterior_marker/inside, /obj/item/rock/hematite{ @@ -33,7 +33,7 @@ }, /obj/structure/table/desk/ebony, /turf/floor/path/herringbone/basalt, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "k" = ( /obj/abstract/exterior_marker/inside, /obj/structure/table/wood/ebony, @@ -41,12 +41,12 @@ /obj/item/chems/glass/handmade/teapot, /obj/abstract/landmark/organize/vertical, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "m" = ( /obj/abstract/exterior_marker/inside, /obj/structure/reagent_dispensers/barrel/ebony/oil, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "n" = ( /obj/structure/wall_sconce/lantern{ dir = 1; @@ -60,7 +60,7 @@ /obj/item/chems/glass/mortar, /obj/item/rock/basalt, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "q" = ( /obj/structure/drying_rack/ebony, /turf/floor/dirt, @@ -69,11 +69,11 @@ /obj/abstract/exterior_marker/inside, /obj/structure/filter_stand/mapped, /turf/floor/path/herringbone/basalt, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "s" = ( /obj/abstract/exterior_marker/inside, /turf/wall/log/walnut, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "z" = ( /turf/template_noop, /area/template_noop) @@ -81,30 +81,30 @@ /obj/abstract/exterior_marker/inside, /obj/structure/door/walnut, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "F" = ( /obj/abstract/exterior_marker/inside, /turf/wall/brick/basalt, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "H" = ( /obj/abstract/exterior_marker/inside, /turf/wall/brick/basalt/shutter, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "I" = ( /obj/abstract/exterior_marker/inside, /obj/structure/reagent_dispensers/barrel/ebony/water, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "J" = ( /obj/abstract/exterior_marker/inside, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "K" = ( /obj/abstract/exterior_marker/inside, /obj/structure/bed/simple/ebony/cloth, /obj/item/bedsheet/furs, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "L" = ( /obj/abstract/exterior_marker/inside, /obj/structure/table/wood/ebony, @@ -115,22 +115,22 @@ /obj/item/food/grown/carrot, /obj/item/kitchen/rollingpin, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "M" = ( /obj/abstract/exterior_marker/inside, /obj/structure/reagent_dispensers/barrel/ebony/wine, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "N" = ( /obj/abstract/exterior_marker/inside, /turf/floor/path/herringbone/basalt, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "R" = ( /obj/abstract/exterior_marker/inside, /obj/structure/closet/crate/chest/ebony, /obj/random/jewelry, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "U" = ( /obj/abstract/exterior_marker/inside, /obj/structure/wall_sconce/lantern{ @@ -149,19 +149,19 @@ pixel_y = 9 }, /turf/floor/path/herringbone/basalt, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "W" = ( /turf/floor/dirt, /area/template_noop) "X" = ( /obj/abstract/exterior_marker/inside, /turf/wall/log/walnut/shutter, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) "Y" = ( /obj/abstract/exterior_marker/inside, /obj/structure/fire_source/stove, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/chemistry_shack) +/area/fantasy/outside/point_of_interest/chemistry_shack) (1,1,1) = {" W diff --git a/maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring.dmm b/mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring.dmm similarity index 75% rename from maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring.dmm rename to mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring.dmm index b3c1314f5521..2611fe47b348 100644 --- a/maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring.dmm +++ b/mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring.dmm @@ -1,14 +1,14 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE "a" = ( /turf/floor/fake_grass, -/area/shaded_hills/outside/point_of_interest/fairy_ring) +/area/fantasy/outside/point_of_interest/fairy_ring) "w" = ( /obj/structure/flora/plant/random_mushroom, /turf/floor/fake_grass, -/area/shaded_hills/outside/point_of_interest/fairy_ring) +/area/fantasy/outside/point_of_interest/fairy_ring) "D" = ( /turf/floor/grass/wild, -/area/shaded_hills/outside/point_of_interest/fairy_ring) +/area/fantasy/outside/point_of_interest/fairy_ring) "N" = ( /turf/template_noop, /area/template_noop) diff --git a/maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring_glowing.dmm b/mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring_glowing.dmm similarity index 75% rename from maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring_glowing.dmm rename to mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring_glowing.dmm index bbd7d2ae0368..b86a4adcb0f4 100644 --- a/maps/shaded_hills/submaps/woods/fairy_rings/fairy_ring_glowing.dmm +++ b/mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring_glowing.dmm @@ -4,14 +4,14 @@ /area/template_noop) "h" = ( /turf/floor/grass, -/area/shaded_hills/outside/point_of_interest/fairy_ring) +/area/fantasy/outside/point_of_interest/fairy_ring) "j" = ( /turf/floor/barren, -/area/shaded_hills/outside/point_of_interest/fairy_ring) +/area/fantasy/outside/point_of_interest/fairy_ring) "A" = ( /obj/structure/flora/plant/random_mushroom/glowing, /turf/floor/grass, -/area/shaded_hills/outside/point_of_interest/fairy_ring) +/area/fantasy/outside/point_of_interest/fairy_ring) (1,1,1) = {" a diff --git a/mods/content/fantasy/submaps/woods/fairy_rings/fairy_rings.dm b/mods/content/fantasy/submaps/woods/fairy_rings/fairy_rings.dm new file mode 100644 index 000000000000..76140bdb7592 --- /dev/null +++ b/mods/content/fantasy/submaps/woods/fairy_rings/fairy_rings.dm @@ -0,0 +1,15 @@ +/datum/map_template/fantasy/woods/fairy_ring + name = "fairy ring" + mappaths = list("mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring.dmm") + template_flags = TEMPLATE_FLAG_CLEAR_CONTENTS | TEMPLATE_FLAG_NO_RUINS | TEMPLATE_FLAG_ALLOW_DUPLICATES | TEMPLATE_FLAG_GENERIC_REPEATABLE + template_categories = list( + MAP_TEMPLATE_CATEGORY_FANTASY_WOODS + ) + area_coherency_test_exempt_areas = list(/area/fantasy/outside/point_of_interest/fairy_ring) + +/datum/map_template/fantasy/woods/fairy_ring/glowing + name = "glowing fairy ring" + mappaths = list("mods/content/fantasy/submaps/woods/fairy_rings/fairy_ring_glowing.dmm") + +/area/fantasy/outside/point_of_interest/fairy_ring + name = "Point of Interest - Fairy Ring" diff --git a/mods/content/fantasy/submaps/woods/fox_den/fox_den.dm b/mods/content/fantasy/submaps/woods/fox_den/fox_den.dm new file mode 100644 index 000000000000..894f6f7fb50a --- /dev/null +++ b/mods/content/fantasy/submaps/woods/fox_den/fox_den.dm @@ -0,0 +1,6 @@ +/datum/map_template/fantasy/woods/fox_den + name = "fox den" + mappaths = list("mods/content/fantasy/submaps/woods/fox_den/fox_den.dmm") + +/area/fantasy/outside/point_of_interest/fox_den + name = "Point of Interest - Fox Den" diff --git a/maps/shaded_hills/submaps/woods/fox_den/fox_den.dmm b/mods/content/fantasy/submaps/woods/fox_den/fox_den.dmm similarity index 82% rename from maps/shaded_hills/submaps/woods/fox_den/fox_den.dmm rename to mods/content/fantasy/submaps/woods/fox_den/fox_den.dmm index 6e1c6e5ce940..8053ead1e471 100644 --- a/maps/shaded_hills/submaps/woods/fox_den/fox_den.dmm +++ b/mods/content/fantasy/submaps/woods/fox_den/fox_den.dmm @@ -9,7 +9,7 @@ /mob/living/simple_animal/passive/fox, /obj/abstract/exterior_marker/inside, /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/fox_den) +/area/fantasy/outside/point_of_interest/fox_den) "x" = ( /turf/floor/grass/wild, /area/template_noop) @@ -23,7 +23,7 @@ /obj/abstract/exterior_marker/inside, /obj/abstract/exterior_marker/inside, /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/fox_den) +/area/fantasy/outside/point_of_interest/fox_den) "B" = ( /turf/floor/grass, /area/template_noop) @@ -31,32 +31,32 @@ /obj/abstract/exterior_marker/inside, /obj/abstract/exterior_marker/inside, /turf/wall/natural/dirt, -/area/shaded_hills/outside/point_of_interest/fox_den) +/area/fantasy/outside/point_of_interest/fox_den) "O" = ( /obj/abstract/exterior_marker/inside, /obj/abstract/exterior_marker/inside, /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/fox_den) +/area/fantasy/outside/point_of_interest/fox_den) "P" = ( /obj/item/food/butchery/offal/small, /obj/item/stack/material/bone/mapped/bone, /obj/abstract/exterior_marker/inside, /obj/abstract/exterior_marker/inside, /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/fox_den) +/area/fantasy/outside/point_of_interest/fox_den) "S" = ( /obj/abstract/exterior_marker/inside, /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/fox_den) +/area/fantasy/outside/point_of_interest/fox_den) "W" = ( /obj/abstract/exterior_marker/inside, /turf/wall/natural/dirt, -/area/shaded_hills/outside/point_of_interest/fox_den) +/area/fantasy/outside/point_of_interest/fox_den) "Y" = ( /obj/item/seeds/extracted/foxglove, /obj/abstract/exterior_marker/inside, /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/fox_den) +/area/fantasy/outside/point_of_interest/fox_den) (1,1,1) = {" n diff --git a/mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dm b/mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dm new file mode 100644 index 000000000000..262e1b71d551 --- /dev/null +++ b/mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dm @@ -0,0 +1,6 @@ +/datum/map_template/fantasy/woods/hunter_camp + name = "hunter camp" + mappaths = list("mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dmm") + +/area/fantasy/outside/point_of_interest/hunter_camp + name = "Point of Interest - Hunter Camp" diff --git a/maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dmm b/mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dmm similarity index 69% rename from maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dmm rename to mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dmm index 0d8357987feb..b269d8d4cdde 100644 --- a/maps/shaded_hills/submaps/woods/hunter_camp/hunter_camp.dmm +++ b/mods/content/fantasy/submaps/woods/hunter_camp/hunter_camp.dmm @@ -1,93 +1,93 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE "a" = ( /turf/floor/grass/wild, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "b" = ( /obj/structure/drying_rack, /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "e" = ( /turf/floor/grass, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "h" = ( /obj/structure/flora/tree/hardwood/ebony, /turf/floor/grass, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "j" = ( /obj/item/stack/material/skin/mapped/leather/twenty, /turf/floor/barren, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "k" = ( /obj/item/food/butchery/offal/beef, /obj/item/food/butchery/offal/small/beef, /obj/structure/pit, /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "n" = ( /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "q" = ( /obj/structure/closet/crate/chest/ebony, /obj/item/food/butchery/haunch/shoulder/beef, /obj/item/food/butchery/haunch/side/beef, /turf/floor/barren, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "A" = ( /obj/abstract/exterior_marker/inside, /turf/wall/log/walnut, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "B" = ( /obj/structure/flora/stump/tree/ebony, /turf/floor/grass/wild, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "C" = ( /obj/structure/flora/stump/tree/ebony, /turf/floor/grass, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "D" = ( /obj/abstract/exterior_marker/inside, /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "E" = ( /obj/structure/reagent_dispensers/barrel/ebony/water, /turf/floor/barren, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "F" = ( /obj/structure/drying_rack, /turf/floor/barren, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "I" = ( /turf/floor/barren, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "J" = ( /obj/structure/flora/tree/hardwood/ebony, /turf/floor/grass/wild, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "K" = ( /turf/template_noop, /area/template_noop) "P" = ( /obj/structure/flora/tree/hardwood/mahogany, /turf/floor/grass/wild, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "Q" = ( /obj/structure/bed/bedroll/fur, /obj/abstract/exterior_marker/inside, /turf/floor/barren, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "S" = ( /obj/structure/fire_source/firepit/basalt, /obj/item/stack/material/log/mapped/walnut/fifteen, /turf/floor/barren, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "U" = ( /obj/abstract/exterior_marker/inside, /turf/floor/barren, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) "Z" = ( /obj/item/bladed/knife, /turf/floor/barren, -/area/shaded_hills/outside/point_of_interest/hunter_camp) +/area/fantasy/outside/point_of_interest/hunter_camp) (1,1,1) = {" K diff --git a/mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dm b/mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dm new file mode 100644 index 000000000000..4a2130efce27 --- /dev/null +++ b/mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dm @@ -0,0 +1,6 @@ +/datum/map_template/fantasy/woods/old_cabin + name = "old cabin" + mappaths = list("mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dmm") + +/area/fantasy/outside/point_of_interest/old_cabin + name = "Point of Interest - Old Cabin" diff --git a/maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dmm b/mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dmm similarity index 73% rename from maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dmm rename to mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dmm index 84ac9a1af5e2..18e121752741 100644 --- a/maps/shaded_hills/submaps/woods/old_cabin/old_cabin.dmm +++ b/mods/content/fantasy/submaps/woods/old_cabin/old_cabin.dmm @@ -3,33 +3,33 @@ /obj/structure/door/walnut, /obj/abstract/exterior_marker/inside, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "g" = ( /obj/abstract/exterior_marker/inside, /obj/structure/table/end, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "h" = ( /turf/template_noop, /area/template_noop) "i" = ( /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "k" = ( /obj/structure/closet/crate/chest/ebony, /obj/abstract/exterior_marker/inside, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "o" = ( /obj/structure/drying_rack/ebony, /obj/abstract/exterior_marker/inside, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "u" = ( /obj/structure/reagent_dispensers/barrel/ebony/beer, /obj/abstract/exterior_marker/inside, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "x" = ( /obj/structure/table/wood/ebony, /obj/item/flame/torch, @@ -38,7 +38,7 @@ /obj/item/rock/hematite, /obj/abstract/exterior_marker/inside, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "z" = ( /obj/effect/spider/spiderling/mundane, /obj/structure/table/wood/ebony, @@ -48,23 +48,23 @@ }, /obj/abstract/exterior_marker/inside, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "B" = ( /obj/effect/decal/cleanable/blood, /obj/abstract/exterior_marker/inside, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "D" = ( /obj/effect/spider/spiderling/mundane, /obj/structure/table/wood/ebony, /obj/item/food/grown/carrot, /obj/abstract/exterior_marker/inside, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "G" = ( /obj/abstract/exterior_marker/inside, /turf/wall/log/walnut/shutter, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "H" = ( /obj/structure/table/wood/ebony, /obj/item/bladed/knife, @@ -73,37 +73,37 @@ /obj/item/food/grown/carrot, /obj/abstract/exterior_marker/inside, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "I" = ( /obj/abstract/exterior_marker/inside, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "L" = ( /obj/effect/spider/spiderling/mundane, /obj/abstract/exterior_marker/inside, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "M" = ( /obj/abstract/exterior_marker/inside, /turf/wall/log/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "N" = ( /obj/abstract/exterior_marker/inside, /obj/structure/coatrack/ebony, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "T" = ( /obj/abstract/exterior_marker/inside, /obj/structure/table/desk/dresser, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "W" = ( /obj/structure/wall_sconce/torch{ dir = 1; pixel_y = 24 }, /turf/floor/dirt, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) "Z" = ( /obj/item/remains/human, /obj/structure/bed/simple/ebony/cloth, @@ -112,7 +112,7 @@ /obj/random/jewelry, /obj/abstract/exterior_marker/inside, /turf/floor/wood/rough/walnut, -/area/shaded_hills/outside/point_of_interest/old_cabin) +/area/fantasy/outside/point_of_interest/old_cabin) (1,1,1) = {" i diff --git a/maps/shaded_hills/submaps/woods/suspicious_cabin/suspicious_cabin.dmm b/mods/content/fantasy/submaps/woods/suspicious_cabin/suspicious_cabin.dmm similarity index 100% rename from maps/shaded_hills/submaps/woods/suspicious_cabin/suspicious_cabin.dmm rename to mods/content/fantasy/submaps/woods/suspicious_cabin/suspicious_cabin.dmm diff --git a/mods/content/psionics/_psionics.dm b/mods/content/psionics/_psionics.dm index 9092fd88ae6d..fa58ed18f582 100644 --- a/mods/content/psionics/_psionics.dm +++ b/mods/content/psionics/_psionics.dm @@ -30,3 +30,12 @@ var/datum/ability_handler/psionics/psi = !is_preview_copy && istype(character) && character.get_ability_handler(/datum/ability_handler/psionics) if(psi) psi.update() + +/decl/ability/can_use_ability(mob/user, list/metadata, silent = FALSE) + . = ..() + if(. && is_supernatural) + var/spell_leech = user.disrupts_psionics() + if(spell_leech) + if(!silent) + to_chat(user, SPAN_WARNING("You try to marshal your energy, but find it leeched away by \the [spell_leech]!")) + return FALSE diff --git a/mods/content/psionics/_psionics.dme b/mods/content/psionics/_psionics.dme index df5544cffe15..d52fd0955164 100644 --- a/mods/content/psionics/_psionics.dme +++ b/mods/content/psionics/_psionics.dme @@ -9,7 +9,6 @@ #include "datum\jobs.dm" #include "datum\mind.dm" #include "datum\security_state.dm" -#include "datum\spells.dm" #include "datum\surgery.dm" #include "datum\uplink.dm" #include "datum\antagonists\foundation.dm" @@ -27,7 +26,6 @@ #include "items\literature.dm" #include "items\null_ammo.dm" #include "items\nullrod.dm" -#include "items\soulstone.dm" #include "machines\psimeter.dm" #include "machines\psimonitor.dm" #include "system\subsystem_psi.dm" @@ -54,7 +52,6 @@ #include "system\psionics\interface\ui.dm" #include "system\psionics\interface\ui_hub.dm" #include "system\psionics\interface\ui_toggles.dm" -#include "system\psionics\mob\borer_power.dm" #include "system\psionics\mob\mob.dm" #include "system\psionics\mob\mob_assay.dm" #include "system\psionics\mob\mob_interactions.dm" diff --git a/mods/content/psionics/datum/chems.dm b/mods/content/psionics/datum/chems.dm index 1bc713de0eb3..e859f0dc5153 100644 --- a/mods/content/psionics/datum/chems.dm +++ b/mods/content/psionics/datum/chems.dm @@ -1,34 +1,7 @@ /decl/material/liquid/crystal_agent/do_material_check(var/mob/living/M) . = !!M.get_ability_handler(/datum/ability_handler/psionics) ? /decl/material/nullglass : ..() -/decl/material/liquid/glowsap/gleam/affect_overdose(mob/living/M, total_dose) +/decl/material/liquid/glowsap/gleam/affect_overdose(mob/living/victim, total_dose) ..() - var/datum/ability_handler/psionics/psi = M.get_ability_handler(/datum/ability_handler/psionics) + var/datum/ability_handler/psionics/psi = victim.get_ability_handler(/datum/ability_handler/psionics) psi?.check_latency_trigger(30, "a [name] overdose") - -/decl/chemical_reaction/synthesis/nullglass - name = "Soulstone" - result = null - required_reagents = list(/decl/material/liquid/blood = 15, /decl/material/liquid/crystal_agent = 1) - result_amount = 1 - -#ifdef GAMEMODE_PACK_CULT -/decl/chemical_reaction/synthesis/nullglass/get_alternate_reaction_indicator(var/datum/reagents/holder) - var/list/blood_data = REAGENT_DATA(holder, /decl/material/liquid/blood) - var/weakref/donor_ref = LAZYACCESS(blood_data, DATA_BLOOD_DONOR) - var/mob/living/donor = donor_ref?.resolve() - . = istype(donor) && !!donor.get_ability_handler(/datum/ability_handler/psionics) -#endif - -/decl/chemical_reaction/synthesis/nullglass/on_reaction(datum/reagents/holder, created_volume, reaction_flags, list/reaction_data) - var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) - if(reaction_flags) - #ifdef GAMEMODE_PACK_CULT - for(var/i = 1, i <= created_volume, i++) - new /obj/item/soulstone(location) - #else - CRASH("Nullglass alternate reaction triggered in [holder.my_atom] without cult modpack loaded!") - #endif - else - for(var/i = 1, i <= created_volume*2, i++) - new /obj/item/shard(location, /decl/material/solid/gemstone/crystal) \ No newline at end of file diff --git a/mods/content/psionics/datum/spells.dm b/mods/content/psionics/datum/spells.dm deleted file mode 100644 index 7c02c3520004..000000000000 --- a/mods/content/psionics/datum/spells.dm +++ /dev/null @@ -1,7 +0,0 @@ -/spell/cast_check(skipcharge = 0,mob/user = usr, var/list/targets) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell - var/spell_leech = user.disrupts_psionics() - if(spell_leech) - to_chat(user, SPAN_WARNING("You try to marshal your energy, but find it leeched away by \the [spell_leech]!")) - return 0 - . = ..() - \ No newline at end of file diff --git a/mods/content/psionics/items/soulstone.dm b/mods/content/psionics/items/soulstone.dm deleted file mode 100644 index 3d984a0711c7..000000000000 --- a/mods/content/psionics/items/soulstone.dm +++ /dev/null @@ -1,15 +0,0 @@ -#ifdef GAMEMODE_PACK_CULT -/obj/item/soulstone/disrupts_psionics() - . = !full ? src : FALSE - -/obj/item/soulstone/shatter() - for(var/i=1 to rand(2,5)) - new /obj/item/shard(get_turf(src), /decl/material/nullglass) - . = ..() - -/obj/item/soulstone/withstand_psi_stress(var/stress, var/atom/source) - . = ..(stress, source) - if(. > 0) - . = max(0, . - rand(2,5)) - shatter() -#endif \ No newline at end of file diff --git a/mods/content/psionics/system/psionics/complexus/complexus.dm b/mods/content/psionics/system/psionics/complexus/complexus.dm index 990edecd13e7..0ce5f4cfc189 100644 --- a/mods/content/psionics/system/psionics/complexus/complexus.dm +++ b/mods/content/psionics/system/psionics/complexus/complexus.dm @@ -1,5 +1,4 @@ /datum/ability_handler/psionics - var/announced = FALSE // Whether or not we have been announced to our holder yet. var/suppressed = TRUE // Whether or not we are suppressing our psi powers. var/use_psi_armour = TRUE // Whether or not we should automatically deflect/block incoming damage. diff --git a/mods/content/psionics/system/psionics/equipment/psipower.dm b/mods/content/psionics/system/psionics/equipment/psipower.dm index 3d850f27cf2d..8aa0afca3524 100644 --- a/mods/content/psionics/system/psionics/equipment/psipower.dm +++ b/mods/content/psionics/system/psionics/equipment/psipower.dm @@ -15,7 +15,9 @@ . = ..() /obj/item/ability/psionic/attack_self(var/mob/user) - sound_to(owner, 'sound/effects/psi/power_fail.ogg') + var/mob/owner = owner_ref?.resolve() + if(istype(owner)) + sound_to(owner, 'sound/effects/psi/power_fail.ogg') . = ..() /obj/item/ability/psionic/use_on_mob(mob/living/target, mob/living/user, animate = TRUE) @@ -31,6 +33,7 @@ . = ..(target, user, proximity) /obj/item/ability/psionic/Process() + var/mob/living/owner = owner_ref?.resolve() var/datum/ability_handler/psionics/psi = istype(owner) && owner.get_ability_handler(/datum/ability_handler/psionics) psi?.spend_power(maintain_cost, backblast_on_failure = FALSE) if((!owner || owner.do_psionics_check(maintain_cost, owner) || loc != owner || !(src in owner.get_held_items())) && !QDELETED(src)) diff --git a/mods/content/psionics/system/psionics/equipment/psipower_tk.dm b/mods/content/psionics/system/psionics/equipment/psipower_tk.dm index 787d2a59050f..ee21afaa9077 100644 --- a/mods/content/psionics/system/psionics/equipment/psipower_tk.dm +++ b/mods/content/psionics/system/psionics/equipment/psipower_tk.dm @@ -9,6 +9,7 @@ . = ..() /obj/item/ability/psionic/telekinesis/Process() + var/mob/living/owner = owner_ref?.resolve() var/datum/ability_handler/psionics/psi = istype(owner) && owner.get_ability_handler(/datum/ability_handler/psionics) if(!focus || !isturf(focus.loc) || get_dist(get_turf(focus), get_turf(owner)) > psi?.get_rank(PSI_PSYCHOKINESIS)) owner.drop_from_inventory(src) @@ -30,6 +31,7 @@ else return FALSE + var/mob/living/owner = owner_ref?.resolve() var/datum/ability_handler/psionics/psi = istype(owner) && owner.get_ability_handler(/datum/ability_handler/psionics) if(_focus.anchored || (check_paramount && psi?.get_rank(PSI_PSYCHOKINESIS) < PSI_RANK_PARAMOUNT)) focus = _focus @@ -88,7 +90,7 @@ else if(!focus.anchored) var/user_rank = psi?.get_rank(PSI_PSYCHOKINESIS) - focus.throw_at(target, user_rank*2, user_rank*10, owner) + focus.throw_at(target, user_rank*2, user_rank*10, owner_ref?.resolve()) sleep(1) sparkle() diff --git a/mods/content/psionics/system/psionics/interface/ui.dm b/mods/content/psionics/system/psionics/interface/ui.dm index 4e8adfa83bd5..3d8255b20308 100644 --- a/mods/content/psionics/system/psionics/interface/ui.dm +++ b/mods/content/psionics/system/psionics/interface/ui.dm @@ -1,14 +1,17 @@ /obj/screen/psi icon = 'mods/content/psionics/icons/psi.dmi' requires_ui_style = FALSE + apply_screen_overlay = FALSE var/hidden = TRUE + var/can_hide = TRUE /obj/screen/psi/Initialize(mapload, mob/_owner, ui_style, ui_color, ui_alpha, ui_cat) . = ..() update_icon() /obj/screen/psi/on_update_icon() - if(hidden) + ..() + if(hidden && can_hide) set_invisibility(INVISIBILITY_ABSTRACT) else set_invisibility(INVISIBILITY_NONE) \ No newline at end of file diff --git a/mods/content/psionics/system/psionics/interface/ui_hub.dm b/mods/content/psionics/system/psionics/interface/ui_hub.dm index cd87e5282115..97c5ba41adc0 100644 --- a/mods/content/psionics/system/psionics/interface/ui_hub.dm +++ b/mods/content/psionics/system/psionics/interface/ui_hub.dm @@ -6,6 +6,7 @@ maptext_x = 6 maptext_y = -8 requires_ui_style = FALSE + can_hide = FALSE var/image/on_cooldown var/list/components @@ -19,6 +20,7 @@ START_PROCESSING(SSprocessing, src) /obj/screen/psi/hub/on_update_icon() + ..() var/mob/living/owner = owner_ref?.resolve() var/datum/ability_handler/psionics/psi = istype(owner) && owner.get_ability_handler(/datum/ability_handler/psionics) icon_state = psi?.suppressed ? "psi_suppressed" : "psi_active" diff --git a/mods/content/psionics/system/psionics/interface/ui_toggles.dm b/mods/content/psionics/system/psionics/interface/ui_toggles.dm index 5585ac5d802a..93c34b82a275 100644 --- a/mods/content/psionics/system/psionics/interface/ui_toggles.dm +++ b/mods/content/psionics/system/psionics/interface/ui_toggles.dm @@ -29,6 +29,7 @@ name = "Show/Hide Psi UI" icon_state = "arrow_left" requires_ui_style = FALSE + can_hide = FALSE var/obj/screen/psi/hub/controller /obj/screen/psi/toggle_psi_menu/Initialize(mapload, mob/_owner, ui_style, ui_color, ui_alpha, ui_cat, obj/screen/psi/hub/_controller) @@ -43,6 +44,7 @@ controller.update_icon() /obj/screen/psi/toggle_psi_menu/on_update_icon() + ..() if(hidden) icon_state = "arrow_left" else diff --git a/mods/content/psionics/system/psionics/mob/mob.dm b/mods/content/psionics/system/psionics/mob/mob.dm index c85902acde4d..15cc79147421 100644 --- a/mods/content/psionics/system/psionics/mob/mob.dm +++ b/mods/content/psionics/system/psionics/mob/mob.dm @@ -1,4 +1,5 @@ /datum/ability_handler/psionics/refresh_login() + . = ..() update(TRUE) if(!suppressed) show_auras() diff --git a/mods/content/psionics/system/psionics/mob/mob_interactions.dm b/mods/content/psionics/system/psionics/mob/mob_interactions.dm index 366adb308823..aba8eeb102c0 100644 --- a/mods/content/psionics/system/psionics/mob/mob_interactions.dm +++ b/mods/content/psionics/system/psionics/mob/mob_interactions.dm @@ -6,8 +6,6 @@ power.handle_post_power(user, target); \ if(istype(result)) { \ sound_to(user, sound('sound/effects/psi/power_evoke.ogg')); \ - LAZYADD(ability_items, result); \ - user.put_in_hands(result); \ } \ return TRUE; \ } \ @@ -28,15 +26,19 @@ INVOKE_PSI_POWERS(user, get_grab_powers(SSpsi.get_faculty_by_intent(user.get_intent())), target) /datum/ability_handler/psionics/can_do_melee_invocation(mob/user, atom/target) + SHOULD_CALL_PARENT(FALSE) return TRUE /datum/ability_handler/psionics/do_melee_invocation(mob/user, atom/target) + SHOULD_CALL_PARENT(FALSE) INVOKE_PSI_POWERS(user, get_melee_powers(SSpsi.get_faculty_by_intent(user.get_intent())), target) /datum/ability_handler/psionics/can_do_ranged_invocation(mob/user, atom/target) + SHOULD_CALL_PARENT(FALSE) return TRUE /datum/ability_handler/psionics/do_ranged_invocation(mob/user, atom/target) + SHOULD_CALL_PARENT(FALSE) INVOKE_PSI_POWERS(user, get_ranged_powers(SSpsi.get_faculty_by_intent(user.get_intent())), target) -#undef INVOKE_PSI_POWERS \ No newline at end of file +#undef INVOKE_PSI_POWERS diff --git a/mods/content/standard_jobs/_standard_jobs.dme b/mods/content/standard_jobs/_standard_jobs.dme index cbba09eacef5..a17a75892bba 100644 --- a/mods/content/standard_jobs/_standard_jobs.dme +++ b/mods/content/standard_jobs/_standard_jobs.dme @@ -11,6 +11,7 @@ #include "departments\security.dm" #include "departments\service.dm" #include "departments\supply.dm" +#include "jobs\_job.dm" #include "jobs\captain.dm" #include "jobs\civilian.dm" #include "jobs\engineering.dm" diff --git a/mods/content/standard_jobs/icons/hud.dmi b/mods/content/standard_jobs/icons/hud.dmi new file mode 100644 index 000000000000..ccea1d4a2116 Binary files /dev/null and b/mods/content/standard_jobs/icons/hud.dmi differ diff --git a/mods/content/standard_jobs/jobs/_job.dm b/mods/content/standard_jobs/jobs/_job.dm new file mode 100644 index 000000000000..6869734493ab --- /dev/null +++ b/mods/content/standard_jobs/jobs/_job.dm @@ -0,0 +1,3 @@ +/datum/job/standard + abstract_type = /datum/job/standard + hud_icon = 'mods/content/standard_jobs/icons/hud.dmi' diff --git a/mods/content/standard_jobs/jobs/captain.dm b/mods/content/standard_jobs/jobs/captain.dm index c07823772524..d7abb62e0cd7 100644 --- a/mods/content/standard_jobs/jobs/captain.dm +++ b/mods/content/standard_jobs/jobs/captain.dm @@ -1,5 +1,6 @@ -/datum/job/captain +/datum/job/standard/captain title = "Captain" + hud_icon_state = "hudcaptain" head_position = 1 department_types = list(/decl/department/command) total_positions = 1 @@ -33,16 +34,17 @@ /datum/computer_file/program/reports ) -/datum/job/captain/equip_job(var/mob/living/human/H) +/datum/job/standard/captain/equip_job(var/mob/living/human/H) . = ..() if(.) H.implant_loyalty(src) -/datum/job/captain/get_access() +/datum/job/standard/captain/get_access() return get_all_station_access() -/datum/job/hop +/datum/job/standard/hop title = "Head of Personnel" + hud_icon_state = "hudhop" head_position = 1 department_types = list( /decl/department/command, diff --git a/mods/content/standard_jobs/jobs/civilian.dm b/mods/content/standard_jobs/jobs/civilian.dm index af71d84e5369..1ce8eeb39d04 100644 --- a/mods/content/standard_jobs/jobs/civilian.dm +++ b/mods/content/standard_jobs/jobs/civilian.dm @@ -1,5 +1,6 @@ -/datum/job/assistant +/datum/job/standard/assistant title = "Assistant" + hud_icon_state = "hudassistant" total_positions = -1 spawn_positions = -1 supervisors = "absolutely everyone" @@ -10,13 +11,14 @@ outfit_type = /decl/outfit/job/generic/assistant department_types = list(/decl/department/civilian) -/datum/job/assistant/get_access() +/datum/job/standard/assistant/get_access() if(get_config_value(/decl/config/toggle/assistant_maint)) return list(access_maint_tunnels) return list() -/datum/job/chaplain +/datum/job/standard/chaplain title = "Chaplain" + hud_icon_state = "hudchaplain" // TODO: not always a crucifix department_types = list(/decl/department/civilian) total_positions = 1 spawn_positions = 1 @@ -42,9 +44,10 @@ software_on_spawn = list(/datum/computer_file/program/reports) //Food -/datum/job/bartender +/datum/job/standard/bartender title = "Bartender" department_types = list(/decl/department/service) + hud_icon_state = "hudbartender" total_positions = 1 spawn_positions = 1 supervisors = "the head of personnel" @@ -68,8 +71,9 @@ SKILL_CHEMISTRY = SKILL_BASIC ) -/datum/job/chef +/datum/job/standard/chef title = "Chef" + hud_icon_state = "hudchef" department_types = list(/decl/department/service) total_positions = 2 spawn_positions = 2 @@ -89,8 +93,9 @@ SKILL_CHEMISTRY = SKILL_BASIC ) -/datum/job/hydro +/datum/job/standard/hydro title = "Gardener" + hud_icon_state = "hudgardener" department_types = list(/decl/department/service) total_positions = 2 spawn_positions = 1 @@ -111,8 +116,9 @@ event_categories = list(ASSIGNMENT_GARDENER) //Cargo -/datum/job/qm +/datum/job/standard/qm title = "Quartermaster" + hud_icon_state = "hudqm" department_types = list(/decl/department/supply) total_positions = 1 spawn_positions = 1 @@ -156,11 +162,12 @@ /datum/computer_file/program/reports ) -/datum/job/cargo_tech +/datum/job/standard/cargo_tech title = "Cargo Technician" department_types = list(/decl/department/supply) total_positions = 2 spawn_positions = 2 + hud_icon_state = "hudcargo" supervisors = "the quartermaster and the head of personnel" access = list( access_maint_tunnels, @@ -192,8 +199,9 @@ /datum/computer_file/program/reports ) -/datum/job/mining +/datum/job/standard/mining title = "Shaft Miner" + hud_icon_state = "hudminer" department_types = list(/decl/department/supply) total_positions = 3 spawn_positions = 3 @@ -227,11 +235,12 @@ SKILL_PILOT = SKILL_MAX ) -/datum/job/janitor +/datum/job/standard/janitor title = "Janitor" department_types = list(/decl/department/service) total_positions = 1 spawn_positions = 1 + hud_icon_state = "hudjanitor" supervisors = "the head of personnel" access = list( access_janitor, @@ -261,8 +270,9 @@ event_categories = list(ASSIGNMENT_JANITOR) //More or less assistants -/datum/job/librarian +/datum/job/standard/librarian title = "Librarian" + hud_icon_state = "hudlibrarian" department_types = list(/decl/department/civilian) total_positions = 1 spawn_positions = 1 @@ -281,8 +291,9 @@ skill_points = 20 software_on_spawn = list(/datum/computer_file/program/reports) -/datum/job/lawyer +/datum/job/standard/lawyer title = "Internal Affairs Agent" + hud_icon_state = "hudia" department_types = list(/decl/department/support) total_positions = 2 spawn_positions = 2 @@ -308,7 +319,7 @@ skill_points = 20 software_on_spawn = list(/datum/computer_file/program/reports) -/datum/job/lawyer/equip_job(var/mob/living/human/H) +/datum/job/standard/lawyer/equip_job(var/mob/living/human/H) . = ..() if(.) H.implant_loyalty(H) diff --git a/mods/content/standard_jobs/jobs/engineering.dm b/mods/content/standard_jobs/jobs/engineering.dm index 40cba5464895..84630cb60bac 100644 --- a/mods/content/standard_jobs/jobs/engineering.dm +++ b/mods/content/standard_jobs/jobs/engineering.dm @@ -1,5 +1,6 @@ -/datum/job/chief_engineer +/datum/job/standard/chief_engineer title = "Chief Engineer" + hud_icon_state = "hudce" head_position = 1 department_types = list( /decl/department/engineering, @@ -69,16 +70,15 @@ max_skill = list( SKILL_CONSTRUCTION = SKILL_MAX, - SKILL_ELECTRICAL = SKILL_MAX, - SKILL_ATMOS = SKILL_MAX, - SKILL_ENGINES = SKILL_MAX + SKILL_ELECTRICAL = SKILL_MAX, + SKILL_ATMOS = SKILL_MAX, + SKILL_ENGINES = SKILL_MAX ) skill_points = 30 software_on_spawn = list( /datum/computer_file/program/comm, /datum/computer_file/program/network_monitor, /datum/computer_file/program/power_monitor, - /datum/computer_file/program/supermatter_monitor, /datum/computer_file/program/alarm_monitor, /datum/computer_file/program/atmos_control, /datum/computer_file/program/rcon_console, @@ -88,10 +88,10 @@ ) event_categories = list(ASSIGNMENT_ENGINEER) -/datum/job/engineer +/datum/job/standard/engineer title = "Engineer" department_types = list(/decl/department/engineering) - + hud_icon_state = "hudengineer" total_positions = 8 spawn_positions = 7 supervisors = "the chief engineer" @@ -130,22 +130,21 @@ min_skill = list( SKILL_LITERACY = SKILL_ADEPT, SKILL_COMPUTER = SKILL_BASIC, - SKILL_EVA = SKILL_BASIC, - SKILL_CONSTRUCTION = SKILL_ADEPT, - SKILL_ELECTRICAL = SKILL_BASIC, - SKILL_ATMOS = SKILL_BASIC, - SKILL_ENGINES = SKILL_BASIC + SKILL_EVA = SKILL_BASIC, + SKILL_CONSTRUCTION = SKILL_ADEPT, + SKILL_ELECTRICAL = SKILL_BASIC, + SKILL_ATMOS = SKILL_BASIC, + SKILL_ENGINES = SKILL_BASIC ) max_skill = list( SKILL_CONSTRUCTION = SKILL_MAX, - SKILL_ELECTRICAL = SKILL_MAX, - SKILL_ATMOS = SKILL_MAX, - SKILL_ENGINES = SKILL_MAX + SKILL_ELECTRICAL = SKILL_MAX, + SKILL_ATMOS = SKILL_MAX, + SKILL_ENGINES = SKILL_MAX ) skill_points = 20 software_on_spawn = list( /datum/computer_file/program/power_monitor, - /datum/computer_file/program/supermatter_monitor, /datum/computer_file/program/alarm_monitor, /datum/computer_file/program/atmos_control, /datum/computer_file/program/rcon_console, diff --git a/mods/content/standard_jobs/jobs/medical.dm b/mods/content/standard_jobs/jobs/medical.dm index 14e68446da0a..d1a5517f1c31 100644 --- a/mods/content/standard_jobs/jobs/medical.dm +++ b/mods/content/standard_jobs/jobs/medical.dm @@ -1,5 +1,6 @@ -/datum/job/cmo +/datum/job/standard/cmo title = "Chief Medical Officer" + hud_icon_state = "hudcmo" head_position = 1 department_types = list( /decl/department/medical, @@ -73,8 +74,9 @@ ) event_categories = list(ASSIGNMENT_MEDICAL) -/datum/job/doctor +/datum/job/standard/doctor title = "Medical Doctor" + hud_icon_state = "hudmed" department_types = list(/decl/department/medical) minimal_player_age = 3 total_positions = 5 @@ -126,8 +128,9 @@ skill_points = 22 event_categories = list(ASSIGNMENT_MEDICAL) -/datum/job/chemist +/datum/job/standard/chemist title = "Pharmacist" + hud_icon_state = "hudpharmacist" department_types = list(/decl/department/medical) minimal_player_age = 7 total_positions = 2 @@ -161,8 +164,9 @@ ) skill_points = 16 -/datum/job/counselor +/datum/job/standard/counselor title = "Counselor" + hud_icon_state = "hudmed" alt_titles = list("Mentalist") department_types = list(/decl/department/medical) total_positions = 1 @@ -199,15 +203,6 @@ ) give_psionic_implant_on_join = FALSE -#ifdef MODPACK_PSIONICS -/datum/job/counselor/equip_job(var/mob/living/human/H) - if(H.mind.role_alt_title == "Counselor") - psi_faculties = list("[PSI_REDACTION]" = PSI_RANK_OPERANT) - if(H.mind.role_alt_title == "Mentalist") - psi_faculties = list("[PSI_COERCION]" = PSI_RANK_OPERANT) - return ..() -#endif - // Department-flavor IDs /obj/item/card/id/medical name = "identification card" diff --git a/mods/content/standard_jobs/jobs/science.dm b/mods/content/standard_jobs/jobs/science.dm index a7a074efbce1..548f9147ea76 100644 --- a/mods/content/standard_jobs/jobs/science.dm +++ b/mods/content/standard_jobs/jobs/science.dm @@ -1,10 +1,11 @@ -/datum/job/rd +/datum/job/standard/rd title = "Chief Science Officer" head_position = 1 department_types = list( /decl/department/science, /decl/department/command ) + hud_icon_state = "hudrd" total_positions = 1 spawn_positions = 1 supervisors = "the captain" @@ -74,13 +75,14 @@ skill_points = 30 event_categories = list(ASSIGNMENT_SCIENTIST) -/datum/job/scientist +/datum/job/standard/scientist title = "Scientist" department_types = list(/decl/department/science) total_positions = 6 spawn_positions = 4 supervisors = "the Chief Science Officer" selection_color = "#633d63" + hud_icon_state = "hudscientist" economic_power = 7 access = list( access_robotics, @@ -122,8 +124,9 @@ skill_points = 20 event_categories = list(ASSIGNMENT_SCIENTIST) -/datum/job/roboticist +/datum/job/standard/roboticist title = "Roboticist" + hud_icon_state = "hudroboticist" department_types = list(/decl/department/science) total_positions = 2 spawn_positions = 2 diff --git a/mods/content/standard_jobs/jobs/security.dm b/mods/content/standard_jobs/jobs/security.dm index 09751719b28d..b7ae8b0036b4 100644 --- a/mods/content/standard_jobs/jobs/security.dm +++ b/mods/content/standard_jobs/jobs/security.dm @@ -1,5 +1,6 @@ -/datum/job/hos +/datum/job/standard/hos title = "Head of Security" + hud_icon_state = "hudhos" head_position = 1 department_types = list( /decl/department/security, @@ -85,14 +86,15 @@ ) event_categories = list(ASSIGNMENT_SECURITY) -/datum/job/hos/equip_job(var/mob/living/human/H) +/datum/job/standard/hos/equip_job(var/mob/living/human/H) . = ..() if(.) H.implant_loyalty(H) -/datum/job/warden +/datum/job/standard/warden title = "Warden" department_types = list(/decl/department/security) + hud_icon_state = "hudwarden" total_positions = 1 spawn_positions = 1 supervisors = "the head of security" @@ -138,10 +140,10 @@ /datum/computer_file/program/camera_monitor ) -/datum/job/detective +/datum/job/standard/detective title = "Detective" department_types = list(/decl/department/security) - + hud_icon_state = "huddetective" total_positions = 2 spawn_positions = 2 supervisors = "the head of security" @@ -186,8 +188,9 @@ /datum/computer_file/program/camera_monitor ) -/datum/job/officer +/datum/job/standard/officer title = "Security Officer" + hud_icon_state = "hudsec" department_types = list(/decl/department/security) total_positions = 4 spawn_positions = 4 diff --git a/mods/content/standard_jobs/jobs/synthetics.dm b/mods/content/standard_jobs/jobs/synthetics.dm index 3a3dfbcd869b..23f768d4ac62 100644 --- a/mods/content/standard_jobs/jobs/synthetics.dm +++ b/mods/content/standard_jobs/jobs/synthetics.dm @@ -1,4 +1,4 @@ -/datum/job/computer +/datum/job/standard/computer title = "Computer" event_categories = list(ASSIGNMENT_COMPUTER) total_positions = 0 // Not used for AI, see is_position_available below and modules/mob/living/silicon/ai/latejoin.dm @@ -11,7 +11,8 @@ economic_power = 0 outfit_type = /decl/outfit/job/silicon/ai loadout_allowed = FALSE - hud_icon = "hudblank" + hud_icon_state = "hudblank" + hud_icon = null skill_points = 0 no_skill_buffs = TRUE guestbanned = 1 @@ -19,16 +20,16 @@ skip_loadout_preview = TRUE department_types = list(/decl/department/miscellaneous) -/datum/job/computer/equip_job(var/mob/living/human/H) +/datum/job/standard/computer/equip_job(var/mob/living/human/H) return !!H -/datum/job/computer/is_position_available() +/datum/job/standard/computer/is_position_available() return (empty_playable_ai_cores.len != 0) -/datum/job/computer/handle_variant_join(var/mob/living/human/H, var/alt_title) +/datum/job/standard/computer/handle_variant_join(var/mob/living/human/H, var/alt_title) return H -/datum/job/computer/do_spawn_special(var/mob/living/character, var/mob/new_player/new_player_mob, var/latejoin) +/datum/job/standard/computer/do_spawn_special(var/mob/living/character, var/mob/new_player/new_player_mob, var/latejoin) character = character.AIize(move = FALSE) // is_available for AI checks that there is an empty core available in this list @@ -46,7 +47,7 @@ qdel(C) return TRUE -/datum/job/robot +/datum/job/standard/robot title = "Robot" event_categories = list(ASSIGNMENT_ROBOT) total_positions = 2 @@ -58,7 +59,8 @@ economic_power = 0 loadout_allowed = FALSE outfit_type = /decl/outfit/job/silicon/cyborg - hud_icon = "hudblank" + hud_icon_state = "hudblank" + hud_icon = null skill_points = 0 no_skill_buffs = TRUE guestbanned = 1 @@ -66,14 +68,14 @@ skip_loadout_preview = TRUE department_types = list(/decl/department/miscellaneous) -/datum/job/robot/handle_variant_join(var/mob/living/human/H, var/alt_title) +/datum/job/standard/robot/handle_variant_join(var/mob/living/human/H, var/alt_title) if(H) return H.Robotize(SSrobots.get_mob_type_by_title(alt_title || title)) -/datum/job/robot/equip_job(var/mob/living/human/H) +/datum/job/standard/robot/equip_job(var/mob/living/human/H) return !!H -/datum/job/robot/New() +/datum/job/standard/robot/New() ..() alt_titles = SSrobots.robot_alt_titles.Copy() alt_titles -= title // So the unit test doesn't flip out if a mob or brain type is declared for our main title. diff --git a/mods/content/supermatter/_supermatter.dm b/mods/content/supermatter/_supermatter.dm new file mode 100644 index 000000000000..78daa387234a --- /dev/null +++ b/mods/content/supermatter/_supermatter.dm @@ -0,0 +1,23 @@ +// These are used by supermatter and supermatter monitor program, mostly for UI updating purposes. Higher should always be worse! +#define SUPERMATTER_ERROR -1 // Unknown status, shouldn't happen but just in case. +#define SUPERMATTER_INACTIVE 0 // No or minimal energy +#define SUPERMATTER_NORMAL 1 // Normal operation +#define SUPERMATTER_NOTIFY 2 // Ambient temp > 80% of CRITICAL_TEMPERATURE +#define SUPERMATTER_WARNING 3 // Ambient temp > CRITICAL_TEMPERATURE OR integrity damaged +#define SUPERMATTER_DANGER 4 // Integrity < 50% +#define SUPERMATTER_EMERGENCY 5 // Integrity < 25% +#define SUPERMATTER_DELAMINATING 6 // Pretty obvious. + +#define SUPERMATTER_DATA_EER "Relative EER" +#define SUPERMATTER_DATA_TEMPERATURE "Temperature" +#define SUPERMATTER_DATA_PRESSURE "Pressure" +#define SUPERMATTER_DATA_EPR "Chamber EPR" + +/decl/modpack/supermatter + name = "Supermatter Content" + desc = "This modpack includes the supermatter engine and related content." + nanoui_directory = "mods/content/supermatter/nano_templates/" + +/decl/modpack/supermatter/pre_initialize() + . = ..() + global.debug_verbs |= /datum/admins/proc/setup_supermatter \ No newline at end of file diff --git a/mods/content/supermatter/_supermatter.dme b/mods/content/supermatter/_supermatter.dme new file mode 100644 index 000000000000..fb6723cce50b --- /dev/null +++ b/mods/content/supermatter/_supermatter.dme @@ -0,0 +1,30 @@ +#ifndef CONTENT_PACK_SUPERMATTER +#define CONTENT_PACK_SUPERMATTER +// BEGIN_INCLUDE +#include "_supermatter.dm" +#include "admin_setup_supermatter.dm" +#include "datums\sm_codex.dm" +#include "datums\sm_follow.dm" +#include "datums\sm_grief_fix.dm" +#include "datums\sm_looping_sound.dm" +#include "datums\sm_supply_drop.dm" +#include "datums\sm_supply_pack.dm" +#include "datums\supermatter_monitor.dm" +#include "endgame_cascade\cascade_blob.dm" +#include "endgame_cascade\portal.dm" +#include "endgame_cascade\universe.dm" +#include "items\sm_book.dm" +#include "items\sm_grenade.dm" +#include "machinery\sm_supply_beacon.dm" +#include "machinery\supermatter.dm" +#include "machinery\supermatter_core_console.dm" +#include "overrides\sm_fuel_compressor.dm" +#include "overrides\sm_meteor.dm" +#include "overrides\sm_singularity.dm" +#include "overrides\sm_strings.dm" +#include "overrides\sm_trader.dm" +#include "overrides\sm_unit_tests.dm" +#include "overrides\sm_xenoarchaeology.dm" +#include "structures\sm_closets.dm" +// END_INCLUDE +#endif diff --git a/mods/content/supermatter/admin_setup_supermatter.dm b/mods/content/supermatter/admin_setup_supermatter.dm new file mode 100644 index 000000000000..9664671e8361 --- /dev/null +++ b/mods/content/supermatter/admin_setup_supermatter.dm @@ -0,0 +1,116 @@ +#define ENERGY_NITROGEN 115 // Roughly 8 emitter shots. +#define ENERGY_CARBONDIOXIDE 150 // Roughly 10 emitter shots. +#define ENERGY_HYDROGEN 300 // Roughly 20 emitter shots. + +/datum/admins/proc/setup_supermatter() + set category = "Debug" + set name = "Setup Supermatter" + set desc = "Allows you to start the Supermatter engine." + + if (!istype(src,/datum/admins)) + src = usr.client.holder + if (!istype(src,/datum/admins)) + to_chat(usr, "Error: you are not an admin!") + return + + var/response = input(usr, "Are you sure? This will start up the engine with selected gas as coolant.", "Engine setup") as null|anything in list("N2", "CO2", "H2", "Abort") + if(!response || response == "Abort") + return + + var/errors = 0 + var/warnings = 0 + var/success = 0 + + log_and_message_admins("## SUPERMATTER SETUP - Setup initiated by [usr] using coolant type [response].") + + // CONFIGURATION PHASE + // Coolant canisters, set types according to response. + for(var/obj/effect/engine_setup/coolant_canister/C in global.engine_setup_markers) + switch(response) + if("N2") + C.canister_type = /obj/machinery/portable_atmospherics/canister/nitrogen/engine_setup/ + continue + if("CO2") + C.canister_type = /obj/machinery/portable_atmospherics/canister/carbon_dioxide/engine_setup/ + continue + if("H2") + C.canister_type = /obj/machinery/portable_atmospherics/canister/hydrogen/engine_setup/ + continue + + for(var/obj/effect/engine_setup/core/C in global.engine_setup_markers) + switch(response) + if("N2") + C.energy_setting = ENERGY_NITROGEN + continue + if("CO2") + C.energy_setting = ENERGY_CARBONDIOXIDE + continue + if("H2") + C.energy_setting = ENERGY_HYDROGEN + continue + + for(var/obj/effect/engine_setup/filter/F in global.engine_setup_markers) + F.coolant = response + + var/list/delayed_objects = list() + // SETUP PHASE + for(var/obj/effect/engine_setup/S in global.engine_setup_markers) + var/result = S.activate(0) + switch(result) + if(ENGINE_SETUP_OK) + success++ + continue + if(ENGINE_SETUP_WARNING) + warnings++ + continue + if(ENGINE_SETUP_ERROR) + errors++ + log_and_message_admins("## SUPERMATTER SETUP - Error encountered! Aborting.") + break + if(ENGINE_SETUP_DELAYED) + delayed_objects.Add(S) + continue + + if(!errors) + for(var/obj/effect/engine_setup/S in delayed_objects) + var/result = S.activate(1) + switch(result) + if(ENGINE_SETUP_OK) + success++ + continue + if(ENGINE_SETUP_WARNING) + warnings++ + continue + if(ENGINE_SETUP_ERROR) + errors++ + log_and_message_admins("## SUPERMATTER SETUP - Error encountered! Aborting.") + break + + log_and_message_admins("## SUPERMATTER SETUP - Setup completed with [errors] errors, [warnings] warnings and [success] successful steps.") + + return + + + +// Energises the supermatter. Errors when unable to locate supermatter. +/obj/effect/engine_setup/core + name = "Supermatter Core Marker" + var/energy_setting = 0 + +/obj/effect/engine_setup/core/activate(var/last = 0) + if(!last) + return ENGINE_SETUP_DELAYED + ..() + var/obj/machinery/power/supermatter/SM = locate() in get_turf(src) + if(!SM) + log_and_message_admins("## ERROR: Unable to locate supermatter core at [x] [y] [z]!") + return ENGINE_SETUP_ERROR + if(!energy_setting) + log_and_message_admins("## ERROR: Energy setting unset at [x] [y] [z]!") + return ENGINE_SETUP_ERROR + SM.power = energy_setting + return ENGINE_SETUP_OK + +#undef ENERGY_NITROGEN +#undef ENERGY_CARBONDIOXIDE +#undef ENERGY_HYDROGEN diff --git a/mods/content/supermatter/datums/sm_codex.dm b/mods/content/supermatter/datums/sm_codex.dm new file mode 100644 index 000000000000..c0d5c160faeb --- /dev/null +++ b/mods/content/supermatter/datums/sm_codex.dm @@ -0,0 +1,21 @@ + +/datum/codex_entry/guide/supermatter + name = "Guide to Supermatter Engines" + available_to_map_tech_level = MAP_TECH_LEVEL_SPACE + +/datum/codex_entry/supermatter + associated_paths = list(/obj/machinery/power/supermatter) + mechanics_text = "When energized by a laser (or something hitting it), it emits radiation and heat. If the heat reaches above 7000 kelvin, it will send an alert and start taking damage. \ + After integrity falls to zero percent, it will delaminate, causing a massive explosion, station-wide radiation spikes, and hallucinations. \ + Supermatter reacts badly to oxygen in the atmosphere. It'll also heat up really quick if it is in vacuum.
    \ +
    \ + Supermatter cores are extremely dangerous to be close to, and requires protection to handle properly. The protection you will need is:
    \ + Optical meson scanners on your eyes, to prevent hallucinations when looking at the supermatter.
    \ + Radiation helmet and suit, as the supermatter is radioactive.
    \ +
    \ + Touching the supermatter will result in *instant death*, with no corpse left behind! You can drag the supermatter, but anything else will kill you. \ + It is advised to obtain a genetic backup before trying to drag it." + antag_text = "Exposing the supermatter to oxygen or vaccum will cause it to start rapidly heating up. Sabotaging the supermatter and making it explode will \ + cause a period of lag as the explosion is processed by the server, as well as irradiating the entire station and causing hallucinations to happen. \ + Wearing radiation equipment will protect you from most of the delamination effects sans explosion." + available_to_map_tech_level = MAP_TECH_LEVEL_SPACE \ No newline at end of file diff --git a/mods/content/supermatter/datums/sm_follow.dm b/mods/content/supermatter/datums/sm_follow.dm new file mode 100644 index 000000000000..5b221ad03d61 --- /dev/null +++ b/mods/content/supermatter/datums/sm_follow.dm @@ -0,0 +1,3 @@ +/datum/follow_holder/supermatter + sort_order = 10 + followed_type = /obj/machinery/power/supermatter \ No newline at end of file diff --git a/mods/content/supermatter/datums/sm_grief_fix.dm b/mods/content/supermatter/datums/sm_grief_fix.dm new file mode 100644 index 000000000000..70dd9469abc1 --- /dev/null +++ b/mods/content/supermatter/datums/sm_grief_fix.dm @@ -0,0 +1,8 @@ +/decl/atmos_grief_fix_step/supermatter + name = "Supermatter depowered" + sort_order = 0 + +/decl/atmos_grief_fix_step/supermatter/act() + // Depower the supermatter, as it would quickly blow up once we remove all gases from the pipes. + for(var/obj/machinery/power/supermatter/S in SSmachines.machinery) + S.power = 0 \ No newline at end of file diff --git a/code/modules/supermatter/sm_looping_sound.dm b/mods/content/supermatter/datums/sm_looping_sound.dm similarity index 100% rename from code/modules/supermatter/sm_looping_sound.dm rename to mods/content/supermatter/datums/sm_looping_sound.dm diff --git a/mods/content/supermatter/datums/sm_supply_drop.dm b/mods/content/supermatter/datums/sm_supply_drop.dm new file mode 100644 index 000000000000..1560d1118d2c --- /dev/null +++ b/mods/content/supermatter/datums/sm_supply_drop.dm @@ -0,0 +1,5 @@ +/datum/supply_drop_loot/supermatter + name = "Supermatter" +/datum/supply_drop_loot/supermatter/New() + ..() + contents = list(/obj/machinery/power/supermatter) diff --git a/mods/content/supermatter/datums/sm_supply_pack.dm b/mods/content/supermatter/datums/sm_supply_pack.dm new file mode 100644 index 000000000000..5261f06a0693 --- /dev/null +++ b/mods/content/supermatter/datums/sm_supply_pack.dm @@ -0,0 +1,6 @@ +/decl/hierarchy/supply_pack/engineering/smbig + name = "Power - Supermatter core" + contains = list(/obj/machinery/power/supermatter) + containertype = /obj/structure/closet/crate/secure/large/supermatter + containername = "\improper Supermatter crate (CAUTION)" + access = access_ce \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm b/mods/content/supermatter/datums/supermatter_monitor.dm similarity index 91% rename from code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm rename to mods/content/supermatter/datums/supermatter_monitor.dm index 08da0af07d61..2c20605a6b16 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm +++ b/mods/content/supermatter/datums/supermatter_monitor.dm @@ -5,7 +5,7 @@ /datum/computer_file/program/supermatter_monitor filename = "supmon" filedesc = "Supermatter Monitoring" - nanomodule_path = /datum/nano_module/program/supermatter_monitor/ + nanomodule_path = /datum/nano_module/program/supermatter_monitor program_icon_state = "smmon_0" program_key_state = "tech_key" program_menu_icon = "notice" @@ -215,3 +215,20 @@ if(S.uid == newuid) active = S return 1 + +// Add this to the software list for borgs +/obj/item/robot_module/engineering/grant_software() + software |= /datum/computer_file/program/supermatter_monitor + return ..() + +/obj/item/robot_module/flying/repair/grant_software() + software |= /datum/computer_file/program/supermatter_monitor + return ..() + +/obj/machinery/computer/modular/telescreen/preset/engineering/Initialize(mapload, d, populate_parts) + default_software |= /datum/computer_file/program/supermatter_monitor + return ..() + +/obj/machinery/computer/modular/preset/engineering/Initialize(mapload, d, populate_parts) + default_software |= /datum/computer_file/program/supermatter_monitor + return ..() \ No newline at end of file diff --git a/code/game/gamemodes/endgame/supermatter_cascade/cascade_blob.dm b/mods/content/supermatter/endgame_cascade/cascade_blob.dm similarity index 98% rename from code/game/gamemodes/endgame/supermatter_cascade/cascade_blob.dm rename to mods/content/supermatter/endgame_cascade/cascade_blob.dm index ef04b1069f78..6cd76d142330 100644 --- a/code/game/gamemodes/endgame/supermatter_cascade/cascade_blob.dm +++ b/mods/content/supermatter/endgame_cascade/cascade_blob.dm @@ -9,7 +9,7 @@ //luminosity = 5 //l_color="#0066ff" plane = ABOVE_LIGHTING_PLANE - layer = SUPERMATTER_WALL_LAYER + layer = SUBSPACE_WALL_LAYER var/list/avail_dirs = list(NORTH,SOUTH,EAST,WEST,UP,DOWN) diff --git a/code/game/gamemodes/endgame/supermatter_cascade/portal.dm b/mods/content/supermatter/endgame_cascade/portal.dm similarity index 100% rename from code/game/gamemodes/endgame/supermatter_cascade/portal.dm rename to mods/content/supermatter/endgame_cascade/portal.dm diff --git a/code/game/gamemodes/endgame/supermatter_cascade/universe.dm b/mods/content/supermatter/endgame_cascade/universe.dm similarity index 99% rename from code/game/gamemodes/endgame/supermatter_cascade/universe.dm rename to mods/content/supermatter/endgame_cascade/universe.dm index e9b2d2e40fd4..507097a121eb 100644 --- a/code/game/gamemodes/endgame/supermatter_cascade/universe.dm +++ b/mods/content/supermatter/endgame_cascade/universe.dm @@ -1,6 +1,3 @@ -var/global/universe_has_ended = 0 - - /datum/universal_state/supermatter_cascade name = "Supermatter Cascade" desc = "Unknown harmonance affecting universal substructure, converting nearby matter to supermatter." diff --git a/mods/content/supermatter/items/sm_book.dm b/mods/content/supermatter/items/sm_book.dm new file mode 100644 index 000000000000..8230625788a0 --- /dev/null +++ b/mods/content/supermatter/items/sm_book.dm @@ -0,0 +1,6 @@ +/obj/item/book/manual/supermatter_engine + name = "supermatter engine reference manual" + icon = 'icons/obj/items/books/book_supermatter.dmi' + author = "Central Engineering Division" + title = "Supermatter Engine Operating Manual" + guide_decl = /datum/codex_entry/guide/supermatter \ No newline at end of file diff --git a/code/game/objects/items/weapons/grenades/supermatter.dm b/mods/content/supermatter/items/sm_grenade.dm similarity index 50% rename from code/game/objects/items/weapons/grenades/supermatter.dm rename to mods/content/supermatter/items/sm_grenade.dm index 4f2758b53e30..b7f3186e666f 100644 --- a/code/game/objects/items/weapons/grenades/supermatter.dm +++ b/mods/content/supermatter/items/sm_grenade.dm @@ -33,3 +33,25 @@ if(world.time > implode_at) explosion(loc, 0, 1, 3, 4) qdel(src) + +/obj/item/box/supermatters + name = "box of supermatter grenades" + desc = "A box containing 5 highly experimental supermatter grenades." + icon_state = "radbox" + +/obj/item/box/supermatters/WillContain() + return list(/obj/item/grenade/supermatter = 5) + +/datum/uplink_item/item/grenades/supermatter + name = "1x Supermatter Grenade" + desc = "This grenade contains a small supermatter shard which will delaminate upon activation and pull in nearby objects, irradiate lifeforms, and eventually explode." + item_cost = 15 + antag_roles = list(/decl/special_role/mercenary) + path = /obj/item/grenade/supermatter + +/datum/uplink_item/item/grenades/supermatters + name = "5x Supermatter Grenades" + desc = "These grenades contains a small supermatter shard which will delaminate upon activation and pull in nearby objects, irradiate lifeforms, and eventually explode." + item_cost = 60 + antag_roles = list(/decl/special_role/mercenary) + path = /obj/item/box/supermatters diff --git a/mods/content/supermatter/machinery/sm_supply_beacon.dm b/mods/content/supermatter/machinery/sm_supply_beacon.dm new file mode 100644 index 000000000000..e6a622480b60 --- /dev/null +++ b/mods/content/supermatter/machinery/sm_supply_beacon.dm @@ -0,0 +1,7 @@ +/obj/item/supply_beacon/supermatter + name = "inactive supermatter supply beacon" + deploy_path = /obj/structure/supply_beacon/supermatter + +/obj/structure/supply_beacon/supermatter + name = "supermatter supply beacon" + drop_type = "supermatter" diff --git a/code/modules/supermatter/supermatter.dm b/mods/content/supermatter/machinery/supermatter.dm similarity index 98% rename from code/modules/supermatter/supermatter.dm rename to mods/content/supermatter/machinery/supermatter.dm index 5cb5d84467e5..f05b56abdaac 100644 --- a/code/modules/supermatter/supermatter.dm +++ b/mods/content/supermatter/machinery/supermatter.dm @@ -99,7 +99,7 @@ var/global/list/supermatter_delam_accent_sounds = list( SPAN_DANGER("As \the [source] slowly stops resonating, you find your skin covered in new radiation burns."), 1,\ SPAN_DANGER("The unearthly ringing subsides and you notice you have new radiation burns."), 2) else - M.show_message(SPAN_DANGER("You hear an uneartly ringing and notice your skin is covered in fresh radiation burns."), 2) + M.show_message(SPAN_DANGER("You hear an unearthly ringing and notice your skin is covered in fresh radiation burns."), 2) var/rads = 500 SSradiation.radiate(source, rads) @@ -116,6 +116,7 @@ var/global/list/supermatter_delam_accent_sounds = list( /decl/material/solid/exotic_matter = MATTER_AMOUNT_PRIMARY, /decl/material/solid/metal/steel = MATTER_AMOUNT_REINFORCEMENT ) + w_class = ITEM_SIZE_LARGE_STRUCTURE var/nitrogen_retardation_factor = 0.15 // Higher == N2 slows reaction more var/thermal_release_modifier = 10000 // Higher == more heat released during reaction @@ -696,6 +697,7 @@ var/global/list/supermatter_delam_accent_sounds = list( desc = "A strangely translucent and iridescent crystal that looks like it used to be part of a larger structure. You get headaches just from looking at it." icon = 'icons/obj/supermatter_32.dmi' icon_state = "supermatter_shard" + w_class = ITEM_SIZE_STRUCTURE warning_point = 50 emergency_point = 400 @@ -708,6 +710,7 @@ var/global/list/supermatter_delam_accent_sounds = list( /obj/machinery/power/supermatter/medium icon = 'icons/obj/supermatter_32.dmi' + w_class = (ITEM_SIZE_STRUCTURE + ITEM_SIZE_LARGE_STRUCTURE) / 2 // halfway between a shard and a normal SM /obj/machinery/power/supermatter/shard/announce_warning() //Shards don't get announcements return diff --git a/mods/content/supermatter/machinery/supermatter_core_console.dm b/mods/content/supermatter/machinery/supermatter_core_console.dm new file mode 100644 index 000000000000..8b2bf0e175ca --- /dev/null +++ b/mods/content/supermatter/machinery/supermatter_core_console.dm @@ -0,0 +1,45 @@ +// Does this really need to be its own thing...? +// Can it not just be a stock parts preset or something? +/obj/machinery/computer/air_control/supermatter_core + frequency = 1438 + out_pressure_mode = 1 + +/datum/fabricator_recipe/imprinter/circuit/supermatter_control + path = /obj/item/stock_parts/circuitboard/air_management/supermatter_core + +/obj/item/stock_parts/circuitboard/air_management/supermatter_core + name = "circuitboard (core control)" + build_path = /obj/machinery/computer/air_control/supermatter_core + frequency = 1438 + var/input_tag + var/output_tag + + var/list/input_info = list() + var/list/output_info = list() + + var/input_flow_setting = 700 + var/pressure_setting = 100 + +/obj/item/stock_parts/circuitboard/air_management/supermatter_core/construct(var/obj/machinery/computer/air_control/supermatter_core/SC) + if(..(SC)) + SC.input_tag = input_tag + SC.output_tag = output_tag + + SC.input_info = input_info.Copy() + SC.output_info = output_info.Copy() + + SC.input_flow_setting = input_flow_setting + SC.pressure_setting = input_flow_setting + return 1 + +/obj/item/stock_parts/circuitboard/air_management/supermatter_core/deconstruct(var/obj/machinery/computer/air_control/supermatter_core/SC) + if(..(SC)) + input_tag = SC.input_tag + output_tag = SC.output_tag + + input_info = SC.input_info.Copy() + output_info = SC.output_info.Copy() + + input_flow_setting = SC.input_flow_setting + pressure_setting = SC.input_flow_setting + return 1 \ No newline at end of file diff --git a/nano/templates/supermatter_crystal.tmpl b/mods/content/supermatter/nano_templates/supermatter_crystal.tmpl similarity index 100% rename from nano/templates/supermatter_crystal.tmpl rename to mods/content/supermatter/nano_templates/supermatter_crystal.tmpl diff --git a/nano/templates/supermatter_monitor.tmpl b/mods/content/supermatter/nano_templates/supermatter_monitor.tmpl similarity index 100% rename from nano/templates/supermatter_monitor.tmpl rename to mods/content/supermatter/nano_templates/supermatter_monitor.tmpl diff --git a/mods/content/supermatter/overrides/sm_fuel_compressor.dm b/mods/content/supermatter/overrides/sm_fuel_compressor.dm new file mode 100644 index 000000000000..e259fa266258 --- /dev/null +++ b/mods/content/supermatter/overrides/sm_fuel_compressor.dm @@ -0,0 +1,13 @@ +/obj/machinery/fuel_compressor/add_material(obj/thing, mob/user) + . = ..() + if(.) + return TRUE + if(istype(thing, /obj/machinery/power/supermatter/shard)) + var/exotic_matter_amount = thing?.matter?[/decl/material/solid/exotic_matter] + if(exotic_matter_amount <= 0) + return FALSE + stored_material[/decl/material/solid/exotic_matter] = exotic_matter_amount + to_chat(user, SPAN_NOTICE("You awkwardly cram \the [thing] into \the [src]'s material buffer.")) + qdel(thing) + return TRUE + return FALSE \ No newline at end of file diff --git a/mods/content/supermatter/overrides/sm_meteor.dm b/mods/content/supermatter/overrides/sm_meteor.dm new file mode 100644 index 000000000000..449ad80fbb91 --- /dev/null +++ b/mods/content/supermatter/overrides/sm_meteor.dm @@ -0,0 +1,5 @@ +/obj/effect/meteor/destroyer/supermatter + name = "supermatter shard" + desc = "Oh god, what will be next..?" + icon = 'icons/obj/supermatter_32.dmi' + icon_state = "supermatter" diff --git a/mods/content/supermatter/overrides/sm_singularity.dm b/mods/content/supermatter/overrides/sm_singularity.dm new file mode 100644 index 000000000000..b13506cd580b --- /dev/null +++ b/mods/content/supermatter/overrides/sm_singularity.dm @@ -0,0 +1,46 @@ +#define STAGE_SUPER 11 + +/// A singularity that has the mass of a supermatter crystal. +/decl/singularity_stage/stage_super + name = "super gravitational singularity" + desc = "A gravitational singularity with the properties of supermatter. It has the power to destroy worlds." + min_energy = 50000 + max_energy = INFINITY + stage_size = STAGE_SUPER + footprint = 6 + icon = 'icons/effects/352x352.dmi' + icon_state = "singularity_s11"//uh, whoever drew that, you know that black holes are supposed to look dark right? What's this, the clown's singulo? + pixel_x = -160 + pixel_y = -160 + grav_pull = 16 + consume_range = 5 + dissipates_over_time = 0 //It cant go smaller due to e loss + event_chance = 25 //Events will fire off more often. + forced_event = /decl/singularity_event/supermatter_wave + wander = TRUE + explosion_vulnerable = FALSE + em_heavy_range = 12 + em_light_range = 16 + mesmerize_text = "helpless" + the_goggles_do_nothing = TRUE + ignore_obstacles = TRUE + +/decl/singularity_stage/stage_super/grow_to(obj/effect/singularity/source) + source.visible_message(SPAN_SINISTER("You witness the creation of a destructive force that cannot possibly be stopped by human hands.")) + +// why is this not shrink_from or something? +/decl/singularity_stage/stage_five/shrink_to(obj/effect/singularity/source) + source.visible_message(SPAN_WARNING("\The [source] miraculously reduces in size and loses its supermatter properties.")) + +// Singularity event +/decl/singularity_event/supermatter_wave/handle_event(obj/effect/singularity/source) + for(var/mob/living/M in view(10, source.loc)) + to_chat(M, SPAN_WARNING("You hear an unearthly ringing, then what sounds like a shrilling kettle as you are washed with a wave of heat.")) + if(prob(67)) + to_chat(M, SPAN_NOTICE("Miraculously, it fails to kill you.")) + else + to_chat(M, SPAN_DANGER("You don't even have a moment to react as you are reduced to ashes by the intense radiation.")) + M.dust() + SSradiation.radiate(source, rand(source.energy)) + +#undef STAGE_SUPER \ No newline at end of file diff --git a/mods/content/supermatter/overrides/sm_strings.dm b/mods/content/supermatter/overrides/sm_strings.dm new file mode 100644 index 000000000000..2d7427f03d3d --- /dev/null +++ b/mods/content/supermatter/overrides/sm_strings.dm @@ -0,0 +1,19 @@ +/decl/game_mode/possible_ert_disabled_reasons() + var/static/sm_injected = FALSE + if(sm_injected) + return ..() + sm_injected = TRUE + . = ..() + . += "supermatter dust" + +/obj/item/disk/secret_project/get_secret_project_nouns() + var/static/sm_injected = FALSE + if(sm_injected) + return ..() + sm_injected = TRUE + . = ..() + . += "a supermatter engine" + return . + +/decl/material/solid/exotic_matter + lore_text = "Hypercrystalline supermatter is a subset of non-baryonic 'exotic' matter. It is found mostly in the heart of large stars, and features heavily in all kinds of fringe physics-defying technology." \ No newline at end of file diff --git a/mods/content/supermatter/overrides/sm_trader.dm b/mods/content/supermatter/overrides/sm_trader.dm new file mode 100644 index 000000000000..ded45374bd98 --- /dev/null +++ b/mods/content/supermatter/overrides/sm_trader.dm @@ -0,0 +1,3 @@ +/datum/trader/ship/unique/rock/New() + ..() + possible_trading_items[/obj/machinery/power/supermatter] = TRADER_ALL \ No newline at end of file diff --git a/mods/content/supermatter/overrides/sm_unit_tests.dm b/mods/content/supermatter/overrides/sm_unit_tests.dm new file mode 100644 index 000000000000..18351659e4c1 --- /dev/null +++ b/mods/content/supermatter/overrides/sm_unit_tests.dm @@ -0,0 +1,3 @@ +/datum/unit_test/turf_floor_icons_shall_be_valid/New() + ..() + excepted_types |= /turf/unsimulated/wall/cascade \ No newline at end of file diff --git a/mods/content/supermatter/overrides/sm_xenoarchaeology.dm b/mods/content/supermatter/overrides/sm_xenoarchaeology.dm new file mode 100644 index 000000000000..537de7a311cf --- /dev/null +++ b/mods/content/supermatter/overrides/sm_xenoarchaeology.dm @@ -0,0 +1,7 @@ +/datum/artifact_find/New() + var/static/supermatter_injected = FALSE + if(!supermatter_injected) + potential_finds[/obj/machinery/power/supermatter] = 5 + potential_finds[/obj/machinery/power/supermatter/shard] = 25 + supermatter_injected = TRUE + ..() diff --git a/mods/content/supermatter/structures/sm_closets.dm b/mods/content/supermatter/structures/sm_closets.dm new file mode 100644 index 000000000000..a1e58097f939 --- /dev/null +++ b/mods/content/supermatter/structures/sm_closets.dm @@ -0,0 +1,2 @@ +/obj/structure/closet/crate/secure/large/supermatter + closet_appearance = /decl/closet_appearance/large_crate/secure/hazard \ No newline at end of file diff --git a/mods/content/tabloids/_tabloids.dm b/mods/content/tabloids/_tabloids.dm new file mode 100644 index 000000000000..7d6188ff28fa --- /dev/null +++ b/mods/content/tabloids/_tabloids.dm @@ -0,0 +1,58 @@ +/decl/modpack/tabloids + name = "Tabloids" + tabloid_publishers = list( + "\improper Solar Enquirer", + "\improper Stellar Examiner", + "\improper Antares Daily", + "\improper Weekly Galactic News", + "\improper Spiral" + ) + tabloid_headlines = list( + "NARCOALGORITHMS: ARE YOUR CHILDREN SAFE?", + "ARE GMO HUMANS POISONOUS IN BED?", + "TOP 10 REASONS WHY OTHER SPECIES ARE A HOAX", + "CENTENNIAL POSITRONIC EXTENDS LIFESPAN WITH 1 SIMPLE TRICK", + "TOP 10 DANGEROUS FOODS WITH CHEMICALS", + "NEW TERRIFYING TEEN TREND: SUN-DIVING", + "HAS YOUR SPOUSE BEEN REPLACED BY AN ALIEN IMPOSTER? STUDIES SUGGEST YES!", + "SPACE CAUSES CANCER: DOCTORS CONFIRM", + "ARE BODY SCANNERS TOO INVASIVE? FIND OUT INSIDE!", + "HAS SCIENCE GONE TOO FAR? LOCAL SCIENTIST DEBUNKS ALIEN THEORY, DECRIES THEM AS TUBE EXPERIMENTS GONE WRONG", + "100 DELICIOUS RECIPES LETHAL TO CARBON-BASED LIFE", + "TOP FIVE SPECIES WE DROVE TO EXTINCTION; NUMBER TWO WILL SHOCK YOU", + "RELIGION WAS RIGHT? SHOCK FINDINGS SHOW ALIEN SIMILARITY TO ANIMALS, EXISTENCE OF BOATS", + "TOP TEN REASONS WHY ONLY HUMANS ARE SENTIENT", + "WHICH PLANET HAS THE BEST LOVERS? THIS AND MORE INSIDE!", + "SHE SAID WE SHOULD SEE OTHER PEOPLE, SO I MARRIED A NEO-AVIAN PACK: FULL STORY INSIDE", + "LOSE WEIGHT THREE TIMES FASTER WITH THESE LOW-G MANEUVERS!", + "MY DAUGHTER JOINED A NEURAL COLLECTIVE AND NOW SHE CAN TASTE SPACETIME: FULL STORY INSIDE", + "WERE THE NAZIS PSYCHIC? ONE HISTORIAN TELLS ALL", + "IS THE SOLAR GOVERNMENT CREATING AN AI SUPERINTELLIGENCE NEAR MERCURY? ONE EXPERT REVEALS SHOCKING INSIDER DETAILS!", + "TOP TEN HISTORICAL FIGURES THAT WERE TWO PROMETHEANS IN A TRENCHCOAT", + "TOP 10 SECRET AUGMENTS THE GOVERNMENT DOESN'T WANT YOU TO GET", + "ENLARGE YOUR MENTAL FACULTIES WITH THIS 1 WEIRD HAT", + "'HELP, MY SON THINKS HE'S A 20TH CENTURY VID CHARACTER CALLED SPOCK' AND MORE SHOCKING TALES INSIDE", + "18 RADICAL HIP IMPLANTS ALL THE KIDS ARE GETTING!", + "PRESERVED HEAD OF 21ST CENTURY CAPITALIST INSISTS THAT 'DYSON WALL' ONLY SANE SOLUTION TO RIMWARD MALCONTENTS", + "50 SHADES OF GREEN; BESTSELLING MULTISPECIES ROMANCE COMING TO CINEMAS", + "PLUTO: DWARF PLANET, OR SECRET RAMPANT AI FACILITY HELL-BENT ON CORRUPTING YOUR CHILDREN?", + "TOP TEN ANIME ALIENS. NUMBER 3 WILL SICKEN YOU", + "OCTUBER X'RALLBRE EXPOSED; NUDE PHOTOSHOOT LEAKS", + "WAR ON MARS AFTER NAKED MAN WAS FOUND; WERE THE ROMANS RIGHT?", + "REAL ALIENS ARGUE EARTH MOVIES RACIST!", + "HELP! I MARRIED A HEGEMONOUS SWARM INTELLIGENCE AND MY SON THINKS HE'S A ROUTER!", + "POSITRONICS: HUMAN INGENUITY AND GENEROSITY, OR A HORRIBLE MISTAKE? FIND OUT INSIDE!", + "THE FREE TRADER UNION: NEITHER FREE NOR A UNION. SHOCKING EXPOSE!", + "HAS THE FREE MARKET GONE TOO FAR? LUNA GLITTERPOP STAR AUCTIONS THIRD TESTICLE FOR TRANS-ORBITAL SHIPPING BONDS", + "THEY SAID IT WAS CANCER, BUT I KNEW IT WAS A TINY, SELF-REPLICATING CLONE OF RAY KURZWEIL: FULL STORY INSIDE", + "WHAT HAS TECHNOLOGY DONE? INDUSTRY BILLIONAIRE MARRIES OWN INFORMORPH MIND-COPY", + "REPTILLIAN ICE WARRIORS FROM ANOTHER WORLD LIVE INSIDE YOUR AIR DUCTS: HERE'S HOW TO GET RID OF THEM", + "10 CRITICAL THINGS YOU NEED TO KNOW ABOUT 'DRONEGATE'", + "THEY CALL THEM JUMPGATES BUT I'VE NEVER SEEN THEM JUMP: AN INDUSTRY INSIDER SPEAKS FOR THE FIRST TIME", + "EMERGENT INTELLIGENCES ARE STEALING YOUR BANK DETAILS, FETISHES: FOIL HAT RECIPE INSIDE", + "TIME TRAVELLERS ARE STEALING YOUR WIFI: 5 TIPS FOR DEFEATING HACKERS FROM THE FUTURE", + "'My mother was an alien spy': THIS CELEBRITY REVEAL WILL SHOCK AND AMAZE YOU", + "LUMINARY SCIENTIST SPEAKS: DIABETES IS A HYPERCORP RETROVIRUS!", + "'I REROUTED MY NEURAL CIRCUITRY SO THAT PAIN TASTES OF STRAWBERRIES' AND FIFTEEN OTHER CRAZY ALMACH STORIES", + "JOINING THE NAVY? HERE'S 15 EXPERT TIPS FOR AVOIDING BRAIN PARASITES" + ) \ No newline at end of file diff --git a/mods/content/tabloids/_tabloids.dme b/mods/content/tabloids/_tabloids.dme new file mode 100644 index 000000000000..0c6e6e35b01a --- /dev/null +++ b/mods/content/tabloids/_tabloids.dme @@ -0,0 +1,8 @@ +#ifndef CONTENT_PACK_TABLOIDS +#define CONTENT_PACK_TABLOIDS +// BEGIN_INCLUDE +#include "_tabloids.dm" +#include "tabloid.dm" +#include "tabloid_helpers.dm" +// END_INCLUDE +#endif \ No newline at end of file diff --git a/mods/content/tabloids/icons/magazine.dmi b/mods/content/tabloids/icons/magazine.dmi new file mode 100644 index 000000000000..62b385510c84 Binary files /dev/null and b/mods/content/tabloids/icons/magazine.dmi differ diff --git a/mods/content/tabloids/tabloid.dm b/mods/content/tabloids/tabloid.dm new file mode 100644 index 000000000000..6fc781a7ee64 --- /dev/null +++ b/mods/content/tabloids/tabloid.dm @@ -0,0 +1,36 @@ +/obj/item/tabloid + name = "tabloid magazine" + desc = "It's one of those trashy tabloid magazines. It looks pretty out of date." + icon = 'mods/content/tabloids/icons/magazine.dmi' + icon_state = "magazine" + randpixel = 6 + material = /decl/material/solid/organic/paper + matter = list(/decl/material/solid/organic/plastic = MATTER_AMOUNT_REINFORCEMENT) + var/headline + var/article_body + +/obj/item/tabloid/Initialize() + . = ..() + var/list/tabloid_headlines = get_tabloid_headlines() + name = SAFEPICK(get_tabloid_publishers()) || initial(name) + icon_state = SAFEPICK(get_tabloid_states()) || initial(icon_state) + headline = SAFEPICK(tabloid_headlines) + if(length(tabloid_headlines) && tabloid_headlines[headline]) + article_body = tabloid_headlines[headline] + +/obj/item/tabloid/examine(mob/user, distance, infix, suffix) + . = ..() + if(headline) + to_chat(user, "The headline screams, \"[headline]\"") + +/obj/item/tabloid/attack_self(mob/user) + . = ..() + if(!.) + user.visible_message(SPAN_NOTICE("\The [user] leafs idly through \the [src].")) + if(headline) + to_chat(user, "Most of it is the usual tabloid garbage, but the headline story, \"[headline]\", holds your attention for awhile.") + if(article_body) + to_chat(user, article_body) + else + to_chat(user, "It's the usual tabloid garbage. You find nothing of interest.") + return TRUE diff --git a/mods/content/tabloids/tabloid_helpers.dm b/mods/content/tabloids/tabloid_helpers.dm new file mode 100644 index 000000000000..966556dafbed --- /dev/null +++ b/mods/content/tabloids/tabloid_helpers.dm @@ -0,0 +1,24 @@ +// Minor fluff item for mapping in waiting rooms etc. +/proc/get_tabloid_publishers() + var/static/list/tabloid_publishers + if(!tabloid_publishers) + tabloid_publishers = list() + for(var/modpack_name in SSmodpacks.loaded_modpacks) + var/decl/modpack/modpack = SSmodpacks.loaded_modpacks[modpack_name] + if(length(modpack.tabloid_publishers)) + tabloid_publishers |= modpack.tabloid_publishers + return tabloid_publishers + +/proc/get_tabloid_headlines() + var/static/list/tabloid_headlines + if(!tabloid_headlines) + tabloid_headlines = list() + for(var/modpack_name in SSmodpacks.loaded_modpacks) + var/decl/modpack/modpack = SSmodpacks.loaded_modpacks[modpack_name] + if(length(modpack.tabloid_headlines)) + tabloid_headlines |= modpack.tabloid_headlines + return tabloid_headlines + +/proc/get_tabloid_states() + var/static/list/tabloid_states = icon_states('mods/content/tabloids/icons/magazine.dmi') + return tabloid_states diff --git a/mods/gamemodes/cult/_cult.dme b/mods/gamemodes/cult/_cult.dme index 82d4e19aed59..02138255d74c 100644 --- a/mods/gamemodes/cult/_cult.dme +++ b/mods/gamemodes/cult/_cult.dme @@ -21,7 +21,11 @@ #include "special_role.dm" #include "structures.dm" #include "talisman.dm" -#include "cultify\de-cultify.dm" +#include "abilities\_handler.dm" +#include "abilities\construct.dm" +#include "abilities\harvest.dm" +#include "abilities\shade.dm" +#include "cultify\de-cultify.dm" #include "cultify\defile.dm" #include "cultify\mob.dm" #include "cultify\turf.dm" @@ -29,7 +33,12 @@ #include "mobs\shade.dm" #include "mobs\constructs\constructs.dm" #include "mobs\constructs\soulstone.dm" -#include "spells\construct.dm" -#include "spells\harvest.dm" // END_INCLUDE -#endif \ No newline at end of file +#endif +// BEGIN_INTERNALS +// END_INTERNALS +// BEGIN_FILE_DIR +#define FILE_DIR . +// END_FILE_DIR +// BEGIN_PREFERENCES +// END_PREFERENCES diff --git a/mods/gamemodes/cult/abilities/_handler.dm b/mods/gamemodes/cult/abilities/_handler.dm new file mode 100644 index 000000000000..f346bb73fb41 --- /dev/null +++ b/mods/gamemodes/cult/abilities/_handler.dm @@ -0,0 +1,21 @@ +/obj/screen/ability/category/cult + name = "Toggle Construct Abilities" + icon = 'mods/gamemodes/cult/icons/abilities.dmi' + +/obj/screen/ability/button/cult + icon = 'mods/gamemodes/cult/icons/abilities.dmi' + +/datum/ability_handler/cult + category_toggle_type = /obj/screen/ability/category/cult + +/decl/ability/cult + abstract_type = /decl/ability/cult + ability_icon = 'mods/gamemodes/cult/icons/abilities.dmi' + ability_icon_state = "artificer" + associated_handler_type = /datum/ability_handler/cult + ui_element_type = /obj/screen/ability/button/cult + ability_cooldown_time = 60 SECONDS + +/obj/item/ability/cult + icon = 'mods/gamemodes/cult/icons/ability_item.dmi' + color = COLOR_RED diff --git a/mods/gamemodes/cult/abilities/construct.dm b/mods/gamemodes/cult/abilities/construct.dm new file mode 100644 index 000000000000..60138eaba356 --- /dev/null +++ b/mods/gamemodes/cult/abilities/construct.dm @@ -0,0 +1,131 @@ +//////////////////////////////Construct Spells///////////////////////// +/decl/ability/cult/construct + name = "Artificer" + desc = "This spell conjures a construct which may be controlled by shades." + target_selector = /decl/ability_targeting/clear_turf + overlay_icon = 'mods/gamemodes/cult/icons/effects.dmi' + overlay_icon_state = "sparkles" + target_selector = /decl/ability_targeting/clear_turf/construct + var/summon_type = /obj/structure/constructshell + +/decl/ability_targeting/clear_turf/construct/validate_target(mob/user, atom/target, list/metadata, decl/ability/ability) + var/decl/ability/cult/construct/cult_ability = ability + if(!istype(cult_ability)) + return FALSE + return ..() && !istype(target, cult_ability.summon_type) && !(locate(cult_ability.summon_type) in target) + +/decl/ability/cult/construct/apply_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) + . = ..() + var/turf/target_turf = get_turf(hit_target) + if(istype(target_turf)) + if(ispath(summon_type, /turf)) + target_turf = target_turf.ChangeTurf(summon_type, TRUE, FALSE, TRUE, TRUE, FALSE) + if(target_turf) // We reapply effects as target no longer exists. + apply_effect_to(user, target_turf, metadata) + else if(ispath(summon_type, /atom)) + new summon_type(target_turf) + +/decl/ability/cult/construct/lesser + ability_cooldown_time = 2 MINUTES + summon_type = /obj/structure/constructshell/cult + ability_icon_state = "const_shell" + +/decl/ability/cult/construct/floor + name = "Floor Construction" + desc = "This spell constructs a cult floor" + ability_cooldown_time = 2 SECONDS + summon_type = /turf/floor/cult + ability_icon_state = "const_floor" + overlay_icon_state = "cultfloor" + +/decl/ability/cult/construct/wall + name = "Lesser Construction" + desc = "This spell constructs a cult wall" + ability_cooldown_time = 10 SECONDS + summon_type = /turf/wall/cult + ability_icon_state = "const_wall" + overlay_icon_state = "cultwall" + +/decl/ability/cult/construct/wall/reinforced + name = "Greater Construction" + desc = "This spell constructs a reinforced metal wall" + ability_cooldown_time = 30 SECONDS + summon_type = /turf/wall/r_wall + +/decl/ability/cult/construct/soulstone + name = "Summon Soulstone" + desc = "This spell reaches into Nar-Sie's realm, summoning one of the legendary fragments across time and space." + ability_cooldown_time = 5 MINUTES + summon_type = /obj/item/soulstone + ability_icon_state = "const_stone" + +/decl/ability/cult/construct/pylon + name = "Red Pylon" + desc = "This spell conjures a fragile crystal from Nar-Sie's realm. Makes for a convenient light source." + ability_cooldown_time = 20 SECONDS + summon_type = /obj/structure/cult/pylon + ability_icon_state = "const_pylon" + target_selector = /decl/ability_targeting/pylon + is_melee_invocation = TRUE + prep_cast = TRUE + +/decl/ability_targeting/pylon/validate_target(mob/user, atom/target, list/metadata, decl/ability/ability) + . = ..() + if(!.) + return + if(istype(target, /obj/structure/cult/pylon)) + return TRUE + if(isturf(target)) + var/turf/target_turf = target + // We can repair pylons, so let us target turfs containing broken pylons. + if(target_turf.contains_dense_objects(user)) + for(var/obj/structure/cult/pylon/pylon in target_turf) + if(pylon.isbroken) + return TRUE + return FALSE + // We can summon pylons in empty turfs. + return TRUE + return FALSE + +/decl/ability/cult/construct/pylon/apply_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) + for(var/obj/structure/cult/pylon/P in get_turf(hit_target)) + if(P.isbroken) + P.repair(user) + return TRUE + . = ..() + +/decl/ability/cult/construct/forcewall/lesser + name = "Force Shield" + desc = "Allows you to pull up a shield to protect yourself and allies from incoming threats" + summon_type = /obj/effect/cult_force_wall + ability_cooldown_time = 30 SECONDS + ability_use_channel = 20 SECONDS + ability_icon_state = "const_juggwall" + prepare_message_3p_str = "$USER$ begins to twist and warp space around $TARGET$, building a wall of force." + prepare_message_1p_str = "You begin the lengthy process of warping local space to form a wall of force." + cast_message_3p_str = "$USER$ completes a wall of force!" + cast_message_1p_str = "You complete a wall of force!" + fail_cast_1p_str = "The screaming fabric of spacetime escapes your grip, and the wall of force vanishes." + +//Code for the Juggernaut construct's forcefield, that seemed like a good place to put it. +/obj/effect/cult_force_wall + desc = "This eerie-looking obstacle seems to have been pulled from another dimension through sheer force." + name = "wall of force" + icon = 'mods/gamemodes/cult/icons/effects.dmi' + icon_state = "m_shield_cult" + light_color = "#b40000" + light_range = 2 + anchored = TRUE + opacity = FALSE + density = TRUE + +/obj/effect/cult_force_wall/Initialize(mapload) + . = ..() + addtimer(CALLBACK(src, PROC_REF(vanish)), 30 SECONDS) + +/obj/effect/cult_force_wall/proc/vanish() + density = FALSE + icon_state = "m_shield_cult_vanish" + sleep(12) + if(!QDELETED(src)) + qdel(src) diff --git a/mods/gamemodes/cult/abilities/harvest.dm b/mods/gamemodes/cult/abilities/harvest.dm new file mode 100644 index 000000000000..49569d6a25ef --- /dev/null +++ b/mods/gamemodes/cult/abilities/harvest.dm @@ -0,0 +1,41 @@ +/decl/ability/cult/construct/harvest + name = "Harvest" + desc = "Back to where I come from, and you're coming with me." + ability_cooldown_time = 20 SECONDS + ability_use_channel = 10 SECONDS + overlay_icon_state = "rune_teleport" + overlay_lifespan = 0 + ability_icon_state = "const_harvest" + prepare_message_3p_str = "Space around $USER$ begins to bubble and decay as a terrible vista begins to intrude..." + prepare_message_1p_str = "You bore through space and time, seeking the essence of the Geometer of Blood." + fail_cast_1p_str = "Reality reasserts itself, preventing your return to Nar-Sie." + target_selector = /decl/ability_targeting/living_mob + +/decl/ability/cult/construct/harvest/can_use_ability(mob/user, list/metadata, silent) + . = ..() + if(.) + var/destination + for(var/obj/effect/narsie/N in global.narsie_list) + destination = N.loc + break + if(!destination) + to_chat(user, SPAN_DANGER("You cannot sense the Geometer of Blood!")) + return FALSE + +/decl/ability/cult/construct/harvest/apply_effect(mob/user, atom/hit_target, list/metadata, obj/item/projectile/ability/projectile) + ..() + var/destination = null + for(var/obj/effect/narsie/N in global.narsie_list) + destination = N.loc + break + if(!destination) + to_chat(user, SPAN_DANGER("You cannot sense the Geometer of Blood!")) + return + if(ismob(hit_target) && hit_target != user) + var/mob/living/victim = hit_target + to_chat(user, SPAN_SINISTER("You warp back to Nar-Sie along with your prey.")) + to_chat(victim, SPAN_SINISTER("You are wrenched through time and space and thrown into chaos!")) + victim.dropInto(destination) + else + to_chat(user, SPAN_SINISTER("You warp back to Nar-Sie.")) + user.dropInto(destination) diff --git a/mods/gamemodes/cult/abilities/shade.dm b/mods/gamemodes/cult/abilities/shade.dm new file mode 100644 index 000000000000..5fab626d14d6 --- /dev/null +++ b/mods/gamemodes/cult/abilities/shade.dm @@ -0,0 +1 @@ +/decl/ability/cult/construct/shift \ No newline at end of file diff --git a/mods/gamemodes/cult/flooring.dm b/mods/gamemodes/cult/flooring.dm index a92973b1077b..71aff2a3ff30 100644 --- a/mods/gamemodes/cult/flooring.dm +++ b/mods/gamemodes/cult/flooring.dm @@ -7,6 +7,6 @@ turf_flags = TURF_ACID_IMMUNE | TURF_REMOVE_WRENCH can_paint = null -/decl/flooring/reinforced/cult/on_remove() +/decl/flooring/reinforced/cult/on_flooring_remove(turf/removing_from) var/decl/special_role/cultist/cult = GET_DECL(/decl/special_role/cultist) cult.remove_cultiness(CULTINESS_PER_TURF) diff --git a/mods/gamemodes/cult/hell_universe.dm b/mods/gamemodes/cult/hell_universe.dm index c5e5ad0adf02..5133b72ba09a 100644 --- a/mods/gamemodes/cult/hell_universe.dm +++ b/mods/gamemodes/cult/hell_universe.dm @@ -40,9 +40,3 @@ In short: for(var/mob/living/simple_animal/M in SSmobs.mob_list) if(M && !M.client) M.set_stat(DEAD) - -// Disable Narsie when we enter other (non-hell) universe states -/datum/universal_state/supermatter_cascade/OnEnter() - // Disable Nar-Sie. - var/decl/special_role/cultist/cult = GET_DECL(/decl/special_role/cultist) - cult.allow_narsie = 0 \ No newline at end of file diff --git a/mods/gamemodes/cult/icons/abilities.dmi b/mods/gamemodes/cult/icons/abilities.dmi new file mode 100644 index 000000000000..f1d5d8bc121c Binary files /dev/null and b/mods/gamemodes/cult/icons/abilities.dmi differ diff --git a/mods/gamemodes/cult/icons/ability_item.dmi b/mods/gamemodes/cult/icons/ability_item.dmi new file mode 100644 index 000000000000..e22793f4f6bd Binary files /dev/null and b/mods/gamemodes/cult/icons/ability_item.dmi differ diff --git a/mods/gamemodes/cult/icons/effects.dmi b/mods/gamemodes/cult/icons/effects.dmi new file mode 100644 index 000000000000..9e2389414543 Binary files /dev/null and b/mods/gamemodes/cult/icons/effects.dmi differ diff --git a/mods/gamemodes/cult/icons/forcewall.dmi b/mods/gamemodes/cult/icons/forcewall.dmi new file mode 100644 index 000000000000..04b8560cdac3 Binary files /dev/null and b/mods/gamemodes/cult/icons/forcewall.dmi differ diff --git a/icons/effects/uristrunes.dmi b/mods/gamemodes/cult/icons/runes.dmi similarity index 100% rename from icons/effects/uristrunes.dmi rename to mods/gamemodes/cult/icons/runes.dmi diff --git a/mods/gamemodes/cult/mobs/constructs/constructs.dm b/mods/gamemodes/cult/mobs/constructs/constructs.dm index 1f10369a6941..1eb37f6980bd 100644 --- a/mods/gamemodes/cult/mobs/constructs/constructs.dm +++ b/mods/gamemodes/cult/mobs/constructs/constructs.dm @@ -5,7 +5,6 @@ speak_emote = list("hisses") base_animal_type = /mob/living/simple_animal/construct base_movement_delay = -1 - response_help_1p = "You think better of touching $TARGET$." response_help_3p = "$USER$ thinks better of touching $TARGET$." response_disarm = "flails at" @@ -31,7 +30,7 @@ z_flags = ZMM_MANGLE_PLANES glowing_eyes = TRUE ai = /datum/mob_controller/aggressive/construct - var/list/construct_spells = list() + var/list/construct_spells /datum/mob_controller/aggressive/construct emote_speech = list("Hsssssssszsht.", "Hsssssssss...", "Tcshsssssssszht!") @@ -54,7 +53,7 @@ add_language(/decl/language/cultcommon) add_language(/decl/language/cult) for(var/spell in construct_spells) - src.add_spell(new spell, "const_spell_ready") + add_ability(spell) set_light(1.5, -2, COLOR_WHITE) update_icon() @@ -107,7 +106,9 @@ environment_smash = 2 status_flags = 0 resistance = 10 - construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser) + construct_spells = list( + /decl/ability/cult/construct/forcewall/lesser + ) hud_used = /datum/hud/construct/juggernaut base_movement_delay = 2 ai = /datum/mob_controller/aggressive/construct_armoured @@ -163,7 +164,9 @@ natural_weapon = /obj/item/natural_weapon/wraith environment_smash = 1 see_in_dark = 7 - construct_spells = list(/spell/targeted/ethereal_jaunt/shift) + construct_spells = list( + /decl/ability/cult/construct/shift + ) hud_used = /datum/hud/construct/wraith /obj/item/natural_weapon/wraith @@ -194,11 +197,11 @@ natural_weapon = /obj/item/natural_weapon/cult_builder environment_smash = 1 construct_spells = list( - /spell/aoe_turf/conjure/construct/lesser, - /spell/aoe_turf/conjure/wall, - /spell/aoe_turf/conjure/floor, - /spell/aoe_turf/conjure/soulstone, - /spell/aoe_turf/conjure/pylon + /decl/ability/cult/construct/lesser, + /decl/ability/cult/construct/wall, + /decl/ability/cult/construct/floor, + /decl/ability/cult/construct/soulstone, + /decl/ability/cult/construct/pylon ) hud_used = /datum/hud/construct/artificer base_movement_delay = 0 @@ -228,7 +231,9 @@ natural_weapon = /obj/item/natural_weapon/juggernaut/behemoth environment_smash = 2 resistance = 10 - construct_spells = list(/spell/aoe_turf/conjure/forcewall/lesser) + construct_spells = list( + /decl/ability/cult/construct/lesser + ) hud_used = /datum/hud/construct/juggernaut base_movement_delay = 2 ai = /datum/mob_controller/aggressive/construct_armoured @@ -249,7 +254,7 @@ see_in_dark = 7 hud_used = /datum/hud/construct/harvester construct_spells = list( - /spell/targeted/harvest + /decl/ability/cult/construct/harvest ) /obj/item/natural_weapon/harvester @@ -264,14 +269,14 @@ /mob/living/simple_animal/construct/handle_regular_status_updates() . = ..() if(.) - silence_spells(purge) + disable_abilities(purge) /mob/living/simple_animal/construct/handle_regular_hud_updates() . = ..() if(.) if(fire) fire.icon_state = "fire[!!GET_HUD_ALERT(src, /decl/hud_element/condition/fire)]" - silence_spells(purge) + disable_abilities(purge) if(healths) switch(current_health) if(250 to INFINITY) healths.icon_state = "health0" diff --git a/mods/gamemodes/cult/mobs/constructs/soulstone.dm b/mods/gamemodes/cult/mobs/constructs/soulstone.dm index a6e8d693c3b9..b5a8f6f09485 100644 --- a/mods/gamemodes/cult/mobs/constructs/soulstone.dm +++ b/mods/gamemodes/cult/mobs/constructs/soulstone.dm @@ -107,6 +107,33 @@ full = f update_icon() +// Soulstone synthesis recipe. +/decl/chemical_reaction/synthesis/soulstone + name = "Soulstone" + result = null + required_reagents = list(/decl/material/liquid/blood = 15, /decl/material/liquid/crystal_agent = 1) + result_amount = 1 + hidden_from_codex = TRUE // This shouldn't show up in search. Maybe it should be linked in a 'guide to cult' or something? + +/decl/chemical_reaction/synthesis/soulstone/send_data(datum/reagents/holder, reaction_limit) + return REAGENT_DATA(holder, /decl/material/liquid/blood) // allow on_reaction to get donor data + +/// Whether or not the reaction should produce a soulstone or a normal crystal. +/// The donor mob parameter may either be /mob/living or null. +/decl/chemical_reaction/synthesis/soulstone/proc/donor_is_magic(mob/living/donor) + return FALSE // By default, no one is magic! This is for modpacks to override. + +/decl/chemical_reaction/synthesis/soulstone/on_reaction(datum/reagents/holder, created_volume, list/reaction_data) + var/location = get_turf(holder.get_reaction_loc(chemical_reaction_flags)) + var/weakref/donor_ref = LAZYACCESS(reaction_data, DATA_BLOOD_DONOR) + if(donor_is_magic(donor_ref?.resolve())) + for(var/i = 1, i <= created_volume, i++) + new /obj/item/soulstone(location) + else // waste it and produce useless crystal shards + for(var/i = 1, i <= created_volume*2, i++) + new /obj/item/shard(location, /decl/material/solid/gemstone/crystal) + +// Construct shells. These accept soulstones. /obj/structure/constructshell name = "empty shell" icon = 'icons/obj/structures/construct.dmi' diff --git a/mods/gamemodes/cult/overrides.dm b/mods/gamemodes/cult/overrides.dm index 2077c9f0b1e1..2d822d252c77 100644 --- a/mods/gamemodes/cult/overrides.dm +++ b/mods/gamemodes/cult/overrides.dm @@ -15,6 +15,7 @@ playsound(src, 'sound/effects/ghost2.ogg', 10, 5) /datum/trader/ship/clothingshop/hatglovesaccessories/New() + ..() possible_trading_items[/obj/item/clothing/head/culthood] = TRADER_BLACKLIST_ALL /mob/living/silicon/ai @@ -47,9 +48,9 @@ /mob/living/simple_animal/hostile/revenant/cult/on_defilement() return -/obj/item/mop/Initialize() +/obj/item/mop/populate_moppable_types() . = ..() - moppable_types += /obj/effect/rune + moppable_types |= /obj/effect/rune /obj/effect/gateway/active/can_transform(mob/victim) if(iscultist(victim)) diff --git a/mods/gamemodes/cult/runes.dm b/mods/gamemodes/cult/runes.dm index 161d225a6481..6724fbae270b 100644 --- a/mods/gamemodes/cult/runes.dm +++ b/mods/gamemodes/cult/runes.dm @@ -2,7 +2,7 @@ name = "rune" desc = "A strange collection of symbols drawn in blood." anchored = TRUE - icon = 'icons/effects/uristrunes.dmi' + icon = 'mods/gamemodes/cult/icons/runes.dmi' icon_state = "blank" layer = RUNE_LAYER @@ -24,7 +24,7 @@ if(cult.rune_strokes[type]) var/list/f = cult.rune_strokes[type] for(var/i in f) - var/image/t = image('icons/effects/uristrunes.dmi', "rune-[i]") + var/image/t = image(icon, "rune-[i]") overlays += t else var/list/q = list(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) @@ -33,7 +33,7 @@ var/j = pick(q) f += j q -= f - var/image/t = image('icons/effects/uristrunes.dmi', "rune-[j]") + var/image/t = image(icon, "rune-[j]") overlays += t cult.rune_strokes[type] = f.Copy() color = bcolor @@ -480,7 +480,6 @@ var/list/mob/living/casters = get_cultists() if(casters.len < 3) break - //T.turf_animation('icons/effects/effects.dmi', "rune_sac") victim.set_fire_intensity(max(2, victim.get_fire_intensity())) victim.ignite_fire() var/dam_amt = 2 + length(casters) diff --git a/mods/gamemodes/cult/spells/construct.dm b/mods/gamemodes/cult/spells/construct.dm deleted file mode 100644 index 05c35c46785d..000000000000 --- a/mods/gamemodes/cult/spells/construct.dm +++ /dev/null @@ -1,122 +0,0 @@ -//////////////////////////////Construct Spells///////////////////////// - -/spell/aoe_turf/conjure/construct - name = "Artificer" - desc = "This spell conjures a construct which may be controlled by Shades." - - school = "conjuration" - charge_max = 600 - spell_flags = 0 - invocation = "none" - invocation_type = SpI_NONE - range = 0 - - summon_type = list(/obj/structure/constructshell) - - hud_state = "artificer" - -/spell/aoe_turf/conjure/construct/lesser - charge_max = 1800 - summon_type = list(/obj/structure/constructshell/cult) - hud_state = "const_shell" - override_base = "const" - -/spell/aoe_turf/conjure/floor - name = "Floor Construction" - desc = "This spell constructs a cult floor" - - charge_max = 20 - spell_flags = Z2NOCAST | CONSTRUCT_CHECK - invocation = "none" - invocation_type = SpI_NONE - range = 0 - summon_type = list(/turf/floor/cult) - - hud_state = "const_floor" - -/spell/aoe_turf/conjure/wall - name = "Lesser Construction" - desc = "This spell constructs a cult wall" - - charge_max = 100 - spell_flags = Z2NOCAST | CONSTRUCT_CHECK - invocation = "none" - invocation_type = SpI_NONE - range = 0 - summon_type = list(/turf/wall/cult) - - hud_state = "const_wall" - -/spell/aoe_turf/conjure/wall/reinforced - name = "Greater Construction" - desc = "This spell constructs a reinforced metal wall" - - charge_max = 300 - spell_flags = Z2NOCAST - invocation = "none" - invocation_type = SpI_NONE - range = 0 - cast_delay = 50 - - summon_type = list(/turf/wall/r_wall) - -/spell/aoe_turf/conjure/soulstone - name = "Summon Soulstone" - desc = "This spell reaches into Nar-Sie's realm, summoning one of the legendary fragments across time and space" - - charge_max = 3000 - spell_flags = 0 - invocation = "none" - invocation_type = SpI_NONE - range = 0 - - summon_type = list(/obj/item/soulstone) - - hud_state = "const_stone" - override_base = "const" - -/spell/aoe_turf/conjure/pylon - name = "Red Pylon" - desc = "This spell conjures a fragile crystal from Nar-Sie's realm. Makes for a convenient light source." - - charge_max = 200 - spell_flags = CONSTRUCT_CHECK - invocation = "none" - invocation_type = SpI_NONE - range = 0 - - summon_type = list(/obj/structure/cult/pylon) - - hud_state = "const_pylon" - -/spell/aoe_turf/conjure/pylon/cast(list/targets, mob/user) - ..() - var/turf/spawn_place = pick(targets) - for(var/obj/structure/cult/pylon/P in spawn_place.contents) - if(P.isbroken) - P.repair(user) - continue - return - -/spell/aoe_turf/conjure/forcewall/lesser - name = "Force Shield" - desc = "Allows you to pull up a shield to protect yourself and allies from incoming threats" - - charge_max = 300 - spell_flags = 0 - invocation = "none" - invocation_type = SpI_NONE - range = 0 - summon_type = list(/obj/effect/forcefield/cult) - duration = 200 - - hud_state = "const_juggwall" - -//Code for the Juggernaut construct's forcefield, that seemed like a good place to put it. -/obj/effect/forcefield/cult - desc = "That eerie looking obstacle seems to have been pulled from another dimension through sheer force." - name = "Juggerwall" - icon = 'icons/effects/effects.dmi' - icon_state = "m_shield_cult" - light_color = "#b40000" - light_range = 2 \ No newline at end of file diff --git a/mods/gamemodes/cult/spells/harvest.dm b/mods/gamemodes/cult/spells/harvest.dm deleted file mode 100644 index 41854b772bc1..000000000000 --- a/mods/gamemodes/cult/spells/harvest.dm +++ /dev/null @@ -1,37 +0,0 @@ -/spell/targeted/harvest - name = "Harvest" - desc = "Back to where I come from, and you're coming with me." - - school = "transmutation" - charge_max = 200 - spell_flags = Z2NOCAST | CONSTRUCT_CHECK | INCLUDEUSER - invocation = "" - invocation_type = SpI_NONE - range = 0 - max_targets = 0 - - overlay = 1 - overlay_icon = 'icons/effects/effects.dmi' - overlay_icon_state = "rune_teleport" - overlay_lifespan = 0 - - hud_state = "const_harvest" - -/spell/targeted/harvest/cast(list/targets, mob/user)//because harvest is already a proc - ..() - - var/destination = null - for(var/obj/effect/narsie/N in global.narsie_list) - destination = N.loc - break - if(destination) - var/prey = 0 - for(var/mob/living/M in targets) - if(!findNullRod(M)) - M.forceMove(destination) - if(M != user) - prey = 1 - to_chat(user, "You warp back to Nar-Sie[prey ? " along with your prey":""].") - else - to_chat(user, "...something's wrong!")//There shouldn't be an instance of Harvesters when Nar-Sie isn't in the world. - diff --git a/mods/gamemodes/cult/structures.dm b/mods/gamemodes/cult/structures.dm index 51db7add6035..26eec8bb2175 100644 --- a/mods/gamemodes/cult/structures.dm +++ b/mods/gamemodes/cult/structures.dm @@ -13,10 +13,10 @@ desc = "A floating crystal that hums with an unearthly energy." icon = 'icons/obj/structures/pylon.dmi' icon_state = "pylon" - var/isbroken = 0 light_power = 0.5 light_range = 13 light_color = "#3e0000" + var/isbroken = FALSE /obj/structure/cult/pylon/attack_hand(mob/M) SHOULD_CALL_PARENT(FALSE) @@ -42,7 +42,7 @@ ) user.do_attack_animation(src) playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 75, 1) - isbroken = 1 + isbroken = TRUE set_density(0) icon_state = "pylon-broken" set_light(0) @@ -61,10 +61,12 @@ /obj/structure/cult/pylon/proc/repair(mob/user) if(isbroken) to_chat(user, "You repair the pylon.") - isbroken = 0 + isbroken = FALSE set_density(1) icon_state = "pylon" set_light(13, 0.5) + return TRUE + return FALSE /obj/structure/cult/pylon/get_artifact_scan_data() return "Tribal pylon - subject resembles statues/emblems built by cargo cult civilisations to honour energy systems from post-warp civilisations." diff --git a/mods/gamemodes/heist/_heist.dme b/mods/gamemodes/heist/_heist.dme index 57bf5c58b426..de2a67d69d3c 100644 --- a/mods/gamemodes/heist/_heist.dme +++ b/mods/gamemodes/heist/_heist.dme @@ -1,13 +1,5 @@ #ifndef GAMEMODE_PACK_HEIST #define GAMEMODE_PACK_HEIST - -#ifdef MODPACK_VOX -#warn Vox modpack loaded before Heist modpack, compatibility features will be missing. -#endif -#ifdef GAMEMODE_PACK_MIXED -#warn Mixed gamemodes modpack loaded before Heist modpack, Heist combination modes will be missing. -#endif - // BEGIN_INCLUDE #include "_heist.dm" #include "areas.dm" diff --git a/mods/gamemodes/meteor/gamemode.dm b/mods/gamemodes/meteor/gamemode.dm index 10212d20aa99..5836f1ad1547 100644 --- a/mods/gamemodes/meteor/gamemode.dm +++ b/mods/gamemodes/meteor/gamemode.dm @@ -93,8 +93,7 @@ /obj/effect/meteor/irradiated=10, /obj/effect/meteor/golden=10, /obj/effect/meteor/silver=10, - /obj/effect/meteor/flaming=10, - /obj/effect/meteor/supermatter=1 + /obj/effect/meteor/flaming=10 ) // As a bonus, more frequent events. diff --git a/mods/gamemodes/mixed.dm b/mods/gamemodes/mixed.dm new file mode 100644 index 000000000000..f89baef2aa8f --- /dev/null +++ b/mods/gamemodes/mixed.dm @@ -0,0 +1,7 @@ +#ifndef GAMEMODE_PACK_MIXED +#define GAMEMODE_PACK_MIXED +#endif + +// This modpack doesn't actually have anything here, and instead it uses the compatibility patch system to make load order not matter. +/decl/modpack/mixed_modes + name = "Mixed Gamemodes" \ No newline at end of file diff --git a/mods/gamemodes/mixed/_mixed.dm b/mods/gamemodes/mixed/_mixed.dm deleted file mode 100644 index c1c9167d414e..000000000000 --- a/mods/gamemodes/mixed/_mixed.dm +++ /dev/null @@ -1,2 +0,0 @@ -/decl/modpack/mixed_modes - name = "Mixed Gamemodes" \ No newline at end of file diff --git a/mods/gamemodes/mixed/_mixed.dme b/mods/gamemodes/mixed/_mixed.dme deleted file mode 100644 index 6db33d077069..000000000000 --- a/mods/gamemodes/mixed/_mixed.dme +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef GAMEMODE_PACK_MIXED -#define GAMEMODE_PACK_MIXED -// BEGIN_INCLUDE -#include "_mixed.dm" -#if defined(GAMEMODE_PACK_HEIST) // TODO: && defined(GAMEMODE_PACK_MERCENARY) -#include "crossfire.dm" -#endif -#if defined(GAMEMODE_PACK_REVOLUTIONARY) -#include "siege.dm" -#endif -#if defined(GAMEMODE_PACK_REVOLUTIONARY) && defined(GAMEMODE_PACK_CULT) -#include "uprising.dm" -#endif -// END_INCLUDE -#endif \ No newline at end of file diff --git a/mods/mobs/borers/_borers.dme b/mods/mobs/borers/_borers.dme index 380c95f4e87f..7f230fc95363 100644 --- a/mods/mobs/borers/_borers.dme +++ b/mods/mobs/borers/_borers.dme @@ -1,10 +1,5 @@ #ifndef CONTENT_PACK_BORERS #define CONTENT_PACK_BORERS - -#ifdef MODPACK_PSIONICS -#warn Psionics modpack loaded before Borers modpack, compatibility features will be missing. -#endif - // BEGIN_INCLUDE #include "borer.dm" #include "datum\antagonist.dm" diff --git a/mods/mobs/borers/datum/antagonist.dm b/mods/mobs/borers/datum/antagonist.dm index c714ef8e1a1e..423297f09f87 100644 --- a/mods/mobs/borers/datum/antagonist.dm +++ b/mods/mobs/borers/datum/antagonist.dm @@ -7,12 +7,12 @@ welcome_text = "Click a target while on GRAB intent to crawl into their ear and infiltrate their brain. You can only take control temporarily, and at risk of hurting your host, so be clever and careful; your host is encouraged to help you however they can. Talk to your host with Say, and your fellow borers with ,z." antag_indicator = "hudborer" antaghud_indicator = "hudborer" + antag_hud_icon = 'mods/mobs/borers/icons/hud.dmi' faction_name = "Borer Host" faction_descriptor = "Unity" faction_welcome = "You are now host to a cortical borer. Please listen to what they have to say; they're in your head." faction = "borer" - faction_indicator = "hudalien" hard_cap = 5 hard_cap_round = 8 diff --git a/mods/mobs/borers/datum/symbiote.dm b/mods/mobs/borers/datum/symbiote.dm index f6954fa2bf32..bf2f17e93c40 100644 --- a/mods/mobs/borers/datum/symbiote.dm +++ b/mods/mobs/borers/datum/symbiote.dm @@ -21,7 +21,8 @@ var/global/list/symbiote_starting_points = list() minimal_player_age = 14 economic_power = 0 defer_roundstart_spawn = TRUE - hud_icon = "hudblank" + hud_icon_state = "hudblank" + hud_icon = null outfit_type = /decl/outfit/job/symbiote_host create_record = FALSE var/check_whitelist // = "Symbiote" diff --git a/mods/mobs/borers/icons/hud.dmi b/mods/mobs/borers/icons/hud.dmi new file mode 100644 index 000000000000..8e01986fd475 Binary files /dev/null and b/mods/mobs/borers/icons/hud.dmi differ diff --git a/mods/mobs/borers/mob/overrides.dm b/mods/mobs/borers/mob/overrides.dm index 77c9a2c158ec..26b83686f8e6 100644 --- a/mods/mobs/borers/mob/overrides.dm +++ b/mods/mobs/borers/mob/overrides.dm @@ -22,8 +22,10 @@ var/mob/living/simple_animal/borer/B = HAS_BRAIN_WORMS(src) if(B.controlling) var/image/holder = hud_list[STATUS_HUD] + holder.icon = 'mods/mobs/borers/icons/hud.dmi' holder.icon_state = "hudbrainworm" var/image/holder2 = hud_list[STATUS_HUD_OOC] + holder2.icon = 'mods/mobs/borers/icons/hud.dmi' holder2.icon_state = "hudbrainworm" /mob/living/human/say_understands(mob/speaker, decl/language/speaking) diff --git a/mods/pyrelight/undead/undead.dm b/mods/pyrelight/undead/undead.dm index c2d0f90a9d35..d304b7ddefe7 100644 --- a/mods/pyrelight/undead/undead.dm +++ b/mods/pyrelight/undead/undead.dm @@ -23,7 +23,7 @@ put_in_active_hand(new /obj/item/bladed/broadsword(src)) else put_in_active_hand(new /obj/item/bladed/shortsword(src)) - put_in_inactive_hand(new /obj/item/shield/buckler(src)) + put_in_inactive_hand(new /obj/item/shield/crafted/buckler(src)) return if(species_name == SPECIES_KOBALOI) diff --git a/mods/species/ascent/datum/species_bodytypes.dm b/mods/species/ascent/datum/species_bodytypes.dm index 9136d47e269a..87a8462b0f7d 100644 --- a/mods/species/ascent/datum/species_bodytypes.dm +++ b/mods/species/ascent/datum/species_bodytypes.dm @@ -30,6 +30,7 @@ BP_SYSTEM_CONTROLLER = /obj/item/organ/internal/controller ) limb_mapping = list(BP_CHEST = list(BP_CHEST, BP_M_HAND)) + footprints_icon = 'icons/mob/footprints/footprints_snake.dmi' // big tail heat_discomfort_strings = list( "You feel brittle and overheated.", diff --git a/mods/species/ascent/mobs/bodyparts.dm b/mods/species/ascent/mobs/bodyparts.dm index a86a379a15c5..dba73c0e1210 100644 --- a/mods/species/ascent/mobs/bodyparts.dm +++ b/mods/species/ascent/mobs/bodyparts.dm @@ -5,7 +5,7 @@ var/list/existing_webs = list() var/max_webs = 4 var/web_weave_time = 20 SECONDS - var/cooldown + var/organ_cooldown /obj/item/organ/external/groin/insectoid/mantid/gyne max_webs = 8 @@ -20,12 +20,12 @@ /obj/item/organ/external/groin/insectoid/mantid/refresh_action_button() . = ..() if(.) - action.button_icon_state = "weave-web-[cooldown ? "off" : "on"]" + action.button_icon_state = "weave-web-[organ_cooldown ? "off" : "on"]" action.button?.update_icon() /obj/item/organ/external/groin/insectoid/mantid/attack_self(var/mob/user) . = ..() - if(. && !cooldown) + if(. && !organ_cooldown) if(!isturf(owner.loc)) to_chat(owner, SPAN_WARNING("You cannot use this ability in this location.")) @@ -41,7 +41,7 @@ playsound(user, 'mods/species/ascent/sounds/razorweb_hiss.ogg', 70) owner.visible_message(SPAN_WARNING("\The [owner] separates their jaws and begins to weave a web of crystalline filaments...")) - cooldown = TRUE + organ_cooldown = TRUE refresh_action_button() addtimer(CALLBACK(src, PROC_REF(reset_cooldown)), web_weave_time) if(do_after(owner, web_weave_time) && length(existing_webs) < max_webs) @@ -52,27 +52,27 @@ web.owner = owner /obj/item/organ/external/groin/insectoid/mantid/proc/reset_cooldown() - cooldown = FALSE + organ_cooldown = FALSE refresh_action_button() /obj/item/organ/external/head/insectoid/mantid name = "crested head" action_button_name = "Spit Razorweb" default_action_type = /datum/action/item_action/organ/ascent - var/cooldown_time = 2.5 MINUTES - var/cooldown + var/organ_cooldown_time = 2.5 MINUTES + var/organ_cooldown /obj/item/organ/external/head/insectoid/mantid/refresh_action_button() . = ..() if(.) - action.button_icon_state = "shot-web-[cooldown ? "off" : "on"]" + action.button_icon_state = "shot-web-[organ_cooldown ? "off" : "on"]" action.button?.update_icon() /obj/item/organ/external/head/insectoid/mantid/attack_self(var/mob/user) . = ..() if(.) - if(cooldown) + if(organ_cooldown) to_chat(owner, SPAN_WARNING("Your filament channel hasn't refilled yet!")) return @@ -81,12 +81,12 @@ playsound(user, 'mods/species/ascent/sounds/razorweb.ogg', 100) to_chat(owner, SPAN_WARNING("You spit up a wad of razorweb, ready to throw!")) owner.toggle_throw_mode(TRUE) - cooldown = TRUE + organ_cooldown = TRUE refresh_action_button() - addtimer(CALLBACK(src, PROC_REF(reset_cooldown)), cooldown_time) + addtimer(CALLBACK(src, PROC_REF(reset_cooldown)), organ_cooldown_time) else qdel(web) /obj/item/organ/external/head/insectoid/mantid/proc/reset_cooldown() - cooldown = FALSE + organ_cooldown = FALSE refresh_action_button() diff --git a/mods/species/ascent/mobs/nymph/nymph_inventory.dm b/mods/species/ascent/mobs/nymph/nymph_inventory.dm index 12396419807c..e79adb9931d0 100644 --- a/mods/species/ascent/mobs/nymph/nymph_inventory.dm +++ b/mods/species/ascent/mobs/nymph/nymph_inventory.dm @@ -1,13 +1,8 @@ -/mob/living/simple_animal/alien/kharmaan/proc/contains_crystals(var/obj/item/W) - for(var/mat in W.matter) - if(mat == /decl/material/solid/sand) - . += W.matter[mat] - else if(mat == /decl/material/solid/gemstone/crystal) - . += W.matter[mat] - else if(mat == /decl/material/solid/quartz) - . += W.matter[mat] - else if(mat == /decl/material/solid/glass) - . += W.matter[mat] +/mob/living/simple_animal/alien/kharmaan/proc/contains_crystals(var/obj/item/prop) + . += prop.matter[/decl/material/solid/sand] + . += prop.matter[/decl/material/solid/gemstone/crystal] + . += prop.matter[/decl/material/solid/quartz] + . += prop.matter[/decl/material/solid/glass] /datum/inventory_slot/gripper/mouth/nymph/ascent/equipped(var/mob/living/user, var/obj/item/prop, var/redraw_mob = TRUE, var/delete_old_item = TRUE) var/mob/living/simple_animal/alien/kharmaan/nimp = user diff --git a/mods/species/bayliens/_bayliens.dm b/mods/species/bayliens/_bayliens.dm index 68d625b481ff..80febefc65ea 100644 --- a/mods/species/bayliens/_bayliens.dm +++ b/mods/species/bayliens/_bayliens.dm @@ -10,6 +10,14 @@ /decl/modpack/bayliens name = "Baystation 12 Aliens" + tabloid_headlines = list( + "SHOCKING FIGURES REVEAL MORE TEENS DIE TO UNATHI HONOUR DUELS THAN GUN VIOLENCE", + "LOCAL UNATHI SYMPATHIZER: 'I really think you should stop with these spacebaiting articles.'", + "DO UNATHI SYMPATHIZERS HATE THE HUMAN RACE?", + "TENTACLES OF TERROR: SKRELL BLACK OPS SEIGE NYX NAVAL DEPOT. SHOCKING PHOTOGRAPHS INSIDE!", + "LOCAL MAN HAS SEIZURE AFTER SAYING SKRELLIAN NAME; FORCED ASSIMILATION SOON?", + "TAJARANS: CUTE AND CUDDLY, OR INFILTRATING THE GOVERNMENT? FIND OUT MORE INSIDE" + ) /decl/modpack/bayliens/pre_initialize() ..() diff --git a/mods/species/bayliens/tajaran/datum/species_bodytypes.dm b/mods/species/bayliens/tajaran/datum/species_bodytypes.dm index 225bf5bc86e7..bd161dac4369 100644 --- a/mods/species/bayliens/tajaran/datum/species_bodytypes.dm +++ b/mods/species/bayliens/tajaran/datum/species_bodytypes.dm @@ -16,6 +16,7 @@ base_eye_color = "#00aa00" nail_noun = "claws" uid = "bodytype_feline" + footprints_icon = 'icons/mob/footprints/footprints_paw.dmi' age_descriptor = /datum/appearance_descriptor/age/tajaran diff --git a/mods/species/bayliens/unathi/datum/species_bodytypes.dm b/mods/species/bayliens/unathi/datum/species_bodytypes.dm index 31e9a0584382..12b4de66522e 100644 --- a/mods/species/bayliens/unathi/datum/species_bodytypes.dm +++ b/mods/species/bayliens/unathi/datum/species_bodytypes.dm @@ -18,6 +18,7 @@ eye_flash_mod = 1.2 nail_noun = "claws" uid = "bodytype_unathi_fem" + footprints_icon = 'mods/species/bayliens/unathi/icons/footprints.dmi' age_descriptor = /datum/appearance_descriptor/age/lizard diff --git a/mods/species/bayliens/unathi/icons/footprints.dmi b/mods/species/bayliens/unathi/icons/footprints.dmi new file mode 100644 index 000000000000..fe21767b108c Binary files /dev/null and b/mods/species/bayliens/unathi/icons/footprints.dmi differ diff --git a/mods/species/drakes/_drakes.dme b/mods/species/drakes/_drakes.dme index 1143d6a510ee..025f1c54c518 100644 --- a/mods/species/drakes/_drakes.dme +++ b/mods/species/drakes/_drakes.dme @@ -1,10 +1,5 @@ #ifndef MODPACK_DRAKES #define MODPACK_DRAKES - -#ifdef MODPACK_FANTASY -#warn Fantasy modpack loaded before Drakes modpack, compatibility features will be missing. -#endif - // BEGIN_INCLUDE #include "_drakes.dm" #include "_overrides.dm" diff --git a/mods/species/drakes/drake_abilities.dm b/mods/species/drakes/drake_abilities.dm index 85b589c73f66..fb4d7b0fcabf 100644 --- a/mods/species/drakes/drake_abilities.dm +++ b/mods/species/drakes/drake_abilities.dm @@ -6,9 +6,11 @@ spit_projectile_type = /obj/item/projectile/drake_spit/weak /datum/ability_handler/predator/grafadreka/can_do_ranged_invocation(mob/user, atom/target) - return istype(user) && user.check_intent(I_FLAG_HARM) && !user.incapacitated() && isatom(target) + return ..() || (istype(user) && user.check_intent(I_FLAG_HARM) && !user.incapacitated() && isatom(target)) /datum/ability_handler/predator/grafadreka/do_ranged_invocation(mob/user, atom/target) + if((. = ..())) + return if(world.time < next_spit) to_chat(user, SPAN_WARNING("You cannot spit again so soon!")) return TRUE diff --git a/mods/species/drakes/sifsap.dm b/mods/species/drakes/sifsap.dm index f0fd4f179efe..5334839e70fa 100644 --- a/mods/species/drakes/sifsap.dm +++ b/mods/species/drakes/sifsap.dm @@ -44,9 +44,9 @@ M.add_chemical_effect(CE_PULSE, -1) return ..() -/decl/material/liquid/sifsap/affect_overdose(mob/living/M, total_dose) - if(M.has_trait(/decl/trait/sivian_biochemistry)) +/decl/material/liquid/sifsap/affect_overdose(mob/living/victim, total_dose) + if(victim.has_trait(/decl/trait/sivian_biochemistry)) return - M.apply_damage(1, IRRADIATE) - SET_STATUS_MAX(M, 5, STAT_DROWSY) + victim.apply_damage(1, IRRADIATE) + SET_STATUS_MAX(victim, 5, STAT_DROWSY) return ..() diff --git a/mods/species/drakes/species.dm b/mods/species/drakes/species.dm index 970ecc2f04a3..cd57051614f9 100644 --- a/mods/species/drakes/species.dm +++ b/mods/species/drakes/species.dm @@ -43,16 +43,11 @@ traits = list( /decl/trait/sivian_biochemistry = TRAIT_LEVEL_EXISTS ) + move_trail = /obj/effect/decal/cleanable/blood/tracks/paw // Drakes must be whitelisted for jobs to be able to join as them, see maps.dm. job_blacklist_by_default = TRUE spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED - character_preview_screen_locs = list( - "1" = "character_preview_map:1,4:36", - "2" = "character_preview_map:1,3:31", - "4" = "character_preview_map:1,2:26", - "8" = "character_preview_map:1,1:21" - ) var/list/adult_pain_emotes_with_pain_level = list( list(/decl/emote/audible/drake_huff, /decl/emote/audible/drake_rattle) = 20 diff --git a/mods/species/drakes/species_bodytypes.dm b/mods/species/drakes/species_bodytypes.dm index dc5afea4ea45..a04b7513377e 100644 --- a/mods/species/drakes/species_bodytypes.dm +++ b/mods/species/drakes/species_bodytypes.dm @@ -46,6 +46,8 @@ antaghud_offset_x = 16 override_organ_types = list(BP_DRAKE_GIZZARD = /obj/item/organ/internal/drake_gizzard) uid = "bodytype_drake" + footprints_icon = 'icons/mob/footprints/footprints_paw.dmi' + additional_emotes = list( /decl/emote/audible/drake_warble, /decl/emote/audible/drake_purr, @@ -94,6 +96,13 @@ /decl/emote/visible/tfist ) + character_preview_screen_locs = list( + "1" = "character_preview_map:1,4:36", + "2" = "character_preview_map:1,3:31", + "4" = "character_preview_map:1,2:26", + "8" = "character_preview_map:1,1:21" + ) + available_mob_postures = list( /decl/posture/standing, /decl/posture/lying/drake, @@ -184,6 +193,7 @@ blood_overlays = 'mods/species/drakes/icons/hatchling_blood.dmi' eye_icon = 'mods/species/drakes/icons/hatchling_eyes.dmi' icon_template = 'icons/mob/human_races/species/template.dmi' + damage_overlays = 'icons/mob/human_races/species/default_damage_overlays.dmi' bodytype_category = BODYTYPE_GRAFADREKA_HATCHLING mob_size = MOB_SIZE_SMALL pixel_offset_x = 0 @@ -203,6 +213,7 @@ /decl/emote/audible/drake_sneeze ) age_descriptor = /datum/appearance_descriptor/age/grafadreka/hatchling + character_preview_screen_locs = null uid = "bodytype_drake_hatchling" /decl/bodytype/quadruped/grafadreka/hatchling/Initialize() diff --git a/mods/species/serpentid/datum/species_bodytypes.dm b/mods/species/serpentid/datum/species_bodytypes.dm index 6c4e562b4510..0bf66ff375fa 100644 --- a/mods/species/serpentid/datum/species_bodytypes.dm +++ b/mods/species/serpentid/datum/species_bodytypes.dm @@ -63,6 +63,7 @@ ARMOR_BIO = ARMOR_BIO_SHIELDED, ARMOR_RAD = 0.5*ARMOR_RAD_MINOR ) + footprints_icon = 'icons/mob/footprints/footprints_snake.dmi' /decl/bodytype/serpentid/Initialize() _equip_adjust = list( diff --git a/mods/species/vox/_vox.dme b/mods/species/vox/_vox.dme index 83d61f50f51f..0e0e635d99b4 100644 --- a/mods/species/vox/_vox.dme +++ b/mods/species/vox/_vox.dme @@ -8,7 +8,6 @@ #include "datum\cultures_vox.dm" #include "datum\descriptors_vox.dm" #include "datum\factions_vox.dm" -#include "datum\heist_compatibility.dm" #include "datum\language.dm" #include "datum\locations_vox.dm" #include "datum\outfits.dm" diff --git a/mods/~compatibility/patches/fantasy.dm b/mods/~compatibility/patches/fantasy.dm new file mode 100644 index 000000000000..c176360672c6 --- /dev/null +++ b/mods/~compatibility/patches/fantasy.dm @@ -0,0 +1,4 @@ +// Override drake lore and names for the fantasy modpack. +#ifdef MODPACK_DRAKES +#include "fantasy/drake_fantasy.dm" +#endif \ No newline at end of file diff --git a/mods/~compatibility/patches/fantasy/drake_fantasy.dm b/mods/~compatibility/patches/fantasy/drake_fantasy.dm new file mode 100644 index 000000000000..70ad5e628e7d --- /dev/null +++ b/mods/~compatibility/patches/fantasy/drake_fantasy.dm @@ -0,0 +1,21 @@ +// Rename grafadreka +/decl/species/grafadreka + name = "Meredrake" + name_plural = "Meredrakes" + description = "Meredrakes, sometimes called mire-drakes, are large reptillian pack predators, widely assumed to be cousins to true dragons. \ + They are commonly found living in caves or burrows bordering grassland or forest, and while they prefer to hunt deer or rabbits, they will sometimes attack travellers if pickings are slim enough. \ + While they are not domesticated, they can be habituated and trained as working animals if captured young enough." + +/decl/sprite_accessory/marking/grafadreka + species_allowed = list("Meredrake") + +/decl/language/grafadreka + desc = "Hiss hiss, feed me rabbits." + +/decl/material/liquid/sifsap + name = "drake spittle" + lore_text = "A complex chemical slurry brewed up in the gullet of meredrakes." + +/obj/aura/sifsap_salve + name = "Drakespittle Salve" + descriptor = "glowing spittle" diff --git a/mods/species/vox/datum/heist_compatibility.dm b/mods/~compatibility/patches/heist_vox.dm similarity index 98% rename from mods/species/vox/datum/heist_compatibility.dm rename to mods/~compatibility/patches/heist_vox.dm index 776057948c06..e37a3416faa6 100644 --- a/mods/species/vox/datum/heist_compatibility.dm +++ b/mods/~compatibility/patches/heist_vox.dm @@ -1,4 +1,3 @@ -#ifdef GAMEMODE_PACK_HEIST /decl/special_role/raider/Initialize() . = ..() LAZYSET(outfits_per_species, SPECIES_VOX, /decl/outfit/vox_raider) @@ -41,4 +40,3 @@ vox.SetName(vox.real_name) var/decl/special_role/raider/raiders = GET_DECL(/decl/special_role/raider) raiders.update_access(vox) -#endif \ No newline at end of file diff --git a/mods/~compatibility/patches/mixed_gamemodes.dm b/mods/~compatibility/patches/mixed_gamemodes.dm new file mode 100644 index 000000000000..c554702eff52 --- /dev/null +++ b/mods/~compatibility/patches/mixed_gamemodes.dm @@ -0,0 +1,12 @@ +// TODO: #ifdef GAMEMODE_PACK_MERCENARY +#if defined(GAMEMODE_PACK_HEIST) +#include "mixed_gamemodes/crossfire.dm" +#endif +#if defined(GAMEMODE_PACK_REVOLUTIONARY) +#include "mixed_gamemodes/siege.dm" +#endif +// #endif + +#if defined(GAMEMODE_PACK_REVOLUTIONARY) && defined(GAMEMODE_PACK_CULT) +#include "mixed_gamemodes/uprising.dm" +#endif \ No newline at end of file diff --git a/mods/gamemodes/mixed/crossfire.dm b/mods/~compatibility/patches/mixed_gamemodes/crossfire.dm similarity index 100% rename from mods/gamemodes/mixed/crossfire.dm rename to mods/~compatibility/patches/mixed_gamemodes/crossfire.dm diff --git a/mods/gamemodes/mixed/siege.dm b/mods/~compatibility/patches/mixed_gamemodes/siege.dm similarity index 100% rename from mods/gamemodes/mixed/siege.dm rename to mods/~compatibility/patches/mixed_gamemodes/siege.dm diff --git a/mods/gamemodes/mixed/uprising.dm b/mods/~compatibility/patches/mixed_gamemodes/uprising.dm similarity index 100% rename from mods/gamemodes/mixed/uprising.dm rename to mods/~compatibility/patches/mixed_gamemodes/uprising.dm diff --git a/mods/~compatibility/patches/psionics.dm b/mods/~compatibility/patches/psionics.dm new file mode 100644 index 000000000000..93473b9271f8 --- /dev/null +++ b/mods/~compatibility/patches/psionics.dm @@ -0,0 +1,13 @@ +// Give borers a paramount rank psi aura, and gives them a ranged psychic attack. +#ifdef CONTENT_PACK_BORERS +#include "psionics/borer_psi.dm" +#endif +// Allows psion blood to be used to create soulstones, +// and lets full soulstones nullify psi and shatter into nullglass. +#ifdef GAMEMODE_PACK_CULT +#include "psionics/cult_psi.dm" +#endif +// Adds psi abilities to the counselor. +#ifdef MODPACK_STANDARD_JOBS +#include "psionics/psi_jobs.dm" +#endif \ No newline at end of file diff --git a/mods/content/psionics/system/psionics/mob/borer_power.dm b/mods/~compatibility/patches/psionics/borer_psi.dm similarity index 97% rename from mods/content/psionics/system/psionics/mob/borer_power.dm rename to mods/~compatibility/patches/psionics/borer_psi.dm index 48f62c8adab6..68c70ec95f78 100644 --- a/mods/content/psionics/system/psionics/mob/borer_power.dm +++ b/mods/~compatibility/patches/psionics/borer_psi.dm @@ -1,4 +1,3 @@ -#ifdef CONTENT_PACK_BORERS /mob/living/simple_animal/borer var/image/aura_image @@ -52,5 +51,4 @@ SET_STATUS_MAX(M, STAT_WEAK, 10) set_ability_cooldown(15 SECONDS) - return TRUE -#endif \ No newline at end of file + return TRUE \ No newline at end of file diff --git a/mods/~compatibility/patches/psionics/cult_psi.dm b/mods/~compatibility/patches/psionics/cult_psi.dm new file mode 100644 index 000000000000..0fa46de32d68 --- /dev/null +++ b/mods/~compatibility/patches/psionics/cult_psi.dm @@ -0,0 +1,18 @@ +// Make psion blood usable for soulstone synthesis. +/decl/chemical_reaction/synthesis/soulstone/donor_is_magic(mob/living/donor) + return ..() || !!donor?.get_ability_handler(/datum/ability_handler/psionics) + +// Make soulstones interact with psionics. +/obj/item/soulstone/disrupts_psionics() + . = !full ? src : FALSE + +/obj/item/soulstone/shatter() + for(var/i=1 to rand(2,5)) + new /obj/item/shard(get_turf(src), full ? /decl/material/nullglass : /decl/material/solid/gemstone/crystal) + . = ..() + +/obj/item/soulstone/withstand_psi_stress(var/stress, var/atom/source) + . = ..(stress, source) + if(. > 0) + . = max(0, . - rand(2,5)) + shatter() \ No newline at end of file diff --git a/mods/~compatibility/patches/psionics/psi_jobs.dm b/mods/~compatibility/patches/psionics/psi_jobs.dm new file mode 100644 index 000000000000..d62d097022f0 --- /dev/null +++ b/mods/~compatibility/patches/psionics/psi_jobs.dm @@ -0,0 +1,6 @@ +/datum/job/standard/counselor/equip_job(var/mob/living/human/H) + if(H.mind.role_alt_title == "Counselor") + psi_faculties = list("[PSI_REDACTION]" = PSI_RANK_OPERANT) + if(H.mind.role_alt_title == "Mentalist") + psi_faculties = list("[PSI_COERCION]" = PSI_RANK_OPERANT) + return ..() \ No newline at end of file diff --git a/mods/~compatibility/patches/supermatter.dm b/mods/~compatibility/patches/supermatter.dm new file mode 100644 index 000000000000..27f6a6f44758 --- /dev/null +++ b/mods/~compatibility/patches/supermatter.dm @@ -0,0 +1,12 @@ +// Add the supermatter monitor to engineering jobs' default software. +#ifdef MODPACK_STANDARD_JOBS +#include "supermatter/supermatter_jobs.dm" +#endif +// Disable Narsie during the supermatter cascade. +#ifdef GAMEMODE_PACK_CULT +#include "supermatter/sm_disable_narsie.dm" +#endif +// Add the supermatter meteor to the meteor gamemode's cataclysmic meteors list. +#ifdef GAMEMODE_PACK_METEOR +#include "supermatter/sm_meteor.dm" +#endif \ No newline at end of file diff --git a/mods/~compatibility/patches/supermatter/sm_disable_narsie.dm b/mods/~compatibility/patches/supermatter/sm_disable_narsie.dm new file mode 100644 index 000000000000..a660384347b4 --- /dev/null +++ b/mods/~compatibility/patches/supermatter/sm_disable_narsie.dm @@ -0,0 +1,4 @@ +// Disable Narsie when a supermatter cascade begins. +/datum/universal_state/supermatter_cascade/OnEnter() + var/decl/special_role/cultist/cult = GET_DECL(/decl/special_role/cultist) + cult.allow_narsie = 0 \ No newline at end of file diff --git a/mods/~compatibility/patches/supermatter/sm_meteor.dm b/mods/~compatibility/patches/supermatter/sm_meteor.dm new file mode 100644 index 000000000000..df383bc3f765 --- /dev/null +++ b/mods/~compatibility/patches/supermatter/sm_meteor.dm @@ -0,0 +1,3 @@ +/decl/game_mode/meteor/Initialize() + . = ..() // No debounce, decls only init once. + meteors_cataclysm[/obj/effect/meteor/destroyer/supermatter] = 1 \ No newline at end of file diff --git a/mods/~compatibility/patches/supermatter/supermatter_jobs.dm b/mods/~compatibility/patches/supermatter/supermatter_jobs.dm new file mode 100644 index 000000000000..2a62b17318ca --- /dev/null +++ b/mods/~compatibility/patches/supermatter/supermatter_jobs.dm @@ -0,0 +1,7 @@ +/datum/job/standard/chief_engineer/New() + ..() + software_on_spawn |= /datum/computer_file/program/supermatter_monitor + +/datum/job/standard/engineer/New() + ..() + software_on_spawn |= /datum/computer_file/program/supermatter_monitor \ No newline at end of file diff --git a/mods/~compatibility/readme.md b/mods/~compatibility/readme.md new file mode 100644 index 000000000000..d422273e7bb4 --- /dev/null +++ b/mods/~compatibility/readme.md @@ -0,0 +1,22 @@ +# Modpack Compatibility System +This folder exists as a way to work around the fact that the previous system for modpack cross-compatibility, define-gating, is sensitive to include order. This resulted in a lot of boilerplate, like having to emit warnings if modpacks were included in the wrong order. This meant that you could also introduce cyclical dependencies, where no matter what it would emit a warning and content would be missing. + +To avoid this issue, we instead include all compatibility patches last, so it is load order agnostic. + +## FAQ +### Why aren't the compatibility files in the modpacks themselves? +I didn't want to edit the modpack include validation script to exclude the compatibility patches from all DMEs. + +### Why is it organised using subfolders? +I didn't like using `#if defined(FOO) && defined(BAR)` and nested `#ifdef`s were hard to follow, so instead I group them by modpack. + +### Is there a general rule for which modpacks get their own folder? +Not really. I just grouped them in roughly the way that would result in the largest existing groupings, and then chose groupings that would make the most sense to expand in the future (fantasy and standard jobs). + +### Do all patches need to be in a subfolder? +No, it's totally fine to just put something in the base patches directory if there's only one patch for either of the mods in that pairing. That said, sometimes it can make sense to add a folder with just one patch if you can foresee future development requiring additional patches in the same category. + +### How do I decide which folder a patch goes in if both modpacks have folders? +I tend to personally go based on whatever it's mostly about; a hypothetical patch renaming and respriting psionics for the fantasy modpack would go in the fantasy folder. Alternatively, you could think of it as going for whichever one is more specific. + +That said, if one has a lot more patches than the other, or if one modpack (take Standard Jobs, for example) is patched by several modpacks that already have folders, it's fine to just go with whatever produces the largest patch subfolders (or gets rid of small/redundant ones). \ No newline at end of file diff --git a/mods/~compatibility/~compatibility.dm b/mods/~compatibility/~compatibility.dm new file mode 100644 index 000000000000..6d3b770558f2 --- /dev/null +++ b/mods/~compatibility/~compatibility.dm @@ -0,0 +1,20 @@ +// Add Vox-specific content for the Heist gamemode (Vox raider outfit, mirror to transform into a Vox as a raider) +#if defined(GAMEMODE_PACK_HEIST) && defined(MODPACK_VOX) +#include "patches/heist_vox.dm" +#endif + +#ifdef MODPACK_PSIONICS +#include "patches/psionics.dm" +#endif + +#ifdef GAMEMODE_PACK_MIXED +#include "patches/mixed_gamemodes.dm" +#endif + +#ifdef MODPACK_FANTASY_SPECIES +#include "patches/fantasy.dm" +#endif + +#ifdef CONTENT_PACK_SUPERMATTER +#include "patches/supermatter.dm" +#endif diff --git a/nebula.dme b/nebula.dme index 9a65b6ccccbe..a5636e8735ab 100644 --- a/nebula.dme +++ b/nebula.dme @@ -192,7 +192,6 @@ #include "code\_onclick\hud\robot.dm" #include "code\_onclick\hud\skybox.dm" #include "code\_onclick\hud\screen\_screen.dm" -#include "code\_onclick\hud\screen\screen_abilities.dm" #include "code\_onclick\hud\screen\screen_action_button.dm" #include "code\_onclick\hud\screen\screen_ai_button.dm" #include "code\_onclick\hud\screen\screen_attack_selector.dm" @@ -211,6 +210,7 @@ #include "code\_onclick\hud\screen\screen_intent.dm" #include "code\_onclick\hud\screen\screen_internal.dm" #include "code\_onclick\hud\screen\screen_inventory.dm" +#include "code\_onclick\hud\screen\screen_inventory_hands.dm" #include "code\_onclick\hud\screen\screen_lighting.dm" #include "code\_onclick\hud\screen\screen_maneuver.dm" #include "code\_onclick\hud\screen\screen_module.dm" @@ -427,8 +427,13 @@ #include "code\datums\extensions\abilities\abilities.dm" #include "code\datums\extensions\abilities\abilities_mob.dm" #include "code\datums\extensions\abilities\abilities_predator.dm" +#include "code\datums\extensions\abilities\ability_button.dm" +#include "code\datums\extensions\abilities\ability_decl.dm" #include "code\datums\extensions\abilities\ability_handler.dm" #include "code\datums\extensions\abilities\ability_item.dm" +#include "code\datums\extensions\abilities\ability_projectile.dm" +#include "code\datums\extensions\abilities\ability_targeting.dm" +#include "code\datums\extensions\abilities\readme.dm" #include "code\datums\extensions\appearance\appearance.dm" #include "code\datums\extensions\appearance\base_icon_state.dm" #include "code\datums\extensions\appearance\cardborg.dm" @@ -740,6 +745,7 @@ #include "code\game\atoms_fires.dm" #include "code\game\atoms_fluids.dm" #include "code\game\atoms_init.dm" +#include "code\game\atoms_interactions.dm" #include "code\game\atoms_layering.dm" #include "code\game\atoms_movable.dm" #include "code\game\atoms_movable_grabs.dm" @@ -782,9 +788,6 @@ #include "code\game\gamemodes\endgame\endgame.dm" #include "code\game\gamemodes\endgame\ftl_jump\ftl_jump.dm" #include "code\game\gamemodes\endgame\nuclear_explosion\nuclear_explosion.dm" -#include "code\game\gamemodes\endgame\supermatter_cascade\cascade_blob.dm" -#include "code\game\gamemodes\endgame\supermatter_cascade\portal.dm" -#include "code\game\gamemodes\endgame\supermatter_cascade\universe.dm" #include "code\game\gamemodes\events\power_failure.dm" #include "code\game\gamemodes\extended\extended.dm" #include "code\game\gamemodes\nuclear\nuclear.dm" @@ -1023,6 +1026,7 @@ #include "code\game\objects\effects\effect_system.dm" #include "code\game\objects\effects\explosion_particles.dm" #include "code\game\objects\effects\fake_fire.dm" +#include "code\game\objects\effects\footprints.dm" #include "code\game\objects\effects\force_portal.dm" #include "code\game\objects\effects\gateway.dm" #include "code\game\objects\effects\gibspawner.dm" @@ -1077,6 +1081,7 @@ #include "code\game\objects\items\bodybag.dm" #include "code\game\objects\items\buttons.dm" #include "code\game\objects\items\candelabra.dm" +#include "code\game\objects\items\chisel.dm" #include "code\game\objects\items\christmas.dm" #include "code\game\objects\items\contraband.dm" #include "code\game\objects\items\crutches.dm" @@ -1085,6 +1090,7 @@ #include "code\game\objects\items\fleece.dm" #include "code\game\objects\items\glassjar.dm" #include "code\game\objects\items\holosign_creator.dm" +#include "code\game\objects\items\horseshoe.dm" #include "code\game\objects\items\hourglass.dm" #include "code\game\objects\items\instruments.dm" #include "code\game\objects\items\latexballoon.dm" @@ -1106,6 +1112,8 @@ #include "code\game\objects\items\trash.dm" #include "code\game\objects\items\umbrella.dm" #include "code\game\objects\items\waterskin.dm" +#include "code\game\objects\items\artifice\chain.dm" +#include "code\game\objects\items\artifice\hook.dm" #include "code\game\objects\items\blades\_blade.dm" #include "code\game\objects\items\blades\axe.dm" #include "code\game\objects\items\blades\axe_fire.dm" @@ -1252,7 +1260,6 @@ #include "code\game\objects\items\weapons\RPD.dm" #include "code\game\objects\items\weapons\RSF.dm" #include "code\game\objects\items\weapons\secrets_disk.dm" -#include "code\game\objects\items\weapons\shields.dm" #include "code\game\objects\items\weapons\soap.dm" #include "code\game\objects\items\weapons\staff.dm" #include "code\game\objects\items\weapons\stunbaton.dm" @@ -1312,7 +1319,6 @@ #include "code\game\objects\items\weapons\grenades\prank_grenades.dm" #include "code\game\objects\items\weapons\grenades\smokebomb.dm" #include "code\game\objects\items\weapons\grenades\spawnergrenade.dm" -#include "code\game\objects\items\weapons\grenades\supermatter.dm" #include "code\game\objects\items\weapons\implants\implant.dm" #include "code\game\objects\items\weapons\implants\implantcase.dm" #include "code\game\objects\items\weapons\implants\implantchair.dm" @@ -1350,6 +1356,12 @@ #include "code\game\objects\items\weapons\melee\energy_projected.dm" #include "code\game\objects\items\weapons\melee\energy_sword.dm" #include "code\game\objects\items\weapons\melee\misc.dm" +#include "code\game\objects\items\weapons\shields\_shield.dm" +#include "code\game\objects\items\weapons\shields\shield_crafted.dm" +#include "code\game\objects\items\weapons\shields\shield_crafted_buckler.dm" +#include "code\game\objects\items\weapons\shields\shield_crafting.dm" +#include "code\game\objects\items\weapons\shields\shield_energy.dm" +#include "code\game\objects\items\weapons\shields\shield_riot.dm" #include "code\game\objects\items\weapons\storage\backpack.dm" #include "code\game\objects\items\weapons\storage\bags.dm" #include "code\game\objects\items\weapons\storage\basket.dm" @@ -1414,6 +1426,8 @@ #include "code\game\objects\structures\__structure.dm" #include "code\game\objects\structures\_structure_construction.dm" #include "code\game\objects\structures\_structure_icon.dm" +#include "code\game\objects\structures\_structure_interactions.dm" +#include "code\game\objects\structures\_structure_lock.dm" #include "code\game\objects\structures\_structure_materials.dm" #include "code\game\objects\structures\ai_decoy.dm" #include "code\game\objects\structures\armor_stand.dm" @@ -1478,8 +1492,8 @@ #include "code\game\objects\structures\showcase.dm" #include "code\game\objects\structures\signs.dm" #include "code\game\objects\structures\skele_stand.dm" +#include "code\game\objects\structures\snowman.dm" #include "code\game\objects\structures\stasis_cage.dm" -#include "code\game\objects\structures\structure_lock.dm" #include "code\game\objects\structures\tables.dm" #include "code\game\objects\structures\tank_dispenser.dm" #include "code\game\objects\structures\target_stake.dm" @@ -1639,6 +1653,7 @@ #include "code\game\verbs\who.dm" #include "code\modules\abstract\_abstract.dm" #include "code\modules\abstract\abstract_exterior_marker.dm" +#include "code\modules\abstract\abstract_fluid_direction.dm" #include "code\modules\abstract\abstract_ramp_sculptor.dm" #include "code\modules\abstract\airlock_helper.dm" #include "code\modules\acting\acting_items.dm" @@ -2208,6 +2223,7 @@ #include "code\modules\codex\entries\weapons.dm" #include "code\modules\crafting\handmade_fancy.dm" #include "code\modules\crafting\handmade_items.dm" +#include "code\modules\crafting\forging\bellows.dm" #include "code\modules\crafting\metalwork\metalwork_items.dm" #include "code\modules\crafting\pottery\pottery_moulds.dm" #include "code\modules\crafting\pottery\pottery_structures.dm" @@ -2879,6 +2895,7 @@ #include "code\modules\mob\living\living_give.dm" #include "code\modules\mob\living\living_grabs.dm" #include "code\modules\mob\living\living_hallucinations.dm" +#include "code\modules\mob\living\living_hud.dm" #include "code\modules\mob\living\living_maneuvers.dm" #include "code\modules\mob\living\living_organs.dm" #include "code\modules\mob\living\living_powers.dm" @@ -3165,7 +3182,6 @@ #include "code\modules\modular_computers\file_system\programs\engineering\rcon_console.dm" #include "code\modules\modular_computers\file_system\programs\engineering\shields_monitor.dm" #include "code\modules\modular_computers\file_system\programs\engineering\shutoff_valve.dm" -#include "code\modules\modular_computers\file_system\programs\engineering\supermatter_monitor.dm" #include "code\modules\modular_computers\file_system\programs\generic\camera.dm" #include "code\modules\modular_computers\file_system\programs\generic\configurator.dm" #include "code\modules\modular_computers\file_system\programs\generic\crew_manifest.dm" @@ -3419,6 +3435,7 @@ #include "code\modules\posture\posture_bodytype.dm" #include "code\modules\posture\posture_mob.dm" #include "code\modules\posture\posture_subtypes.dm" +#include "code\modules\power\admin_setup_engine.dm" #include "code\modules\power\apc.dm" #include "code\modules\power\batteryrack.dm" #include "code\modules\power\breaker_box.dm" @@ -3780,14 +3797,6 @@ #include "code\modules\species\station\human_bodytypes.dm" #include "code\modules\species\station\monkey.dm" #include "code\modules\species\station\monkey_bodytypes.dm" -#include "code\modules\spells\construct_spells.dm" -#include "code\modules\spells\spell_code.dm" -#include "code\modules\spells\spells.dm" -#include "code\modules\spells\aoe_turf\aoe_turf.dm" -#include "code\modules\spells\aoe_turf\conjure\conjure.dm" -#include "code\modules\spells\targeted\ethereal_jaunt.dm" -#include "code\modules\spells\targeted\shift.dm" -#include "code\modules\spells\targeted\targeted.dm" #include "code\modules\sprite_accessories\_accessory.dm" #include "code\modules\sprite_accessories\_accessory_category.dm" #include "code\modules\sprite_accessories\cosmetics\_accessory_cosmetics.dm" @@ -3829,9 +3838,6 @@ #include "code\modules\submaps\submap_job.dm" #include "code\modules\submaps\submap_join.dm" #include "code\modules\submaps\submap_landmark.dm" -#include "code\modules\supermatter\setup_supermatter.dm" -#include "code\modules\supermatter\sm_looping_sound.dm" -#include "code\modules\supermatter\supermatter.dm" #include "code\modules\surgery\__surgery_setup.dm" #include "code\modules\surgery\_surgery.dm" #include "code\modules\surgery\bones.dm" @@ -4103,5 +4109,6 @@ #include "maps\~unit_tests\unit_testing.dm" #include "mods\_modpack.dm" #include "mods\pyrelight\undead\_undead.dm" +#include "mods\~compatibility\~compatibility.dm" #include "~code\global_init.dm" // END_INCLUDE diff --git a/test/check-paths.sh b/test/check-paths.sh index dcf902b9335e..b88c7775cf26 100755 --- a/test/check-paths.sh +++ b/test/check-paths.sh @@ -37,7 +37,7 @@ exactly 1 "world.log<< uses" 'world.log<<|world.log[[:space:]]<<' exactly 18 "<< uses" '(?> uses" '>>(?!>)' -P exactly 0 "incorrect indentations" '^( {4,})' -P -exactly 22 "text2path uses" 'text2path' +exactly 23 "text2path uses" 'text2path' exactly 4 "update_icon() override" '/update_icon\((.*)\)' -P exactly 0 "goto uses" 'goto ' exactly 9 "atom/New uses" '^/(obj|atom|area|mob|turf).*/New\(' diff --git a/tools/ReplicateSaves/replicate_saves.py b/tools/ReplicateSaves/replicate_saves.py index fd97ec57aece..7fb417b13def 100644 --- a/tools/ReplicateSaves/replicate_saves.py +++ b/tools/ReplicateSaves/replicate_saves.py @@ -23,6 +23,18 @@ def main(): print("Cannot find directory '" + mapdir + "', make sure you are running this script from the root repository directory.") return + ckey = None + if len(sys.argv) > 2: + ckey = sys.argv[2] + if ckey is not None: + ckey = ckey.lower() + + singletargetmap = None + if len(sys.argv) > 3: + singletargetmap = sys.argv[3] + if singletargetmap is not None: + singletargetmap = singletargetmap.lower() + # Work out what maps we actually need to replicate to. # This should be updated as map directories change, or the script will break. targetmaps = [] @@ -40,7 +52,7 @@ def main(): if os.path.isdir(dir): targetmap = dir.path targetmap = targetmap.replace(mapdir + os.sep, "") - if targetmap not in ignoremaps and targetmap != mapname: + if (targetmap not in ignoremaps) and (targetmap != mapname) and ((singletargetmap is None) or (singletargetmap == targetmap)): targetmaps.append(targetmap) # Make sure we can actually see the save directory. @@ -62,6 +74,8 @@ def main(): continue if match.group(1) != mapname: continue + if (ckey is not None) and (ckey != root[root.rfind("/")+1:]): + continue savefile = os.path.join(root, file) with open(savefile, "r") as loadedsave: wrote = 0