From 65aec78b19591e6468872e4d501023fb7077d4e9 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Sun, 11 Feb 2024 01:12:01 +0000 Subject: [PATCH 01/11] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-5686.yml | 4 ---- html/changelogs/AutoChangeLog-pr-5689.yml | 4 ---- html/changelogs/archive/2024-02.yml | 6 ++++++ 3 files changed, 6 insertions(+), 8 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-5686.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-5689.yml diff --git a/html/changelogs/AutoChangeLog-pr-5686.yml b/html/changelogs/AutoChangeLog-pr-5686.yml deleted file mode 100644 index 886879511c48..000000000000 --- a/html/changelogs/AutoChangeLog-pr-5686.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Drathek" -delete-after: True -changes: - - bugfix: "Fix gardener fruit count not always updating" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-5689.yml b/html/changelogs/AutoChangeLog-pr-5689.yml deleted file mode 100644 index 8aa463f11ae6..000000000000 --- a/html/changelogs/AutoChangeLog-pr-5689.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Vicacrov" -delete-after: True -changes: - - bugfix: "Fixed Warden Praetorians being able to move around the ovipositored Queen with their Retrieve ability." \ No newline at end of file diff --git a/html/changelogs/archive/2024-02.yml b/html/changelogs/archive/2024-02.yml index 03ee5e5c0504..b588f879a491 100644 --- a/html/changelogs/archive/2024-02.yml +++ b/html/changelogs/archive/2024-02.yml @@ -146,3 +146,9 @@ hostile), due to this, UPP comms will always be scrambled at the beginning, no way to tell intentions before meeting. - rscadd: Chem Goon Research Consultant now spawns with reagent scanner goggles. +2024-02-11: + Drathek: + - bugfix: Fix gardener fruit count not always updating + Vicacrov: + - bugfix: Fixed Warden Praetorians being able to move around the ovipositored Queen + with their Retrieve ability. From dde13a9d5fc34a64c407d45ec7ed6cc0e3432f59 Mon Sep 17 00:00:00 2001 From: harryob Date: Mon, 12 Feb 2024 00:35:43 +0000 Subject: [PATCH 02/11] removes dead tor code (#5629) this isn't enabled on the live server, nor would it ever be :cl: server: tor banning functionality is removed /:cl: --- .../configuration/entries/general.dm | 2 - code/game/world.dm | 4 - code/modules/admin/IsBanned.dm | 8 +- code/modules/admin/ToRban.dm | 88 ------------------- code/modules/admin/admin_verbs.dm | 1 - colonialmarines.dme | 1 - config/example/config.txt | 3 - 7 files changed, 1 insertion(+), 106 deletions(-) delete mode 100644 code/modules/admin/ToRban.dm diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm index 385cbcb8d446..eb1b0540fb54 100644 --- a/code/controllers/configuration/entries/general.dm +++ b/code/controllers/configuration/entries/general.dm @@ -491,8 +491,6 @@ This maintains a list of ip addresses that are able to bypass topic filtering. /datum/config_entry/flag/respawn -/datum/config_entry/flag/ToRban - /datum/config_entry/flag/ooc_country_flags /datum/config_entry/flag/record_rounds diff --git a/code/game/world.dm b/code/game/world.dm index f68263412715..627e245bc4c1 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -87,10 +87,6 @@ GLOBAL_LIST_INIT(reboot_sfx, file2list("config/reboot_sfx.txt")) GLOB.obfs_x = rand(-500, 500) //A number between -100 and 100 GLOB.obfs_y = rand(-500, 500) //A number between -100 and 100 - spawn(3000) //so we aren't adding to the round-start lag - if(CONFIG_GET(flag/ToRban)) - ToRban_autoupdate() - // If the server's configured for local testing, get everything set up ASAP. // Shamelessly stolen from the test manager's host_tests() proc if(testing_locally) diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 94f40629fc6a..4a7307b247a5 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -17,6 +17,7 @@ message_admins("Failed Login: [key] - Guests not allowed") return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.") + // wait for database to be ready WAIT_DB_READY if(GLOB.admin_datums[ckey] && (GLOB.admin_datums[ckey].rights & R_MOD)) return ..() @@ -26,13 +27,6 @@ var/datum/entity/player/P = get_player_from_key(ckey) - //check if the IP address is a known TOR node - if(CONFIG_GET(flag/ToRban) && ToRban_isbanned(address)) - log_access("Failed Login: [src] - Banned: ToR") - message_admins("Failed Login: [src] - Banned: ToR") - return list("reason"="Using ToR", "desc"="\nReason: The network you are using to connect has been banned.\nIf you believe this is a mistake, please request help at [CONFIG_GET(string/banappeals)]") - - // wait for database to be ready . = P.check_ban(computer_id, address) if(.) diff --git a/code/modules/admin/ToRban.dm b/code/modules/admin/ToRban.dm deleted file mode 100644 index 549353facfb8..000000000000 --- a/code/modules/admin/ToRban.dm +++ /dev/null @@ -1,88 +0,0 @@ -//By Carnwennan -//fetches an external list and processes it into a list of ip addresses. -//It then stores the processed list into a savefile for later use -#define TORFILE "data/ToR_ban.bdb" -#define TOR_UPDATE_INTERVAL 216000 //~6 hours - -/proc/ToRban_isbanned(ip_address) - var/savefile/F = new(TORFILE) - if(F) - if( ip_address in F.dir ) - return 1 - return 0 - -/proc/ToRban_autoupdate() - var/savefile/F = new(TORFILE) - if(F) - var/last_update - F["last_update"] >> last_update - if((last_update + TOR_UPDATE_INTERVAL) < world.realtime) //we haven't updated for a while - ToRban_update() - return - -/proc/ToRban_update() - spawn(0) - log_misc("Downloading updated ToR data...") - var/http[] = world.Export("https://check.torproject.org/exit-addresses") - - var/list/rawlist = file2list(http["CONTENT"]) - if(rawlist.len) - fdel(TORFILE) - var/savefile/F = new(TORFILE) - for( var/line in rawlist ) - if(!line) continue - if( copytext(line,1,12) == "ExitAddress" ) - var/cleaned = copytext(line,13,length(line)-19) - if(!cleaned) continue - F[cleaned] << 1 - F["last_update"] << world.realtime - log_misc("ToR data updated!") - if(usr) to_chat(usr, "ToRban updated.") - return - log_misc("ToR data update aborted: no data.") - return - -/client/proc/ToRban(task in list("update","toggle","show","remove","remove all","find")) - set name = "ToR Ban Settings" - set category = "Server" - if(!admin_holder) return - switch(task) - if("update") - ToRban_update() - if("toggle") - if(config) - if(CONFIG_GET(flag/ToRban)) - CONFIG_SET(flag/ToRban, FALSE) - message_admins("ToR banning disabled.") - else - CONFIG_SET(flag/ToRban, TRUE) - message_admins("ToR banning enabled.") - if("show") - var/savefile/F = new(TORFILE) - var/dat - if( length(F.dir) ) - for( var/i=1, i<=length(F.dir), i++ ) - dat += "#[i] [F.dir[i]]" - dat = "[dat]
" - else - dat = "No addresses in list." - src << browse(dat,"window=ToRban_show") - if("remove") - var/savefile/F = new(TORFILE) - var/choice = tgui_input_list(src,"Please select an IP address to remove from the ToR banlist:","Remove ToR ban", F.dir) - if(choice) - F.dir.Remove(choice) - to_chat(src, "Address removed") - if("remove all") - to_chat(src, "[TORFILE] was [fdel(TORFILE)?"":"not "]removed.") - if("find") - var/input = input(src,"Please input an IP address to search for:","Find ToR ban",null) as null|text - if(input) - if(ToRban_isbanned(input)) - to_chat(src, "Address is a known ToR address") - else - to_chat(src, "Address is not a known ToR address") - return - -#undef TORFILE -#undef TOR_UPDATE_INTERVAL diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 56002d139599..43b06b6d80bc 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -242,7 +242,6 @@ GLOBAL_LIST_INIT(admin_verbs_possess, list( )) GLOBAL_LIST_INIT(admin_verbs_permissions, list( - /client/proc/ToRban, /client/proc/whitelist_panel, )) diff --git a/colonialmarines.dme b/colonialmarines.dme index 0b39e89042d2..6beec448e4b4 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -1397,7 +1397,6 @@ #include "code\modules\admin\stickyban.dm" #include "code\modules\admin\STUI.dm" #include "code\modules\admin\tag.dm" -#include "code\modules\admin\ToRban.dm" #include "code\modules\admin\medal_panel\medals_panel.dm" #include "code\modules\admin\medal_panel\medals_panel_tgui.dm" #include "code\modules\admin\player_panel\player_action.dm" diff --git a/config/example/config.txt b/config/example/config.txt index 8a976e02a580..f9e0956593a9 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -151,9 +151,6 @@ BANAPPEALS https://cm-ss13.com/viewforum.php?f=76 ##Defines the ticklag for the world. 0.9 is the normal one, 0.5 is smoother. TICKLAG 0.5 -## Uncomment this to ban use of ToR -#TOR_BAN - ## Uncomment this to have country flags pop up in OOC alongside names if the user has the pref turned on (uses IP-API) #OOC_COUNTRY_FLAGS From ee5f6a9d7e663d72d3399f360f9748503067a105 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Mon, 12 Feb 2024 00:45:50 +0000 Subject: [PATCH 03/11] Automatic changelog for PR #5629 [ci skip] --- html/changelogs/AutoChangeLog-pr-5629.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-5629.yml diff --git a/html/changelogs/AutoChangeLog-pr-5629.yml b/html/changelogs/AutoChangeLog-pr-5629.yml new file mode 100644 index 000000000000..c3d38d74f0bb --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5629.yml @@ -0,0 +1,4 @@ +author: "harryob" +delete-after: True +changes: + - server: "tor banning functionality is removed" \ No newline at end of file From ebafd1772d4f1f2d5f5142d16ed2a082d19420f4 Mon Sep 17 00:00:00 2001 From: Staykeu <79605233+Staykeu@users.noreply.github.com> Date: Sun, 11 Feb 2024 19:52:33 -0500 Subject: [PATCH 04/11] Adds One ACCESSORY ONLY Slot for Helmets (#5573) # About the pull request Allows for the insertion of an extra cosmetic item in helmets that subtype the M10. # Explain why it's good for the game Adds more personalization to people who don the helmet. Change is purely cosmetic. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: Stakeyng qol: Lets you put an extra accessory item in your helmet. /:cl: --- code/modules/clothing/head/helmet.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index b5775652d8f6..2e551f65d674 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -380,7 +380,7 @@ GLOBAL_LIST_INIT(allowed_helmet_items, list( var/obj/item/storage/internal/headgear/pockets var/storage_slots = 2 // keep in mind, one slot is reserved for garb items - var/storage_slots_reserved_for_garb = 1 + var/storage_slots_reserved_for_garb = 2 var/storage_max_w_class = SIZE_TINY // can hold tiny items only, EXCEPT for glasses & metal flask. var/storage_max_storage_space = 4 From 34ac6ba3e3ce45be087e7da7f898a3e4c2161f45 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Mon, 12 Feb 2024 01:01:38 +0000 Subject: [PATCH 05/11] Automatic changelog for PR #5573 [ci skip] --- html/changelogs/AutoChangeLog-pr-5573.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-5573.yml diff --git a/html/changelogs/AutoChangeLog-pr-5573.yml b/html/changelogs/AutoChangeLog-pr-5573.yml new file mode 100644 index 000000000000..70597b919bbf --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5573.yml @@ -0,0 +1,4 @@ +author: "Stakeyng" +delete-after: True +changes: + - qol: "Lets you put an extra accessory item in your helmet." \ No newline at end of file From 7f073669922e982a1c2fd468cb490366772a23b1 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Mon, 12 Feb 2024 01:09:38 +0000 Subject: [PATCH 06/11] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-5573.yml | 4 ---- html/changelogs/AutoChangeLog-pr-5629.yml | 4 ---- html/changelogs/archive/2024-02.yml | 5 +++++ 3 files changed, 5 insertions(+), 8 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-5573.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-5629.yml diff --git a/html/changelogs/AutoChangeLog-pr-5573.yml b/html/changelogs/AutoChangeLog-pr-5573.yml deleted file mode 100644 index 70597b919bbf..000000000000 --- a/html/changelogs/AutoChangeLog-pr-5573.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Stakeyng" -delete-after: True -changes: - - qol: "Lets you put an extra accessory item in your helmet." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-5629.yml b/html/changelogs/AutoChangeLog-pr-5629.yml deleted file mode 100644 index c3d38d74f0bb..000000000000 --- a/html/changelogs/AutoChangeLog-pr-5629.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "harryob" -delete-after: True -changes: - - server: "tor banning functionality is removed" \ No newline at end of file diff --git a/html/changelogs/archive/2024-02.yml b/html/changelogs/archive/2024-02.yml index b588f879a491..156a3c6c33be 100644 --- a/html/changelogs/archive/2024-02.yml +++ b/html/changelogs/archive/2024-02.yml @@ -152,3 +152,8 @@ Vicacrov: - bugfix: Fixed Warden Praetorians being able to move around the ovipositored Queen with their Retrieve ability. +2024-02-12: + Stakeyng: + - qol: Lets you put an extra accessory item in your helmet. + harryob: + - server: tor banning functionality is removed From c5c89b89e29e522214ef711d882ae799cbae583b Mon Sep 17 00:00:00 2001 From: Julian56 <117036822+Huffie56@users.noreply.github.com> Date: Mon, 12 Feb 2024 01:57:02 +0100 Subject: [PATCH 07/11] Refactor the file watercloset.dm leaving toilet code in it and moving the rest in their own files. (#5596) # About the pull request # Explain why it's good for the game # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: refactor: refactored watercloset.dm file. /:cl: --------- Co-authored-by: Julien --- code/game/objects/items/toys/toys.dm | 8 + code/game/objects/structures/shower.dm | 222 +++++++++++ code/game/objects/structures/sink.dm | 122 ++++++ code/game/objects/structures/urinal.dm | 22 ++ code/game/objects/structures/watercloset.dm | 393 +------------------- colonialmarines.dme | 3 + 6 files changed, 388 insertions(+), 382 deletions(-) create mode 100644 code/game/objects/structures/shower.dm create mode 100644 code/game/objects/structures/sink.dm create mode 100644 code/game/objects/structures/urinal.dm diff --git a/code/game/objects/items/toys/toys.dm b/code/game/objects/items/toys/toys.dm index 6fa420df35d5..91d8164dcf38 100644 --- a/code/game/objects/items/toys/toys.dm +++ b/code/game/objects/items/toys/toys.dm @@ -396,6 +396,14 @@ src.add_fingerprint(user) addtimer(VARSET_CALLBACK(src, spam_flag, FALSE), 2 SECONDS) +// rubber duck +/obj/item/toy/bikehorn/rubberducky + name = "rubber ducky" + desc = "Rubber ducky you're so fine, you make bathtime lots of fuuun. Rubber ducky I'm awfully fooooond of yooooouuuu~" //thanks doohl + icon = 'icons/obj/structures/props/watercloset.dmi' + icon_state = "rubberducky" + item_state = "rubberducky" + /obj/item/computer3_part name = "computer part" desc = "Holy jesus you donnit now" diff --git a/code/game/objects/structures/shower.dm b/code/game/objects/structures/shower.dm new file mode 100644 index 000000000000..b731a2c0e242 --- /dev/null +++ b/code/game/objects/structures/shower.dm @@ -0,0 +1,222 @@ +/obj/structure/machinery/shower + name = "shower" + desc = "The HS-451. Installed in the 2050s by the Weyland Hygiene Division." + icon = 'icons/obj/structures/props/watercloset.dmi' + icon_state = "shower" + density = FALSE + anchored = TRUE + use_power = USE_POWER_NONE + var/on = 0 + var/obj/effect/mist/mymist = null + /// needs a var so we can make it linger~ + var/ismist = 0 + /// freezing, normal, or boiling + var/watertemp = "normal" + /// true if there is a mob on the shower's loc, this is to ease process() + var/mobpresent = 0 + var/is_washing = 0 + +/obj/structure/machinery/shower/Initialize() + . = ..() + create_reagents(2) + +//add heat controls? when emagged, you can freeze to death in it? + +/obj/effect/mist + name = "mist" + icon = 'icons/obj/structures/props/watercloset.dmi' + icon_state = "mist" + layer = FLY_LAYER + anchored = TRUE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + + +/obj/structure/machinery/shower/attack_hand(mob/M as mob) + on = !on + update_icon() + if(on) + start_processing() + if (M.loc == loc) + wash(M) + check_heat(M) + for (var/atom/movable/G in src.loc) + G.clean_blood() + else + stop_processing() + + +/obj/structure/machinery/shower/attackby(obj/item/I as obj, mob/user as mob) + if(I.type == /obj/item/device/analyzer) + to_chat(user, SPAN_NOTICE("The water temperature seems to be [watertemp].")) + if(HAS_TRAIT(I, TRAIT_TOOL_WRENCH)) + to_chat(user, SPAN_NOTICE("You begin to adjust the temperature valve with \the [I].")) + if(do_after(user, 50, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) + switch(watertemp) + if("normal") + watertemp = "freezing" + if("freezing") + watertemp = "boiling" + if("boiling") + watertemp = "normal" + user.visible_message(SPAN_NOTICE("[user] adjusts the shower with \the [I]."), SPAN_NOTICE("You adjust the shower with \the [I].")) + add_fingerprint(user) + + +/obj/structure/machinery/shower/update_icon() //this is terribly unreadable, but basically it makes the shower mist up + overlays.Cut() //once it's been on for a while, in addition to handling the water overlay. + QDEL_NULL(mymist) + + if(on) + overlays += image('icons/obj/structures/props/watercloset.dmi', src, "water", MOB_LAYER + 1, dir) + if(watertemp == "freezing") + return + if(!ismist) + spawn(50) + if(src && on) + ismist = 1 + mymist = new /obj/effect/mist(loc) + else + ismist = 1 + mymist = new /obj/effect/mist(loc) + else if(ismist) + ismist = 1 + mymist = new /obj/effect/mist(loc) + spawn(250) + if(src && !on) + QDEL_NULL(mymist) + ismist = 0 + + +/obj/structure/machinery/shower/Crossed(atom/movable/O) + ..() + wash(O) + if(ismob(O)) + mobpresent++ + check_heat(O) + + +/obj/structure/machinery/shower/Uncrossed(atom/movable/O) + if(ismob(O)) + mobpresent-- + ..() + +//Yes, showers are super powerful as far as washing goes. +/obj/structure/machinery/shower/proc/wash(atom/movable/O as obj|mob) + if(!on) return + + + if(isliving(O)) + var/mob/living/L = O + L.ExtinguishMob() + L.fire_stacks = -20 //Douse ourselves with water to avoid fire more easily + to_chat(L, SPAN_WARNING("You've been drenched in water!")) + if(iscarbon(O)) + var/mob/living/carbon/M = O + if(M.r_hand) + M.r_hand.clean_blood() + if(M.l_hand) + M.l_hand.clean_blood() + if(M.back) + if(M.back.clean_blood()) + M.update_inv_back(0) + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/washgloves = 1 + var/washshoes = 1 + var/washmask = 1 + var/washears = 1 + var/washglasses = 1 + + if(H.wear_suit) + washgloves = !(H.wear_suit.flags_inv_hide & HIDEGLOVES) + washshoes = !(H.wear_suit.flags_inv_hide & HIDESHOES) + + if(H.head) + washmask = !(H.head.flags_inv_hide & HIDEMASK) + washglasses = !(H.head.flags_inv_hide & HIDEEYES) + washears = !(H.head.flags_inv_hide & HIDEEARS) + + if(H.wear_mask) + if (washears) + washears = !(H.wear_mask.flags_inv_hide & HIDEEARS) + if (washglasses) + washglasses = !(H.wear_mask.flags_inv_hide & HIDEEYES) + + if(H.head) + if(H.head.clean_blood()) + H.update_inv_head() + if(H.wear_suit) + if(H.wear_suit.clean_blood()) + H.update_inv_wear_suit() + else if(H.w_uniform) + if(H.w_uniform.clean_blood()) + H.update_inv_w_uniform() + if(H.gloves && washgloves) + if(H.gloves.clean_blood()) + H.update_inv_gloves() + if(H.shoes && washshoes) + if(H.shoes.clean_blood()) + H.update_inv_shoes() + if(H.wear_mask && washmask) + if(H.wear_mask.clean_blood()) + H.update_inv_wear_mask() + if(H.glasses && washglasses) + if(H.glasses.clean_blood()) + H.update_inv_glasses() + if((H.wear_l_ear || H.wear_r_ear) && washears) + if((H.wear_l_ear && H.wear_l_ear.clean_blood()) ||(H.wear_r_ear && H.wear_r_ear.clean_blood())) + H.update_inv_ears() + if(H.belt) + if(H.belt.clean_blood()) + H.update_inv_belt() + H.clean_blood(washshoes) + else + if(M.wear_mask) //if the mob is not human, it cleans the mask without asking for bitflags + if(M.wear_mask.clean_blood()) + M.update_inv_wear_mask() + M.clean_blood() + else + O.clean_blood() + + if(isturf(loc)) + var/turf/tile = loc + tile.clean_blood() + for(var/obj/effect/E in tile) + if(istype(E,/obj/effect/decal/cleanable) || istype(E,/obj/effect/overlay)) + qdel(E) + + +/obj/structure/machinery/shower/process() + if(!on) return + wash_floor() + if(!mobpresent) return + for(var/mob/living/carbon/C in loc) + check_heat(C) + + +/obj/structure/machinery/shower/proc/wash_floor() + if(!ismist && is_washing) + return + is_washing = 1 + var/turf/T = get_turf(src) +// reagents.add_reagent("water", 2) + T.clean(src) + addtimer(VARSET_CALLBACK(src, is_washing, FALSE), 10 SECONDS) + + +/obj/structure/machinery/shower/proc/check_heat(mob/M as mob) + if(!on || watertemp == "normal") return + if(iscarbon(M)) + var/mob/living/carbon/C = M + + if(watertemp == "freezing") + C.bodytemperature = max(80, C.bodytemperature - 80) + C.recalculate_move_delay = TRUE + to_chat(C, SPAN_WARNING("The water is freezing!")) + return + if(watertemp == "boiling") + C.bodytemperature = min(500, C.bodytemperature + 35) + C.recalculate_move_delay = TRUE + C.apply_damage(5, BURN) + to_chat(C, SPAN_DANGER("The water is searing!")) + return diff --git a/code/game/objects/structures/sink.dm b/code/game/objects/structures/sink.dm new file mode 100644 index 000000000000..6bac40ea7da4 --- /dev/null +++ b/code/game/objects/structures/sink.dm @@ -0,0 +1,122 @@ +/obj/structure/sink + name = "sink" + icon = 'icons/obj/structures/props/watercloset.dmi' + icon_state = "sink_emptied_animation" + desc = "A sink used for washing one's hands and face." + anchored = TRUE + /// if something's being washed at the moment + var/busy = FALSE + + +/obj/structure/sink/Initialize() + . = ..() + if(prob(50)) + icon_state = "sink_emptied" + + +/obj/structure/sink/proc/stop_flow() //sets sink animation to normal sink (without running water) + + if(prob(50)) + icon_state = "sink_emptied_animation" + else + icon_state = "sink_emptied" + flick("sink_animation_empty", src) + + +/obj/structure/sink/attack_hand(mob/user) + if(isRemoteControlling(user)) + return + + if(!Adjacent(user)) + return + + if(busy) + to_chat(user, SPAN_DANGER("Someone's already washing here.")) + return + + to_chat(usr, SPAN_NOTICE(" You start washing your hands.")) + flick("sink_animation_fill", src) //<- play the filling animation then automatically switch back to the loop + icon_state = "sink_animation_fill_loop" //<- set it to the loop + addtimer(CALLBACK(src, PROC_REF(stop_flow)), 6 SECONDS) + playsound(loc, 'sound/effects/sinkrunning.ogg', 25, TRUE) + + busy = TRUE + sleep(40) + busy = FALSE + + if(!Adjacent(user)) return //Person has moved away from the sink + + user.clean_blood() + if(ishuman(user)) + user:update_inv_gloves() + for(var/mob/V in viewers(src, null)) + V.show_message(SPAN_NOTICE("[user] washes their hands using \the [src]."), SHOW_MESSAGE_VISIBLE) + + +/obj/structure/sink/attackby(obj/item/O as obj, mob/user as mob) + if(busy) + to_chat(user, SPAN_DANGER("Someone's already washing here.")) + return + + var/obj/item/reagent_container/RG = O + if (istype(RG) && RG.is_open_container()) + RG.reagents.add_reagent("water", min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this)) + user.visible_message(SPAN_NOTICE("[user] fills \the [RG] using \the [src]."),SPAN_NOTICE("You fill \the [RG] using \the [src].")) + return + + else if (istype(O, /obj/item/weapon/baton)) + var/obj/item/weapon/baton/B = O + if(B.bcell) + if(B.bcell.charge > 0 && B.status == 1) + flick("baton_active", src) + user.apply_effect(10, STUN) + user.stuttering = 10 + user.apply_effect(10, WEAKEN) + B.deductcharge(B.hitcost) + user.visible_message( \ + SPAN_DANGER("[user] was stunned by \his wet [O]!"), \ + SPAN_DANGER("You were stunned by your wet [O]!")) + return + + var/turf/location = user.loc + if(!isturf(location)) return + + var/obj/item/I = O + if(!I || !istype(I,/obj/item)) return + + to_chat(usr, SPAN_NOTICE(" You start washing \the [I].")) + + busy = TRUE + sleep(40) + busy = FALSE + + if(user.loc != location) return //User has moved + if(!I) return //Item's been destroyed while washing + if(user.get_active_hand() != I) return //Person has switched hands or the item in their hands + + O.clean_blood() + user.visible_message( \ + SPAN_NOTICE("[user] washes \a [I] using \the [src]."), \ + SPAN_NOTICE("You wash \a [I] using \the [src].")) + + +/obj/structure/sink/kitchen + name = "kitchen sink" + icon_state = "sink_alt" + + +/obj/structure/sink/puddle //splishy splashy ^_^ + name = "puddle" + icon_state = "puddle" + + +/obj/structure/sink/puddle/attack_hand(mob/M as mob) + icon_state = "puddle-splash" + ..() + icon_state = "puddle" + + +/obj/structure/sink/puddle/attackby(obj/item/O as obj, mob/user as mob) + icon_state = "puddle-splash" + ..() + icon_state = "puddle" diff --git a/code/game/objects/structures/urinal.dm b/code/game/objects/structures/urinal.dm new file mode 100644 index 000000000000..c6d14f46540a --- /dev/null +++ b/code/game/objects/structures/urinal.dm @@ -0,0 +1,22 @@ +/obj/structure/urinal + name = "urinal" + desc = "The HU-452, an experimental urinal." + icon = 'icons/obj/structures/props/watercloset.dmi' + icon_state = "urinal" + density = FALSE + anchored = TRUE + +/obj/structure/urinal/attackby(obj/item/I, mob/living/user) + if(istype(I, /obj/item/grab)) + if(isxeno(user)) return + var/obj/item/grab/G = I + if(isliving(G.grabbed_thing)) + var/mob/living/GM = G.grabbed_thing + if(user.grab_level > GRAB_PASSIVE) + if(!GM.loc == get_turf(src)) + to_chat(user, SPAN_NOTICE("[GM.name] needs to be on the urinal.")) + return + user.visible_message(SPAN_DANGER("[user] slams [GM.name] into [src]!"), SPAN_NOTICE("You slam [GM.name] into [src]!")) + GM.apply_damage(8, BRUTE) + else + to_chat(user, SPAN_NOTICE("You need a tighter grip.")) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index ea93d868c5a1..1014e8ab7a96 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -1,5 +1,3 @@ -//todo: toothbrushes, and some sort of "toilet-filthinator" for the hos - /obj/structure/toilet name = "toilet" desc = "The HT-451, a torque rotation-based, waste disposal unit for small matter. This one seems remarkably clean." @@ -9,16 +7,19 @@ anchored = TRUE can_buckle = TRUE buckle_lying = 0 - var/open = 0 //if the lid is up - var/cistern = 0 //if the cistern bit is open - var/w_items = 0 //the combined w_class of all the items in the cistern - var/mob/living/swirlie = null //the mob being given a swirlie + /// if the lid is up + var/open = 0 + /// if the cistern bit is open + var/cistern = 0 + /// the combined w_class of all the items in the cistern + var/w_items = 0 + /// the mob being given a swirlie + var/mob/living/swirlie = null var/list/buckling_y = list("north" = 1, "south" = 4, "east" = 0, "west" = 0) var/list/buckling_x = list("north" = 0, "south" = 0, "east" = -5, "west" = 4) var/atom/movable/overlay/cistern_overlay - /obj/structure/toilet/Initialize() . = ..() open = round(rand(0, 1)) @@ -29,6 +30,7 @@ vis_contents += cistern_overlay update_icon() + /obj/structure/toilet/attack_hand(mob/living/user as mob) if(buckled_mob) manual_unbuckle(user) @@ -69,7 +71,6 @@ flick("cistern[cistern]_flush", cistern_overlay) - /obj/structure/toilet/send_buckling_message(mob/M, mob/user) if (M == user) to_chat(M, SPAN_NOTICE("You seat yourself onto the toilet")) @@ -77,10 +78,10 @@ to_chat(user, SPAN_NOTICE("[M] has been seated onto the toilet by [user].")) to_chat(M, SPAN_NOTICE("You have been seated onto the toilet by [user].")) + /obj/structure/toilet/afterbuckle(mob/M) . = ..() - if(. && buckled_mob == M) var/direction = dir2text(dir) M.pixel_y = buckling_y[direction] + pixel_y @@ -106,7 +107,6 @@ M.overlays -= image("toilet00") - /obj/structure/toilet/verb/flip_lid() set name = "Flip lid" set category = "Object" @@ -116,11 +116,11 @@ update_icon() - /obj/structure/toilet/update_icon() icon_state = "toilet[open][cistern]" cistern_overlay.icon_state = "cistern[cistern]" + /obj/structure/toilet/attackby(obj/item/I, mob/living/user) if(HAS_TRAIT(I, TRAIT_TOOL_CROWBAR)) to_chat(user, SPAN_NOTICE("You start to [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"].")) @@ -168,374 +168,3 @@ w_items += I.w_class to_chat(user, "You carefully place \the [I] into the cistern.") return - - - -/obj/structure/urinal - name = "urinal" - desc = "The HU-452, an experimental urinal." - icon = 'icons/obj/structures/props/watercloset.dmi' - icon_state = "urinal" - density = FALSE - anchored = TRUE - -/obj/structure/urinal/attackby(obj/item/I, mob/living/user) - if(istype(I, /obj/item/grab)) - if(isxeno(user)) return - var/obj/item/grab/G = I - if(isliving(G.grabbed_thing)) - var/mob/living/GM = G.grabbed_thing - if(user.grab_level > GRAB_PASSIVE) - if(!GM.loc == get_turf(src)) - to_chat(user, SPAN_NOTICE("[GM.name] needs to be on the urinal.")) - return - user.visible_message(SPAN_DANGER("[user] slams [GM.name] into [src]!"), SPAN_NOTICE("You slam [GM.name] into [src]!")) - GM.apply_damage(8, BRUTE) - else - to_chat(user, SPAN_NOTICE("You need a tighter grip.")) - - - -/obj/structure/machinery/shower - name = "shower" - desc = "The HS-451. Installed in the 2050s by the Weyland Hygiene Division." - icon = 'icons/obj/structures/props/watercloset.dmi' - icon_state = "shower" - density = FALSE - anchored = TRUE - use_power = USE_POWER_NONE - var/on = 0 - var/obj/effect/mist/mymist = null - var/ismist = 0 //needs a var so we can make it linger~ - var/watertemp = "normal" //freezing, normal, or boiling - var/mobpresent = 0 //true if there is a mob on the shower's loc, this is to ease process() - var/is_washing = 0 - -/obj/structure/machinery/shower/Initialize() - . = ..() - create_reagents(2) - -//add heat controls? when emagged, you can freeze to death in it? - -/obj/effect/mist - name = "mist" - icon = 'icons/obj/structures/props/watercloset.dmi' - icon_state = "mist" - layer = FLY_LAYER - anchored = TRUE - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - -/obj/structure/machinery/shower/attack_hand(mob/M as mob) - on = !on - update_icon() - if(on) - start_processing() - if (M.loc == loc) - wash(M) - check_heat(M) - for (var/atom/movable/G in src.loc) - G.clean_blood() - else - stop_processing() - -/obj/structure/machinery/shower/attackby(obj/item/I as obj, mob/user as mob) - if(I.type == /obj/item/device/analyzer) - to_chat(user, SPAN_NOTICE("The water temperature seems to be [watertemp].")) - if(HAS_TRAIT(I, TRAIT_TOOL_WRENCH)) - to_chat(user, SPAN_NOTICE("You begin to adjust the temperature valve with \the [I].")) - if(do_after(user, 50, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD)) - switch(watertemp) - if("normal") - watertemp = "freezing" - if("freezing") - watertemp = "boiling" - if("boiling") - watertemp = "normal" - user.visible_message(SPAN_NOTICE("[user] adjusts the shower with \the [I]."), SPAN_NOTICE("You adjust the shower with \the [I].")) - add_fingerprint(user) - -/obj/structure/machinery/shower/update_icon() //this is terribly unreadable, but basically it makes the shower mist up - overlays.Cut() //once it's been on for a while, in addition to handling the water overlay. - QDEL_NULL(mymist) - - if(on) - overlays += image('icons/obj/structures/props/watercloset.dmi', src, "water", MOB_LAYER + 1, dir) - if(watertemp == "freezing") - return - if(!ismist) - spawn(50) - if(src && on) - ismist = 1 - mymist = new /obj/effect/mist(loc) - else - ismist = 1 - mymist = new /obj/effect/mist(loc) - else if(ismist) - ismist = 1 - mymist = new /obj/effect/mist(loc) - spawn(250) - if(src && !on) - QDEL_NULL(mymist) - ismist = 0 - -/obj/structure/machinery/shower/Crossed(atom/movable/O) - ..() - wash(O) - if(ismob(O)) - mobpresent++ - check_heat(O) - -/obj/structure/machinery/shower/Uncrossed(atom/movable/O) - if(ismob(O)) - mobpresent-- - ..() - -//Yes, showers are super powerful as far as washing goes. -/obj/structure/machinery/shower/proc/wash(atom/movable/O as obj|mob) - if(!on) return - - - if(isliving(O)) - var/mob/living/L = O - L.ExtinguishMob() - L.fire_stacks = -20 //Douse ourselves with water to avoid fire more easily - to_chat(L, SPAN_WARNING("You've been drenched in water!")) - if(iscarbon(O)) - var/mob/living/carbon/M = O - if(M.r_hand) - M.r_hand.clean_blood() - if(M.l_hand) - M.l_hand.clean_blood() - if(M.back) - if(M.back.clean_blood()) - M.update_inv_back(0) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - var/washgloves = 1 - var/washshoes = 1 - var/washmask = 1 - var/washears = 1 - var/washglasses = 1 - - if(H.wear_suit) - washgloves = !(H.wear_suit.flags_inv_hide & HIDEGLOVES) - washshoes = !(H.wear_suit.flags_inv_hide & HIDESHOES) - - if(H.head) - washmask = !(H.head.flags_inv_hide & HIDEMASK) - washglasses = !(H.head.flags_inv_hide & HIDEEYES) - washears = !(H.head.flags_inv_hide & HIDEEARS) - - if(H.wear_mask) - if (washears) - washears = !(H.wear_mask.flags_inv_hide & HIDEEARS) - if (washglasses) - washglasses = !(H.wear_mask.flags_inv_hide & HIDEEYES) - - if(H.head) - if(H.head.clean_blood()) - H.update_inv_head() - if(H.wear_suit) - if(H.wear_suit.clean_blood()) - H.update_inv_wear_suit() - else if(H.w_uniform) - if(H.w_uniform.clean_blood()) - H.update_inv_w_uniform() - if(H.gloves && washgloves) - if(H.gloves.clean_blood()) - H.update_inv_gloves() - if(H.shoes && washshoes) - if(H.shoes.clean_blood()) - H.update_inv_shoes() - if(H.wear_mask && washmask) - if(H.wear_mask.clean_blood()) - H.update_inv_wear_mask() - if(H.glasses && washglasses) - if(H.glasses.clean_blood()) - H.update_inv_glasses() - if((H.wear_l_ear || H.wear_r_ear) && washears) - if((H.wear_l_ear && H.wear_l_ear.clean_blood()) ||(H.wear_r_ear && H.wear_r_ear.clean_blood())) - H.update_inv_ears() - if(H.belt) - if(H.belt.clean_blood()) - H.update_inv_belt() - H.clean_blood(washshoes) - else - if(M.wear_mask) //if the mob is not human, it cleans the mask without asking for bitflags - if(M.wear_mask.clean_blood()) - M.update_inv_wear_mask() - M.clean_blood() - else - O.clean_blood() - - if(isturf(loc)) - var/turf/tile = loc - tile.clean_blood() - for(var/obj/effect/E in tile) - if(istype(E,/obj/effect/decal/cleanable) || istype(E,/obj/effect/overlay)) - qdel(E) - -/obj/structure/machinery/shower/process() - if(!on) return - wash_floor() - if(!mobpresent) return - for(var/mob/living/carbon/C in loc) - check_heat(C) - -/obj/structure/machinery/shower/proc/wash_floor() - if(!ismist && is_washing) - return - is_washing = 1 - var/turf/T = get_turf(src) -// reagents.add_reagent("water", 2) - T.clean(src) - addtimer(VARSET_CALLBACK(src, is_washing, FALSE), 10 SECONDS) - -/obj/structure/machinery/shower/proc/check_heat(mob/M as mob) - if(!on || watertemp == "normal") return - if(iscarbon(M)) - var/mob/living/carbon/C = M - - if(watertemp == "freezing") - C.bodytemperature = max(80, C.bodytemperature - 80) - C.recalculate_move_delay = TRUE - to_chat(C, SPAN_WARNING("The water is freezing!")) - return - if(watertemp == "boiling") - C.bodytemperature = min(500, C.bodytemperature + 35) - C.recalculate_move_delay = TRUE - C.apply_damage(5, BURN) - to_chat(C, SPAN_DANGER("The water is searing!")) - return - - - -/obj/item/toy/bikehorn/rubberducky - name = "rubber ducky" - desc = "Rubber ducky you're so fine, you make bathtime lots of fuuun. Rubber ducky I'm awfully fooooond of yooooouuuu~" //thanks doohl - icon = 'icons/obj/structures/props/watercloset.dmi' - icon_state = "rubberducky" - item_state = "rubberducky" - - - -/obj/structure/sink - name = "sink" - icon = 'icons/obj/structures/props/watercloset.dmi' - icon_state = "sink_emptied_animation" - desc = "A sink used for washing one's hands and face." - anchored = TRUE - var/busy = FALSE //Something's being washed at the moment - -/obj/structure/sink/Initialize() - . = ..() - if(prob(50)) - icon_state = "sink_emptied" - - - -/obj/structure/sink/proc/stop_flow() //sets sink animation to normal sink (without running water) - - if(prob(50)) - icon_state = "sink_emptied_animation" - else - icon_state = "sink_emptied" - flick("sink_animation_empty", src) - - - -/obj/structure/sink/attack_hand(mob/user) - if(isRemoteControlling(user)) - return - - if(!Adjacent(user)) - return - - if(busy) - to_chat(user, SPAN_DANGER("Someone's already washing here.")) - return - - to_chat(usr, SPAN_NOTICE(" You start washing your hands.")) - flick("sink_animation_fill", src) //<- play the filling animation then automatically switch back to the loop - icon_state = "sink_animation_fill_loop" //<- set it to the loop - addtimer(CALLBACK(src, PROC_REF(stop_flow)), 6 SECONDS) - playsound(loc, 'sound/effects/sinkrunning.ogg', 25, TRUE) - - busy = TRUE - sleep(40) - busy = FALSE - - if(!Adjacent(user)) return //Person has moved away from the sink - - user.clean_blood() - if(ishuman(user)) - user:update_inv_gloves() - for(var/mob/V in viewers(src, null)) - V.show_message(SPAN_NOTICE("[user] washes their hands using \the [src]."), SHOW_MESSAGE_VISIBLE) - - -/obj/structure/sink/attackby(obj/item/O as obj, mob/user as mob) - if(busy) - to_chat(user, SPAN_DANGER("Someone's already washing here.")) - return - - var/obj/item/reagent_container/RG = O - if (istype(RG) && RG.is_open_container()) - RG.reagents.add_reagent("water", min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this)) - user.visible_message(SPAN_NOTICE("[user] fills \the [RG] using \the [src]."),SPAN_NOTICE("You fill \the [RG] using \the [src].")) - return - - else if (istype(O, /obj/item/weapon/baton)) - var/obj/item/weapon/baton/B = O - if(B.bcell) - if(B.bcell.charge > 0 && B.status == 1) - flick("baton_active", src) - user.apply_effect(10, STUN) - user.stuttering = 10 - user.apply_effect(10, WEAKEN) - B.deductcharge(B.hitcost) - user.visible_message( \ - SPAN_DANGER("[user] was stunned by \his wet [O]!"), \ - SPAN_DANGER("You were stunned by your wet [O]!")) - return - - var/turf/location = user.loc - if(!isturf(location)) return - - var/obj/item/I = O - if(!I || !istype(I,/obj/item)) return - - to_chat(usr, SPAN_NOTICE(" You start washing \the [I].")) - - busy = TRUE - sleep(40) - busy = FALSE - - if(user.loc != location) return //User has moved - if(!I) return //Item's been destroyed while washing - if(user.get_active_hand() != I) return //Person has switched hands or the item in their hands - - O.clean_blood() - user.visible_message( \ - SPAN_NOTICE("[user] washes \a [I] using \the [src]."), \ - SPAN_NOTICE("You wash \a [I] using \the [src].")) - - -/obj/structure/sink/kitchen - name = "kitchen sink" - icon_state = "sink_alt" - - -/obj/structure/sink/puddle //splishy splashy ^_^ - name = "puddle" - icon_state = "puddle" - -/obj/structure/sink/puddle/attack_hand(mob/M as mob) - icon_state = "puddle-splash" - ..() - icon_state = "puddle" - -/obj/structure/sink/puddle/attackby(obj/item/O as obj, mob/user as mob) - icon_state = "puddle-splash" - ..() - icon_state = "puddle" diff --git a/colonialmarines.dme b/colonialmarines.dme index 6beec448e4b4..64760c4f2bc9 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -1284,10 +1284,13 @@ #include "code\game\objects\structures\props.dm" #include "code\game\objects\structures\reagent_dispensers.dm" #include "code\game\objects\structures\safe.dm" +#include "code\game\objects\structures\shower.dm" #include "code\game\objects\structures\signs.dm" +#include "code\game\objects\structures\sink.dm" #include "code\game\objects\structures\surface.dm" #include "code\game\objects\structures\tables_racks.dm" #include "code\game\objects\structures\tank_dispenser.dm" +#include "code\game\objects\structures\urinal.dm" #include "code\game\objects\structures\vulture_spotter.dm" #include "code\game\objects\structures\watercloset.dm" #include "code\game\objects\structures\windoor_assembly.dm" From 1e676579e218e15cb785da11df57d6c324bf9771 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Mon, 12 Feb 2024 01:21:03 +0000 Subject: [PATCH 08/11] Automatic changelog for PR #5596 [ci skip] --- html/changelogs/AutoChangeLog-pr-5596.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-5596.yml diff --git a/html/changelogs/AutoChangeLog-pr-5596.yml b/html/changelogs/AutoChangeLog-pr-5596.yml new file mode 100644 index 000000000000..9d1f19e74f38 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5596.yml @@ -0,0 +1,4 @@ +author: "Huffie56" +delete-after: True +changes: + - refactor: "refactored watercloset.dm file." \ No newline at end of file From 153b7cf09286f9ee1b85ee724316236e3e3859bf Mon Sep 17 00:00:00 2001 From: SabreML <57483089+SabreML@users.noreply.github.com> Date: Mon, 12 Feb 2024 21:09:08 +0000 Subject: [PATCH 09/11] Thour tiny tutorial tweaks (and a unit test) (#5695) # About the pull request
  1. Commit 5014927bc4ae6f3bd03f3ea1866cb6ba6c9e7c54: Makes the 'Tutorial Menu' automatically close when a tutorial is started.
    • Also adds an abort_tutorial() call to /datum/tutorial/proc/start_tutorial(), since it may have been possible to for player to get trapped in the tutorial otherwise.
  2. Commit b10974c0471ef14c3c66ec10910e8c993cbb29d1: Adds a tutorial_id to the basic Xenomorph tutorial.
  3. Commit 38c03c987dbad50f7d8a2354a63c75f88d5efcce: Edited the tutorial Xenomorph a bit so that it's always "You are Inquisitive Drone (XX-123)", as opposed to "You are Inquisitive Young/Mature/etc. Drone (XX-123)".
  4. Commits a595b971c489922510bd984e3d324ac844450efe + 27e38e654a611aeefd548c41035bbff035caa76b: Adds a basic unit test for /datum/tutorial subtypes to verify that they have set some basic variables.
    • Also lightly organises the #includes in code/modules/unit_tests/_unit_tests.dm.
# Explain why it's good for the game Just a couple of things I noticed while exploring tutorial code. The third commit is maybe a bit subjective, but I personally think it makes the tutorials seem like more of a separate game state, if that makes sense. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: ui: Made the Tutorial Menu automatically close when a tutorial is started. code: Made the tutorial Xenomorph not inherit the user's 'age' prefix. code: Added a basic unit test for tutorials. /:cl: --- code/datums/tutorial/_tutorial.dm | 1 + code/datums/tutorial/_tutorial_menu.dm | 5 +++-- code/datums/tutorial/xenomorph/_xenomorph.dm | 4 ++++ .../tutorial/xenomorph/xenomorph_basic.dm | 5 ++++- code/modules/unit_tests/_unit_tests.dm | 12 ++++++++---- code/modules/unit_tests/tutorials.dm | 19 +++++++++++++++++++ 6 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 code/modules/unit_tests/tutorials.dm diff --git a/code/datums/tutorial/_tutorial.dm b/code/datums/tutorial/_tutorial.dm index 5423453bbdb9..7dd7ac85c04d 100644 --- a/code/datums/tutorial/_tutorial.dm +++ b/code/datums/tutorial/_tutorial.dm @@ -52,6 +52,7 @@ GLOBAL_LIST_EMPTY_TYPED(ongoing_tutorials, /datum/tutorial) reservation = SSmapping.RequestBlockReservation(initial(tutorial_template.width), initial(tutorial_template.height)) if(!reservation) + abort_tutorial() return FALSE var/turf/bottom_left_corner_reservation = locate(reservation.bottom_left_coords[1], reservation.bottom_left_coords[2], reservation.bottom_left_coords[3]) diff --git a/code/datums/tutorial/_tutorial_menu.dm b/code/datums/tutorial/_tutorial_menu.dm index 42eb3f6aabfa..951b9654ef0e 100644 --- a/code/datums/tutorial/_tutorial_menu.dm +++ b/code/datums/tutorial/_tutorial_menu.dm @@ -79,5 +79,6 @@ return path = new path - path.start_tutorial(usr) - return TRUE + if(path.start_tutorial(usr)) + ui.close() + return TRUE diff --git a/code/datums/tutorial/xenomorph/_xenomorph.dm b/code/datums/tutorial/xenomorph/_xenomorph.dm index bd85cdb35f44..caa33d8eed43 100644 --- a/code/datums/tutorial/xenomorph/_xenomorph.dm +++ b/code/datums/tutorial/xenomorph/_xenomorph.dm @@ -22,6 +22,10 @@ // We don't want people talking to other xenomorphs across tutorials new_character.can_hivemind_speak = FALSE + // No age prefix or HUD element + new_character.age = XENO_NO_AGE + new_character.show_age_prefix = FALSE + new_character.generate_name() tutorial_mob = new_character xeno = new_character diff --git a/code/datums/tutorial/xenomorph/xenomorph_basic.dm b/code/datums/tutorial/xenomorph/xenomorph_basic.dm index 0415977835aa..e91c85e1e1e4 100644 --- a/code/datums/tutorial/xenomorph/xenomorph_basic.dm +++ b/code/datums/tutorial/xenomorph/xenomorph_basic.dm @@ -4,6 +4,7 @@ name = "Xenomorph - Basic" desc = "A tutorial to get you acquainted with the very basics of how to play a xenomorph." icon_state = "xeno" + tutorial_id = "xeno_basic_1" tutorial_template = /datum/map_template/tutorial/s12x12 starting_xenomorph_type = /mob/living/carbon/xenomorph/drone @@ -105,7 +106,7 @@ UnregisterSignal(human_dummy, COMSIG_MOB_DEATH) message_to_player("Well done. Killing humans is one of many ways to help the hive.") - message_to_player("Another way is to capture them. This will grow a new xenomorph inside them which will eventually burst into a new playable xenomorph!") + message_to_player("Another way is to capture them. This will grow a new xenomorph inside them which will eventually burst into a new playable xenomorph!") addtimer(CALLBACK(human_dummy, TYPE_PROC_REF(/mob/living, rejuvenate)), 8 SECONDS) addtimer(CALLBACK(src, PROC_REF(proceed_to_tackle_phase)), 10 SECONDS) @@ -227,3 +228,5 @@ /datum/tutorial/xenomorph/basic/init_map() loc_from_corner(9,0).ChangeTurf(/turf/closed/wall/resin/tutorial) + +#undef WAITING_HEALTH_THRESHOLD diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 90040ec9acf9..3967ee70e391 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -74,19 +74,23 @@ /// A trait source when adding traits through unit tests #define TRAIT_SOURCE_UNIT_TESTS "unit_tests" +// Unit tests #include "autowiki.dm" +#include "check_runtimes.dm" #include "create_and_destroy.dm" -#include "focus_only_tests.dm" +#include "emote_panels.dm" #include "missing_icons.dm" #include "resist.dm" +#include "spawn_humans.dm" #include "spritesheets.dm" #include "subsystem_init.dm" #include "tgui_create_message.dm" #include "timer_sanity.dm" +#include "tutorials.dm" + +// Unit tests backend +#include "focus_only_tests.dm" #include "unit_test.dm" -#include "spawn_humans.dm" -#include "check_runtimes.dm" -#include "emote_panels.dm" #undef TEST_ASSERT #undef TEST_ASSERT_EQUAL diff --git a/code/modules/unit_tests/tutorials.dm b/code/modules/unit_tests/tutorials.dm new file mode 100644 index 000000000000..d835a4f272cb --- /dev/null +++ b/code/modules/unit_tests/tutorials.dm @@ -0,0 +1,19 @@ +/datum/unit_test/tutorials + +/datum/unit_test/tutorials/Run() + var/datum/tutorial/base_path = /datum/tutorial + for(var/datum/tutorial/tutorial_path as anything in subtypesof(base_path)) + if(initial(tutorial_path.parent_path) == tutorial_path) + continue + + // Make sure these variables are overridden on any subtypes. + TEST_ASSERT_NOTEQUAL(initial(tutorial_path.name), initial(base_path.name), + "[tutorial_path] does not have a name set.") + TEST_ASSERT_NOTEQUAL(initial(tutorial_path.tutorial_id), initial(base_path.tutorial_id), + "[tutorial_path] does not have a tutorial_id set.") + TEST_ASSERT_NOTEQUAL(initial(tutorial_path.desc), initial(base_path.desc), + "[tutorial_path] does not have a desc set.") + TEST_ASSERT_NOTEQUAL(initial(tutorial_path.icon_state), initial(base_path.icon_state), + "[tutorial_path] does not have an icon_state set.") + +// TODO: Add a test verifying that a basic tutorial can be started and completed. (Requires unit test client handling) From 41a39b96009f3d97206fd63416a2fb5a47c89525 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Mon, 12 Feb 2024 21:18:16 +0000 Subject: [PATCH 10/11] Automatic changelog for PR #5695 [ci skip] --- html/changelogs/AutoChangeLog-pr-5695.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-5695.yml diff --git a/html/changelogs/AutoChangeLog-pr-5695.yml b/html/changelogs/AutoChangeLog-pr-5695.yml new file mode 100644 index 000000000000..3c88e26a8e5f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5695.yml @@ -0,0 +1,6 @@ +author: "SabreML" +delete-after: True +changes: + - ui: "Made the Tutorial Menu automatically close when a tutorial is started." + - code_imp: "Made the tutorial Xenomorph not inherit the user's 'age' prefix." + - code_imp: "Added a basic unit test for tutorials." \ No newline at end of file From fe2f2b893f1feed94b3719002c60de97a5d36f7d Mon Sep 17 00:00:00 2001 From: Changelogs Date: Tue, 13 Feb 2024 01:07:41 +0000 Subject: [PATCH 11/11] Automatic changelog compile [ci skip] --- html/changelogs/AutoChangeLog-pr-5596.yml | 4 ---- html/changelogs/AutoChangeLog-pr-5695.yml | 6 ------ html/changelogs/archive/2024-02.yml | 7 +++++++ 3 files changed, 7 insertions(+), 10 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-5596.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-5695.yml diff --git a/html/changelogs/AutoChangeLog-pr-5596.yml b/html/changelogs/AutoChangeLog-pr-5596.yml deleted file mode 100644 index 9d1f19e74f38..000000000000 --- a/html/changelogs/AutoChangeLog-pr-5596.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Huffie56" -delete-after: True -changes: - - refactor: "refactored watercloset.dm file." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-5695.yml b/html/changelogs/AutoChangeLog-pr-5695.yml deleted file mode 100644 index 3c88e26a8e5f..000000000000 --- a/html/changelogs/AutoChangeLog-pr-5695.yml +++ /dev/null @@ -1,6 +0,0 @@ -author: "SabreML" -delete-after: True -changes: - - ui: "Made the Tutorial Menu automatically close when a tutorial is started." - - code_imp: "Made the tutorial Xenomorph not inherit the user's 'age' prefix." - - code_imp: "Added a basic unit test for tutorials." \ No newline at end of file diff --git a/html/changelogs/archive/2024-02.yml b/html/changelogs/archive/2024-02.yml index 156a3c6c33be..f8d85764a2a3 100644 --- a/html/changelogs/archive/2024-02.yml +++ b/html/changelogs/archive/2024-02.yml @@ -157,3 +157,10 @@ - qol: Lets you put an extra accessory item in your helmet. harryob: - server: tor banning functionality is removed +2024-02-13: + Huffie56: + - refactor: refactored watercloset.dm file. + SabreML: + - ui: Made the Tutorial Menu automatically close when a tutorial is started. + - code_imp: Made the tutorial Xenomorph not inherit the user's 'age' prefix. + - code_imp: Added a basic unit test for tutorials.