diff --git a/.github/ISSUE_TEMPLATE/issue-report.md b/.github/ISSUE_TEMPLATE/issue-report.md new file mode 100644 index 00000000000..ea0f0aa4093 --- /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 5c858b868b2..3940d892dd0 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 335eb97ec2a..7e207ad9f5e 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 94c9d41639a..680717a8e9a 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 25f2ed8c213..d6591b17acf 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 5bf9a5b371a..55fbbecd14d 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 f53718da51b..90210911f1e 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 8fa2950b1b9..6a254d2fa03 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 f13491832f4..5ac7ac42bd0 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 10b3ccf93c1..34ee968ab77 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 fc921c67cee..4e891170d7b 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 414458af058..00000000000 --- 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 33bf849cb9c..df79fa29ce4 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 ea27e11ca3e..537d2ccce38 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 6fc95896bfa..bb0965dac40 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 5677d2d93bc..ad9171ed446 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 fdf77245d1c..86bba4206e7 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 4682cc14836..ca75b836812 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 5bacceaeef0..cc4a4835b82 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 00000000000..df578406741 --- /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 203bffc6943..1a66910e8d5 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 e389e554cc5..674882295dd 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 679018fba8d..1b4de10e6e8 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 a6e45820115..5a1a2b796fc 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 008d2b90262..0850498b7f2 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 1dbed7ab122..075995076d4 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 de135d672c0..f3d74569b41 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 58e71e52d0d..28244f810e9 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 3995c524dc4..21e02b0126b 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 b72d0ac2c5f..4879b2d05c4 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 066a3feac92..4fc37d4a828 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 00000000000..5ab2d44e66b --- /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 00000000000..9f271846750 --- /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 8dc7ee1e5de..d215868a4c5 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 98bb2b8d43b..b4838fd4145 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 00000000000..896acba2e95 --- /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 00000000000..52f7ee8166c --- /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 00000000000..b7e17f8d59e --- /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 cb9ad6c9539..1db34888001 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 2a71b7b3579..fb12909997c 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 3c771acd1e4..e7ec3c1645b 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 dd3e0df898f..6356be83f0d 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 e7199504921..dd30cd3b4be 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 2a20f984ebe..c91af43ad7d 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 9c8a341a482..3eb68a3b343 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 be291b8ac25..042a32f12ee 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 64214125565..fcfd2c5fcdc 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 39db47d4dc6..95cf7d39aee 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 d13760956e3..fc3e86a037a 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 00000000000..1f8c07525c1 --- /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 4b0049e92f2..7142d14c382 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 110c09afb82..8cf50ef5bc4 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 6d81b42d639..c1c03164c55 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 e01a6995e1b..3aa8d9d84b6 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 be38f8871ef..e6a2f45c19a 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 f5df1fe5197..06e985a8772 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 aecd5af4e4f..3f92564a8d7 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 23f56f7772c..da49b9b5e9c 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 e61cf6be322..7c35679ef55 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 3462f18f560..d6404088a4c 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 dc389cb9dec..e571411e973 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 b9664324917..721eddb4ad9 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 550e474d0ef..831363ce53e 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 a82e8082510..bf5c3741630 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 b295c6fd71f..65d143b39b3 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 fc4fdc8470d..ccfd9b93b6e 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 5ff19547765..1e7a3685c90 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 870df8fbbf1..9ef315bf787 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 b5d5d29540a..664d7af8c8f 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 e67ac44b059..8c2df8b9f8b 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 00000000000..a8af8a6112d --- /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 4a78d796efd..38cd105e6d0 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 b9efb6e61dc..6467b1d19d5 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 abe58d48fbf..e664024c952 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 00000000000..3a48abad475 --- /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 00000000000..c20c77b1480 --- /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 029557ab3b9..9617f3cbb84 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 d9846e8a1a0..9f1a1da2425 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 1dccd0022d3..bad39f2562c 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 00000000000..8bdcf2ab1a4 --- /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 c58b5bd7ae2..4508758e19d 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 88c1e1195d7..3c6f0868145 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 00000000000..089d3c9cc4b --- /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 b19ef3bf316..aaa799ed5a8 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 fe637a0b0dd..0498af95839 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 44377add2c0..1d9cccaf50b 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 7ff92bf32ad..4b0453f2154 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 70cb57c3f47..e46bd9dddc4 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 ee152b86151..ec806c4132f 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 8ab9f986e6b..00000000000 --- 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 00000000000..6da8605ec6b --- /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 00000000000..5d892688b0a --- /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 00000000000..6d78daef790 --- /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 00000000000..307db9bce88 --- /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 00000000000..4b028ca7931 --- /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 00000000000..378ae85d9f0 --- /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 7667753288a..99614d0fe16 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 499ffb5d858..639d83a1754 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 d85bd453f5c..01481422311 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 faf51ae0c59..5fcafd398ae 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 07845b81c45..397257e0d29 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 1945ad56201..243fe2bd7e8 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 4ccde91270d..a17d209574a 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 a069498e7d8..86a88084bd3 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 00000000000..ac17e0641db --- /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 b28986d5592..73424c45322 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 9e717d53f97..6bfeca7cfe8 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 6df0fd7eb1c..d3aa1f21c39 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 745ad4bea2d..ff698963837 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 03d91b43ce4..768fe81af7f 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 e0fe3055aa7..4da0fe52597 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 66f0afe1785..96c1baf5b0a 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 00000000000..60382df695c --- /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 b14f6db9257..59da1232a7c 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 e1fced7cee8..459216c264a 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 eb6f59bc68f..911413e67e9 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 bb4bf178107..d516cd10eb2 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 8150d0abd34..d30c2228570 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 beebb36b775..9fe4be66e46 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 eb80eae759e..cdedfb75619 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 2b5fa2c5063..a4865eb5fe7 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 9ca61af786e..63d3b2ec93c 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 37ce339b7ec..475573d5773 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 a926312bc8f..0a46fa2d41c 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 57063ec8bd0..89b3fd45535 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 27084c19ecb..caf29c81049 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 6055cdda83d..834b109eea7 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 e8ede4d119e..844b479eaa1 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 d023e3d2ee5..f56777dd1c8 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 3351970e8af..d3cadac07f9 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 40ab4f3b70d..8bde4c7ad24 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 7d0cec0a34f..29ea8eefb0d 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 7566bf7578f..760c4a01f0d 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 00000000000..7dabaa77623 --- /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 546f5753cee..8483aa50faa 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 b93ccd2bde9..aba99df3baf 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 2394d2a8197..afea1d4a6fe 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 6638c344791..dd3f4747940 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 8e30b30b4d7..959b1b0c011 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 f1118e682c9..09d5d1cc8c1 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 a0b05c844cd..156e19f2f39 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 af6100a8d0a..7bb3afd7447 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 76f96bf0866..5a4b8a07540 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 de5797080c4..93221465317 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 ad87174808b..b5c1c2a992a 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 83ceb172a41..97d99ab4f2f 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 1a5885cfac6..0e78ae2e832 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 cff4d996c43..7b1f311ebd7 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 744bcdb7813..b51dfb2f51e 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 74c9fe7e444..05b531f2639 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 281174461bd..81ddc6301dc 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 84d9f8ade84..f368481918f 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 7356c78e404..33a099b4194 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 41714c01f86..dbfaaecf3be 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 98313e2441d..759b6001504 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 a6e680313b6..d94e49bf267 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 6aedbb3edaf..bd4284407d8 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 250c133ae7b..eef73b5c8fa 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 c73e38510fc..824a7c5b553 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 dea74926342..5888d3ec832 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 3486a1c88e1..abdd83bf2d4 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 f9777ed43fa..e2637bf9e73 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 e17ac5d3e66..e8c96d49b72 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 ebe02e59ab7..49d718ebbff 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 f6f9b4a7c00..f5e9ac99fa3 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 4ed96a6c0cf..747a279d691 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 eefcbd251aa..ffdbb675590 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 00000000000..3402f4c2cfa --- /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 c952e9b8171..73adc6e921f 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 d2c910fba7b..4cab4e48465 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 c8169a999c2..5472d992243 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 a5a28c6e6a5..7c481de823a 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 369270b898d..17caba7e0c4 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 8b0781f7d43..eafa6e89d73 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 98d3254f522..00f4f0f41b6 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 9672f23017e..32422a17549 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 7a4dbb20ba6..c3db366ce4b 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 bcd301d8c97..2af8810c19c 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 2b0eec774a6..5091a764f83 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 2a191251fa0..0223e3f3185 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 9916487bd32..b647e3c4a5a 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 b39f3c9da04..73966699606 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 44f481a550c..756507124eb 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 ef3d0259a0d..13f78edf239 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 beab9fe50e0..5ea97d7a585 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 f5884e492a0..fcd1cea0e1e 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 9465db82d30..b463944f3ed 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 840d453ce50..bee76cb91f7 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 9903d7217d3..bd7c4a3fb0f 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 0456bff2302..f0f7beb5e72 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 6a5d7898104..46ab1b85227 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 ebdd06610dd..3d515a3000d 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 e8073b75f4a..980172b26b2 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 79885549cc4..8b584709c4c 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 db486feb277..b8f50f15113 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 b17f238fcb4..4633de8a6ca 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 bbfa9096bfe..ec78c02b460 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 6b76cad038a..3b42ee375e4 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 e9ca35c6c78..efb84cdf8e7 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 1d3448bdfed..f0bc71d7a18 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 34144fe8393..a6b33d5a584 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 72bf68d6732..f2f7448b2d6 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 f76503b97bb..b5fb55b0461 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 3c8eeea0d04..3fc3f1c2537 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 f61ac8e6886..f4090637855 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 386e4b4d60f..100b55bf3e8 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 a31e6788e00..39f3c3a2841 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 1bb84a587db..ebc47ef1202 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 903b1bc8ecb..f0ab7bdc92e 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 78ba364f39a..a9f88a6c596 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 00000000000..5e6b7adfff0 --- /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 8913f7a8190..2afaa16ad4c 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 661787ae356..645b5323448 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 e9920873353..230f370eda2 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 8a060e833c2..259ac5bf9a5 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 87216dc3704..ee0046ef2ae 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 d79de772719..d0b1f9456e3 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 651a88e5b4e..e88d8b13112 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 08ee95501bd..4421aabf243 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 52457ceb078..0ec86995aff 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 be7858c6c04..6571031649c 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 7903631bb68..3bd462aca86 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 03827667a28..512db5f11ba 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 04318afb971..ec19dd3daed 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 39a1a9c5606..b55b2342ed8 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 21c41101077..a934d39d2e3 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 cd0d2ec8927..87cad27fdb3 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 6bb4a4f41b8..1bfc73fb6a2 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 ad7c698d6d8..894b912aff9 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 c726c3ac6a2..1bc6fd711de 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 23e4122b908..284372c00bf 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 0ea98dcadb4..ebd8214d0ff 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 69ee279edba..d1aeb0bdaee 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 2eacd7a03ac..dec71c399ff 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 585f57d0d7e..573c28223f1 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 4ba6ad96090..6e22447ab9c 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 03d8abee4ae..a107c79e810 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 72eb84cc491..5991f75c6c4 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 d25c1d6cbe5..cd40acd76d9 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 92a37e75a1b..02428e20f70 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 b01ab304426..16a2f1f7ab9 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 ac8ebc5d961..2e183472066 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 70b9b4c453d..3622d047f5c 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 7905a718674..89f88cf959a 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 0c3222998ac..f06419b8711 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 712c2d6c2b6..5d816b92448 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 6e18e36decb..eb9bbb76a03 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 7cfeaa96c43..0f91439ab58 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 557ae252b88..027081f7949 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 479a9c8cb45..cf33c5df07d 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 4af1f8aa34c..e5aae900584 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 dd74a49e3d3..78f587767ee 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 6958f2431d2..0527ee14941 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 f6c08c8e565..0488d360f93 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 73cffcc1529..5ff951b477b 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 6482521407e..c1c8ea8295e 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 e48a040231b..f3bc342ac90 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 831cacd48c5..2624c10e818 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 4de22aa0616..d01aa247e4b 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 8534b7ddc7a..d4da8ee5045 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 0f54520856d..464ce437f7c 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 07ad3c6c686..152cb7a6ab5 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 8e241456d22..ff77df0fa33 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 5d5b1f9ba65..7210efedb4c 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 a9f290a0aa6..1560263f996 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 67aee6ead08..cac32152287 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 e1002809b1f..9c78f190ca2 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 aa7ca92f847..44384d64365 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 e3a08e5b873..1e4696e3ffe 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 42a44ac8fa1..468300ba172 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 af54d84cd62..eca5276b785 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 9d36a9a5ae3..e9345200297 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 701d2f1d476..7b8357a1767 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 d96d2b840d7..cc0774431ca 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 6647c2afed2..8ab62f4048f 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 c5fc4192862..55c6be4c47c 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 b9295313707..eb5b3cebf44 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 e743ecf0ab2..fbc2eaa85d6 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 8e530dacaa5..a334f65b6ff 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 8f10b625a3c..a4f85cb3fa7 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 ec529bef717..7827c6ac054 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 b8a02ca07fe..62950dd1d64 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 19c5613ea7e..dca52f041f6 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 bc052960e91..0ece0daefd2 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 57192c726ae..79695861328 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 99ec47811aa..db904892033 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 50c6024ac0b..aee39d39921 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 3b1ad5be042..ab42e686e93 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 46c56514eee..695412409f8 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 a048bb7eac3..6c6cf548fe6 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 9cd81a4c437..c3b4cbd9ff8 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 d8d5d4e5e06..778ed37be45 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 a3e89a44343..99f8553586d 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 82cde0c759b..661bab8cf89 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 5c615ad31b3..32980d3c189 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 0f7a721de80..00000000000 --- 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 8dd91146310..00000000000 --- 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 0c705aff4fc..00000000000 --- 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 bfcf1f4d8f6..00000000000 --- 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 ad550747a7f..00000000000 --- 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 55a0ed83359..00000000000 --- 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 2bcc684939a..00000000000 --- 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 733bbf1e540..00000000000 --- 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 9bc3687a1ae..89d8b2f3871 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 5d7aa85f512..e8e408c7c76 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 d2de61af41b..49535017564 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 bb1c9ee58cd..79e5e26956d 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 e41572bbd63..22e68e9011e 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 ad492eb65ef..ba7a38c2f3d 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 b70f17112e8..242af56502d 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 213d77ff128..813f424e7f1 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 3c003aba22d..58783a20f51 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 858063c9bad..b6b652731f8 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 5cf5cb9dce7..3319864ee2a 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 daa00b874bd..58aeb978adc 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 e0665a0e73f..65ecf2cbcfd 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 00000000000..36462616a45 --- /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 e1966e9bb5a..3642e8ed8f4 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 78c4315424a..5502343f0d5 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 7c5729455bf..28317726409 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 965e319bc4a..7cdf5d1b006 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 00000000000..4e058a3f1bf 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 00000000000..2d9699e82c8 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 00000000000..08fac62a016 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 00000000000..6e913803eb1 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 00000000000..944ed4e175b 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 00000000000..4a2e800cf76 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 ed608471041..00000000000 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 705886a5490..00000000000 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 00000000000..ca7d904bd71 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 00000000000..63e1b630dc0 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 f1d05fa9730..00000000000 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 d574921544d..00000000000 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 3b0b33f8490..00000000000 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 fc26d305f6b..00000000000 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 c5a7e57c522..2e3d66fd059 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 62efd8ca867..02a311ec4e8 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 28264b0635f..05840e72af8 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 8a4875e964f..b8c4a0b80fe 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 d2d055fe753..169c66eefdd 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 3a3115d5b88..fa354873156 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 fc54e68b933..412cab2b32d 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 9a35a9acd27..2cdd0893f6a 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 00000000000..2df7a24c30d 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 00000000000..1f7c93487fd 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 00000000000..fd37369cc08 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 00000000000..ce806127f53 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 00000000000..b576bd3b4df 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 00000000000..6890efd9fa4 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 00000000000..4d78c55da72 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 00000000000..e482039b230 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 6aa6118a743..02f97413e1a 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 5ab217edcd5..64af8d1e078 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 59702d43b99..0f65b990467 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 e11d10d2c13..8511d73937a 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 0ce80198e6b..f8cfa9cbbc5 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 17faaf9413d..b3a61c63a9b 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 d3e9075d704..ee795947c30 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 fe86e824f98..1e768fdd53d 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 00000000000..95d5c71b70f 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 00000000000..602683208c7 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 00000000000..15f6f5f2482 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 00000000000..64d0ded9257 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 00000000000..7a898ac6f09 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 ff53a0e14e0..00000000000 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 00000000000..41372efa755 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 00000000000..03e9bc34a6d 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 00000000000..0d27f07c23e 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 00000000000..94e4563a342 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 00000000000..e4c289ffc0c 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 00000000000..e277e1ba44b 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 dbb7e7db2bc..cc9a43d9971 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 00000000000..a7b0a4e0611 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 00000000000..bcbda6a5144 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 0bf325c1efb..00000000000 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 00000000000..dc83a302239 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 00000000000..9e6031422ef 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 00000000000..c9eea92cfd2 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 00000000000..c209cf5e868 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 00000000000..c174da4bb4d 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 00000000000..bc7af6f5b8c 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 49d879d47d8..b8ebfc01108 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 00000000000..b8d98129369 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 00000000000..07840ff2614 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 00000000000..5899f696f70 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 00000000000..280097c8166 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 23e147992e0..3e7992ed2c9 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 9f210bc1c2d..a89c5ee023d 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 00000000000..01fe4cbfcd4 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 4d3b627143f..34269ce2cd3 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 a1670a3978c..de64aad2f44 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 e3ad5c0c488..28d5cf504c6 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 89dd2f9a079..c2c456e9d50 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 df58cbab4de..bd953735089 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 2490837e993..059f7cec344 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 9fcc6687e4d..f8b0550efc0 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 9372a9368a7..67ca1974ecc 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 322bebbf1d3..e09d2ddc900 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 72c324b5c1d..8275bc4173b 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 df6c7b54782..6ca8b4d8ab4 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 107fa0ae8c9..d5f70fdf957 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 952d808b00e..00000000000 Binary files a/maps/exodus/hud.dmi and /dev/null differ diff --git a/maps/ministation/hud.dmi b/maps/ministation/hud.dmi index d4fed05d840..8a3e91cf3a7 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 3d1601530d6..18024cc2379 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 a823a716095..1a27ff0736d 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 d780f2353d2..a3cb57fbc0a 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 0e91a2d945b..1dd568c8176 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 f2d80cbe65f..7b8e61e4591 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 55ea8e841e2..242c665e7f3 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 1e167615cf8..daa715dddd5 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 88dfa842c03..35b21cdc415 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 5deccebb931..f0257f29891 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 7fd20f4bff7..b087edf407c 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 cbdd8abb538..e5b68a7fe20 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 2ecca91fa60..fca80d6d647 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 92e28630c1f..17bb28b7b9e 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 0a9ca098454..29613596f64 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 b33bf376d84..e31eff6ce28 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 9b7de6659e1..803f9a5e920 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 0fd8dca0685..73c262300a6 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 c8c2fcf8bd1..00000000000 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 638c6ff7bf5..7eb2719f661 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 fc96452d2d1..dc2d59ddcc5 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 b885f19cf3f..3adbafa7443 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 66168daa63f..06a9695d634 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 a4bf84f171d..f2337434fae 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 14b3948c927..00000000000 --- 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 22721f265b8..00000000000 --- 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 39f0722666b..00000000000 --- 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 9f4f963c1ee..00000000000 --- 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 0baea8f75c5..00000000000 --- 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 ee4d7f30849..00000000000 --- 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 19de9faa978..00000000000 --- 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 89ec23e18dc..00000000000 --- 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 de7b5dcfd5f..00000000000 --- 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 3cf4e2edc68..00000000000 --- 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 2d56e5161b3..00000000000 --- 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 e9d719bd211..ac7cc4422dc 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 f491bc953a3..edb03def44a 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 0d124a9841e..3647a632760 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 1938f034a31..62a9c6659c4 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 03b480321b8..bedcf558453 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 c14bb9e5b92..d941587b27d 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 f68f5a6eeb9..1de29f1d0ba 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 8a068ace688..fd28e95fb89 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 2eb597a678c..f7a67396265 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 1a4f81e3fb3..bc596cfeecd 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 32eeb975e2c..739a2948bae 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 61b526624e0..71ba7143cc3 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 c4be5d21c35..36e4d8acdb7 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 673a2e15ef4..4347eed5419 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 81c16e69f7a..0fb1d5d7908 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 2dcfaa8cde5..87b99cb04e9 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 218068362ce..1edda9e8e99 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 532c1e74997..2c9e6b417ef 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 00000000000..9849d6f87d8 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 00000000000..71cfb9e98a0 --- /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 00000000000..c97d04705d0 --- /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 00000000000..57fcd595c5f --- /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 00000000000..60ece589b4a --- /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 00000000000..657ce2c6b26 --- /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 00000000000..cb4da036c7c --- /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 01ac1b5988a..021df578e9b 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 00000000000..158824c417b --- /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 fa4f65d3fd7..6ed42c83589 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 b3c1314f552..2611fe47b34 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 bbd7d2ae036..b86a4adcb0f 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 00000000000..76140bdb759 --- /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 00000000000..894f6f7fb50 --- /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 6e1c6e5ce94..8053ead1e47 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 00000000000..262e1b71d55 --- /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 0d8357987fe..b269d8d4cdd 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 00000000000..4a2130efce2 --- /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 84ac9a1af5e..18e12175274 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 9092fd88ae6..fa58ed18f58 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 df5544cffe1..d52fd095516 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 1bc713de0eb..e859f0dc515 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 7c02c352000..00000000000 --- 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 3d984a0711c..00000000000 --- 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 990edecd13e..0ce5f4cfc18 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 3d850f27cf2..8aa0afca352 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 787d2a59050..ee21afaa907 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 4e8adfa83bd..3d8255b2030 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 cd87e528211..97c5ba41adc 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 5585ac5d802..93c34b82a27 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 c85902acde4..15cc7914742 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 366adb30882..aba8eeb102c 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 cbba09eacef..a17a75892bb 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 00000000000..ccea1d4a211 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 00000000000..6869734493a --- /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 c0782377252..d7abb62e0cd 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 af71d84e536..1ce8eeb39d0 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 40cba546489..84630cb60ba 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 14e68446da0..d1a5517f1c3 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 a7a074efbce..548f9147ea7 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 09751719b28..b7ae8b0036b 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 3a3dfbcd869..23f768d4ac6 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 00000000000..78daa387234 --- /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 00000000000..fb6723cce50 --- /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 00000000000..9664671e836 --- /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 00000000000..c0d5c160fae --- /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 00000000000..5b221ad03d6 --- /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 00000000000..70dd9469abc --- /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 00000000000..1560d1118d2 --- /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 00000000000..5261f06a069 --- /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 08da0af07d6..2c20605a6b1 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 ef04b1069f7..6cd76d14233 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 e9b2d2e40fd..507097a121e 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 00000000000..8230625788a --- /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 4f2758b53e3..b7f3186e666 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 00000000000..e6a622480b6 --- /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 5cb5d84467e..f05b56abdaa 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 00000000000..8b2bf0e175c --- /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 00000000000..e259fa26625 --- /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 00000000000..449ad80fbb9 --- /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 00000000000..b13506cd580 --- /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 00000000000..2d7427f03d3 --- /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 00000000000..ded45374bd9 --- /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 00000000000..18351659e4c --- /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 00000000000..537de7a311c --- /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 00000000000..a1e58097f93 --- /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 00000000000..7d6188ff28f --- /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 00000000000..0c6e6e35b01 --- /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 00000000000..62b385510c8 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 00000000000..6fc781a7ee6 --- /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 00000000000..966556dafbe --- /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 82d4e19aed5..02138255d74 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 00000000000..f346bb73fb4 --- /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 00000000000..60138eaba35 --- /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 00000000000..49569d6a25e --- /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 00000000000..5fab626d14d --- /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 a92973b1077..71aff2a3ff3 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 c5e5ad0adf0..5133b72ba09 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 00000000000..f1d5d8bc121 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 00000000000..e22793f4f6b 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 00000000000..9e238941454 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 00000000000..04b8560cdac 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 1f10369a694..1eb37f6980b 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 a6e8d693c3b..b5a8f6f0948 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 2077c9f0b1e..2d822d252c7 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 161d225a648..6724fbae270 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 05c35c46785..00000000000 --- 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 41854b772bc..00000000000 --- 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 51db7add603..26eec8bb217 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 57bf5c58b42..de2a67d69d3 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 10212d20aa9..5836f1ad154 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 00000000000..f89baef2aa8 --- /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 c1c9167d414..00000000000 --- 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 6db33d07706..00000000000 --- 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 380c95f4e87..7f230fc9536 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 c714ef8e1a1..423297f09f8 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 f6954fa2bf3..bf2f17e93c4 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 00000000000..8e01986fd47 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 77c9a2c158e..26b83686f8e 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/species/ascent/datum/species_bodytypes.dm b/mods/species/ascent/datum/species_bodytypes.dm index 9136d47e269..87a8462b0f7 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 a86a379a15c..dba73c0e121 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 12396419807..e79adb9931d 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 68d625b481f..80febefc65e 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 225bf5bc86e..bd161dac436 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 31e9a058438..12b4de66522 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 00000000000..fe21767b108 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 1143d6a510e..025f1c54c51 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 85b589c73f6..fb4d7b0fcab 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 f0fd4f179ef..5334839e70f 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 970ecc2f04a..cd57051614f 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 dc5afea4ea4..a04b7513377 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 6c4e562b451..0bf66ff375f 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 83d61f50f51..0e0e635d99b 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 00000000000..c176360672c --- /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 00000000000..70ad5e628e7 --- /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 776057948c0..e37a3416faa 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 00000000000..c554702eff5 --- /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 00000000000..93473b9271f --- /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 48f62c8adab..68c70ec95f7 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 00000000000..0fa46de32d6 --- /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 00000000000..d62d097022f --- /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 00000000000..27f6a6f4475 --- /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 00000000000..a660384347b --- /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 00000000000..df383bc3f76 --- /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 00000000000..2a62b17318c --- /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 00000000000..d422273e7bb --- /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 00000000000..6d3b770558f --- /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 9a65b6ccccb..a5636e8735a 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 dcf902b9335..b88c7775cf2 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 fd97ec57aec..7fb417b13de 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