From 7609c576eba96ed466b2659845995736c215e15d Mon Sep 17 00:00:00 2001 From: cuberound <122645057+cuberound@users.noreply.github.com> Date: Sat, 6 Apr 2024 07:53:16 +0200 Subject: [PATCH 01/32] reduces impact area from 9x9 to 7x7, lowers DPS slightly (#6031) # About the pull request okey this is basicly copy of my suggested buff from more then a year ago, but now it is a nerf. Main complain on why the GAU is so OP and strong is its spreat ( that used to be the reason why it was so weak and shit). Therfore, lets do some math. Current situation is that the GAU fires 80 rounds per burst at area of 81 tiles( 9x9) ~0,988 round per tile, the proposed change aims the keep the damage on anyone standing in the impact area about the same ( it is a bit lower might need compensation with bringing the damage to pre double bullet values) , by bringing down the impact area to 49 tiles (7x7) and lowering the number of shots fired to 40, we get value of ~0,816 round per tile. meanwhile it keeps the rest like how long the bursts last the just as long. (https://github.com/cmss13-devs/cmss13/pull/4302 the old "buff") # Explain why it's good for the game Making two bullets per bullet was not a bad idea in general, it brought the DPS on competetive level with other weapons, but the huge spread leads to too big compared to other ordinance. Bringing it in line with other ordinance should allow for easier CAS balance around smaller impact FMs. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: balance: reduced GAU spread from 9x9 to 7x7 balance: reduced GAU shots fired per shot back to 1 (bullets per tile from 0.99 to 0.82) /:cl: Co-authored-by: vincibrv --- code/modules/cm_marines/dropship_ammo.dm | 43 ++++++++++++------------ 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/code/modules/cm_marines/dropship_ammo.dm b/code/modules/cm_marines/dropship_ammo.dm index 93768e218375..0926f2bcefff 100644 --- a/code/modules/cm_marines/dropship_ammo.dm +++ b/code/modules/cm_marines/dropship_ammo.dm @@ -144,7 +144,7 @@ ammo_used_per_firing = 40 point_cost = 275 fire_mission_delay = 2 - var/bullet_spread_range = 4 //how far from the real impact turf can bullets land + var/bullet_spread_range = 3 //how far from the real impact turf can bullets land var/shrapnel_type = /datum/ammo/bullet/shrapnel/gau //For siming 30mm bullet impacts. var/directhit_damage = 105 //how much damage is to be inflicted to a mob, this is here so that we can hit resting mobs. var/penetration = 10 //AP value pretty much @@ -169,27 +169,26 @@ for(var/i = 1 to ammo_used_per_firing) sleep(1) - for(var/j in 1 to 2) //rather than halving the sleep, were doubling the bullets shot "bang" - var/turf/impact_tile = pick(turf_list) - var/datum/cause_data/cause_data = create_cause_data(fired_from.name, source_mob) - impact_tile.ex_act(EXPLOSION_THRESHOLD_VLOW, pick(GLOB.alldirs), cause_data) - create_shrapnel(impact_tile,1,0,0,shrapnel_type,cause_data,FALSE,100) //simulates a bullet - for(var/atom/movable/explosion_effect in impact_tile) - if(iscarbon(explosion_effect)) - var/mob/living/carbon/bullet_effect = explosion_effect - explosion_effect.ex_act(EXPLOSION_THRESHOLD_VLOW, null, cause_data) - bullet_effect.apply_armoured_damage(directhit_damage,ARMOR_BULLET,BRUTE,null,penetration) - else - explosion_effect.ex_act(EXPLOSION_THRESHOLD_VLOW) - new /obj/effect/particle_effect/expl_particles(impact_tile) - if(!soundplaycooldown) //so we don't play the same sound 20 times very fast. - playsound(impact_tile, 'sound/effects/gauimpact.ogg',40,1,20) - soundplaycooldown = 3 - soundplaycooldown-- - if(!debriscooldown) - impact_tile.ceiling_debris_check(1) - debriscooldown = 6 - debriscooldown-- + var/turf/impact_tile = pick(turf_list) + var/datum/cause_data/cause_data = create_cause_data(fired_from.name, source_mob) + impact_tile.ex_act(EXPLOSION_THRESHOLD_VLOW, pick(GLOB.alldirs), cause_data) + create_shrapnel(impact_tile,1,0,0,shrapnel_type,cause_data,FALSE,100) //simulates a bullet + for(var/atom/movable/explosion_effect in impact_tile) + if(iscarbon(explosion_effect)) + var/mob/living/carbon/bullet_effect = explosion_effect + explosion_effect.ex_act(EXPLOSION_THRESHOLD_VLOW, null, cause_data) + bullet_effect.apply_armoured_damage(directhit_damage,ARMOR_BULLET,BRUTE,null,penetration) + else + explosion_effect.ex_act(EXPLOSION_THRESHOLD_VLOW) + new /obj/effect/particle_effect/expl_particles(impact_tile) + if(!soundplaycooldown) //so we don't play the same sound 20 times very fast. + playsound(impact_tile, 'sound/effects/gauimpact.ogg',40,1,20) + soundplaycooldown = 3 + soundplaycooldown-- + if(!debriscooldown) + impact_tile.ceiling_debris_check(1) + debriscooldown = 6 + debriscooldown-- sleep(11) //speed of sound simulation playsound(impact, 'sound/effects/gau.ogg',100,1,60) From 437cab4bea2600d5a4aeb013ddffb14806a51f16 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Sat, 6 Apr 2024 07:01:35 +0100 Subject: [PATCH 02/32] Automatic changelog for PR #6031 [ci skip] --- html/changelogs/AutoChangeLog-pr-6031.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-6031.yml diff --git a/html/changelogs/AutoChangeLog-pr-6031.yml b/html/changelogs/AutoChangeLog-pr-6031.yml new file mode 100644 index 000000000000..c70d02897d01 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-6031.yml @@ -0,0 +1,5 @@ +author: "cuberound" +delete-after: True +changes: + - balance: "reduced GAU spread from 9x9 to 7x7" + - balance: "reduced GAU shots fired per shot back to 1 (bullets per tile from 0.99 to 0.82)" \ No newline at end of file From fa7fba92d772e9aaaaa0c446e83856780f9edabf Mon Sep 17 00:00:00 2001 From: InsaneRed <47158596+InsaneRed@users.noreply.github.com> Date: Sat, 6 Apr 2024 10:13:33 +0300 Subject: [PATCH 03/32] gives proper light armor slowdown to goon armor (#6059) # About the pull request Gives light_slowdown to the goon armor that spawns on survivors, since it has BETTER THEN LIGHTARMOR without any slowdown # Explain why it's good for the game People are powergaming with survivor armor and i dont like it, also the goon armor is described as being shady and bad. Doesnt make sense it has nearly medium stats with no slowdown at all. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: balance: Goon armor properly has slowdown now /:cl: --------- Co-authored-by: InsaneRed Co-authored-by: Drathek <76988376+Drulikar@users.noreply.github.com> --- code/modules/clothing/suits/marine_armor/ert.dm | 3 +-- code/modules/clothing/under/marine_uniform.dm | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/code/modules/clothing/suits/marine_armor/ert.dm b/code/modules/clothing/suits/marine_armor/ert.dm index 19009606db35..6d2ad9934a40 100644 --- a/code/modules/clothing/suits/marine_armor/ert.dm +++ b/code/modules/clothing/suits/marine_armor/ert.dm @@ -79,13 +79,12 @@ item_state = "armor" item_state_slots = null contained_sprite = TRUE + slowdown = SLOWDOWN_ARMOR_LIGHT flags_armor_protection = BODY_FLAG_CHEST flags_cold_protection = BODY_FLAG_CHEST flags_heat_protection = BODY_FLAG_CHEST - slowdown = SLOWDOWN_ARMOR_NONE // only protects chest, but enables rapid movement - /obj/item/clothing/suit/storage/marine/veteran/pmc/light/corporate/lead desc = "A basic vest with a Weyland-Yutani badge on the right breast. This variant is worn by low-level guards that have elevated in rank due to 'good conduct in the field', also known as corporate bootlicking." icon_state = "lead_armor" diff --git a/code/modules/clothing/under/marine_uniform.dm b/code/modules/clothing/under/marine_uniform.dm index f7dd5be511ce..92eeea638fae 100644 --- a/code/modules/clothing/under/marine_uniform.dm +++ b/code/modules/clothing/under/marine_uniform.dm @@ -896,7 +896,7 @@ item_icons = list( WEAR_BODY = 'icons/mob/humans/onmob/uniform_1.dmi', ) - + /obj/item/clothing/under/marine/reporter/black icon_state = "cc_black" worn_state = "cc_black" From e619c331151897d9230b59c47f04c9e8f2d0b5a4 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Sat, 6 Apr 2024 08:19:18 +0100 Subject: [PATCH 04/32] Automatic changelog for PR #6059 [ci skip] --- html/changelogs/AutoChangeLog-pr-6059.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-6059.yml diff --git a/html/changelogs/AutoChangeLog-pr-6059.yml b/html/changelogs/AutoChangeLog-pr-6059.yml new file mode 100644 index 000000000000..e4b85ee392e9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-6059.yml @@ -0,0 +1,4 @@ +author: "InsaneRed" +delete-after: True +changes: + - balance: "Goon armor properly has slowdown now" \ No newline at end of file From c94bda6e80a20e87ccc2d5453871e4f590442594 Mon Sep 17 00:00:00 2001 From: Ben <91219575+Ben10083@users.noreply.github.com> Date: Sat, 6 Apr 2024 03:39:17 -0400 Subject: [PATCH 05/32] Super Strength Grab Changes (Never skip arm day) (#6020) # About the pull request Grabs for those with super strength buffed - passive grabs no longer guarantied resist - target has reduced chance to resist - if the target, _increased_ chance to resist - if both have super strength, works as before (passive grabs guarantied for example) # Explain why it's good for the game Grabs are not often used, even though roles such as WJs are encouraged to do so. This is because grabs are very easy to be resisted out of. This is fine, and is necessary, but in this case, I want to have it so if someone has an advantage in strength, they have advantage in this exchange (both dealing and recieving). I feel this was more an oversight, as logically those who are stronger will have a stronger grip than otherwise. The balance out between the two is to prevent shenanigans between synth and pred, no grab fights there. scenario 1) Synth vs Human Synth has strength, human doesn't advantage synth scenario 2) human vs Pred Pred has strength, human doesnt advantage pred scenario 3) Synth vs Pred Both have strength No advantage (how it is now) # Changelog :cl: balance: Mobs with super strength now have an advantage when resisting of a grab is done, both as the grabber and the one being grabbed (Xenos not affected, works as before). balance: Mobs with super strength no longer have their passive grabs a guaranteed resist (unless both super). /:cl: --------- Co-authored-by: Ben10083 --- .../mob/living/carbon/human/human_helpers.dm | 10 ++--- code/modules/mob/living/living.dm | 37 +++++++++++++------ 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index c38ddbcd552c..d6d438441d20 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -206,18 +206,18 @@ return FALSE -/mob/living/carbon/human/is_mob_restrained(check_grab = 1) +/mob/living/carbon/human/is_mob_restrained(check_grab = TRUE) if(check_grab && pulledby && pulledby.grab_level >= GRAB_AGGRESSIVE) - return 1 + return TRUE if (handcuffed) - return 1 + return TRUE if (istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) - return 1 + return TRUE if (HAS_TRAIT(src, TRAIT_NESTED)) return TRUE - return 0 + return FALSE /mob/living/carbon/human/proc/disable_special_flags() status_flags |= CANPUSH diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index d5190318715c..40a06b253c3e 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -224,19 +224,34 @@ /mob/living/resist_grab(moving_resist) if(!pulledby) return - if(pulledby.grab_level) - if(prob(50)) - playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 25, 1, 7) - visible_message(SPAN_DANGER("[src] has broken free of [pulledby]'s grip!"), null, null, 5) - pulledby.stop_pulling() - return 1 - if(moving_resist && client) //we resisted by trying to move - visible_message(SPAN_DANGER("[src] struggles to break free of [pulledby]'s grip!"), null, null, 5) - client.next_movement = world.time + (10*pulledby.grab_level) + client.move_delay - else + // vars for checks of strengh + var/pulledby_is_strong = HAS_TRAIT(pulledby, TRAIT_SUPER_STRONG) + var/src_is_strong = HAS_TRAIT(src, TRAIT_SUPER_STRONG) + + if(!pulledby.grab_level && (!pulledby_is_strong || src_is_strong)) // if passive grab, check if puller is stronger than src, and if not, break free pulledby.stop_pulling() - return 1 + return TRUE + // Chance for person to break free of grip, defaults to 50. + var/chance = 50 + if(src_is_strong && !isxeno(pulledby)) // no extra chance to resist warrior grabs + chance += 30 // you are strong, you can overpower them easier + if(pulledby_is_strong) + chance -= 30 // stronger grip + // above code means that if you are super strong, 80% chance to resist, otherwise, 20 percent. if both are super strong, standard 50. + + if(prob(chance)) + playsound(loc, 'sound/weapons/thudswoosh.ogg', 25, 1, 7) + visible_message(SPAN_DANGER("[src] has broken free of [pulledby]'s grip!"), max_distance = 5) + pulledby.stop_pulling() + return TRUE + if(moving_resist && client) //we resisted by trying to move + visible_message(SPAN_DANGER("[src] struggles to break free of [pulledby]'s grip!"), max_distance = 5) + // +1 delay if super strong, also done as passive grabs would have a modifier of 0 otherwise, causing spam + if(pulledby_is_strong && !src_is_strong) + client.next_movement = world.time + (10*(pulledby.grab_level + 1)) + client.move_delay + else + client.next_movement = world.time + (10*pulledby.grab_level) + client.move_delay /mob/living/movement_delay() . = ..() From 724f306298c1fb79c0b7b0095fb4e23620de5081 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Sat, 6 Apr 2024 08:43:59 +0100 Subject: [PATCH 06/32] Automatic changelog for PR #6020 [ci skip] --- html/changelogs/AutoChangeLog-pr-6020.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-6020.yml diff --git a/html/changelogs/AutoChangeLog-pr-6020.yml b/html/changelogs/AutoChangeLog-pr-6020.yml new file mode 100644 index 000000000000..3ac915900c1e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-6020.yml @@ -0,0 +1,5 @@ +author: "Ben10083" +delete-after: True +changes: + - balance: "Mobs with super strength now have an advantage when resisting of a grab is done, both as the grabber and the one being grabbed (Xenos not affected, works as before)." + - balance: "Mobs with super strength no longer have their passive grabs a guaranteed resist (unless both super)." \ No newline at end of file From 0657af97b701d4a910353dd1323281380bc05599 Mon Sep 17 00:00:00 2001 From: Drathek <76988376+Drulikar@users.noreply.github.com> Date: Sat, 6 Apr 2024 01:15:41 -0700 Subject: [PATCH 07/32] Fix runtimes when sending messages for ERT objectives (#6085) # About the pull request This PR fixes ERTs that were sending objectives to the player using an incorrect proc reference. # Explain why it's good for the game Objectives are intended to be given to the player. Fixes ![image](https://github.com/cmss13-devs/cmss13/assets/76988376/27a4f149-5d7c-436e-a501-c49f414db878) # Testing Photographs and Procedure
Screenshots & Videos ![image](https://github.com/cmss13-devs/cmss13/assets/76988376/20ab18c6-87e7-4765-a55a-88093ebb23e9)
# Changelog :cl: Drathek fix: Fixed objectives not getting displayed for CMB and cultist ERTs. /:cl: --- code/datums/emergency_calls/cmb.dm | 4 ++-- code/datums/emergency_calls/inspection.dm | 4 ++-- code/datums/emergency_calls/xeno_cultists.dm | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/code/datums/emergency_calls/cmb.dm b/code/datums/emergency_calls/cmb.dm index feb31cf0fe16..bbe2e161842a 100644 --- a/code/datums/emergency_calls/cmb.dm +++ b/code/datums/emergency_calls/cmb.dm @@ -54,7 +54,7 @@ print_backstory(mob) - addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(to_chat), mob, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) /datum/emergency_call/cmb/print_backstory(mob/living/carbon/human/M) @@ -160,7 +160,7 @@ print_backstory(mob) - addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(to_chat), mob, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) /datum/emergency_call/cmb/anchorpoint/print_backstory(mob/living/carbon/human/M) diff --git a/code/datums/emergency_calls/inspection.dm b/code/datums/emergency_calls/inspection.dm index 031a9f210761..e473466f4fb8 100644 --- a/code/datums/emergency_calls/inspection.dm +++ b/code/datums/emergency_calls/inspection.dm @@ -258,7 +258,7 @@ print_backstory(mob) - addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(to_chat), mob, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) /datum/emergency_call/inspection_cmb/print_backstory(mob/living/carbon/human/M) @@ -341,4 +341,4 @@ print_backstory(mob) - addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(to_chat), mob, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) diff --git a/code/datums/emergency_calls/xeno_cultists.dm b/code/datums/emergency_calls/xeno_cultists.dm index f112511b5e22..5a69c4002105 100644 --- a/code/datums/emergency_calls/xeno_cultists.dm +++ b/code/datums/emergency_calls/xeno_cultists.dm @@ -34,4 +34,4 @@ arm_equipment(H, /datum/equipment_preset/other/xeno_cultist, TRUE, TRUE) print_backstory(H) - addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(to_chat), H, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) + addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), H, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS) From 00df7a1a85a3e850df6c421bf0e41e8e199aad82 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Sat, 6 Apr 2024 09:22:18 +0100 Subject: [PATCH 08/32] Automatic changelog for PR #6085 [ci skip] --- html/changelogs/AutoChangeLog-pr-6085.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-6085.yml diff --git a/html/changelogs/AutoChangeLog-pr-6085.yml b/html/changelogs/AutoChangeLog-pr-6085.yml new file mode 100644 index 000000000000..c6891e04a6f4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-6085.yml @@ -0,0 +1,4 @@ +author: "Drathek" +delete-after: True +changes: + - bugfix: "Fixed objectives not getting displayed for CMB and cultist ERTs." \ No newline at end of file From b313d95d05220b36b1246f92e698d19b74a9402b Mon Sep 17 00:00:00 2001 From: NervanCatos <32654903+MobiusWon@users.noreply.github.com> Date: Sat, 6 Apr 2024 03:22:51 -0500 Subject: [PATCH 09/32] No More Prep Raiding (#6083) # About the pull request - Removes access to Marine Prep and Marine Prep Ammo vendors for Cargo Technicians (CT). - Doubles regular ammo in Requisitions to compensate changes and eliminate the need for Cargo Techs to pilfer Marine Prep of all its ammo. - Quartermaster (QM) is unchanged. # Explain why it's good for the game **I would consider this a HOTFIX**, Maintainers update the title as you see fit, I just didn't want to be _that guy_. ### PRIORITY ISSUE: By mid-round of medium pop or higher the ColMarTech Automated Weapons Rack is void of almost all ammo. This is a priority to fix because it _ruins_ the new player experience as they have no ammo to use for their primary ammo before deploying. This causes frustration and can/has led to new players quitting CM before they even got to start. The root causes of this is are: A. CTs raiding the Marine Preps after first drop for more ammo. B. The round scale not reflecting the current population changes and/or ammo expenditures. To fix this CT access has been removed from the Weapons Rack to eliminate the possibility of CTs pilfering the ammo from new players. To compensate, Regular Ammo in Requisitions has been _doubled_ there should no longer be a need to raid Marine Prep for ammo. The QM still has access to the vendor for edge cases where access to the Weapons Rack is needed, but they should not abuse this retention of access. ### SECONDARY ISSUE: There should be no reason for CTs to have to raid the Marine Preps for ammo in the first place, logically this makes no sense. Requisitions is the nexus of all weapons and ammo on the Almayer. For **Regular Ammo** the logistical difficulty should be _getting_ the ammo to the frontlines for resupply, not artificial scarcity of the ammo. This PR will ideally fix this issue as the round start regular ammo count has been doubled. **This value is subject to change.** # Testing Photographs and Procedure
Screenshots & Videos I tested it, they don't have access and the round scale is updated to the new values.
# Changelog :cl: NervanCatos balance: removes CT access to marine prep weapons racks, doubles ammo count of all regular ammo in req to compensate. /:cl: --- .../vending/vendor_types/requisitions.dm | 22 +++++++++---------- .../vendor_types/squad_prep/squad_prep.dm | 2 +- code/modules/gear_presets/uscm_ship.dm | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/code/game/machinery/vending/vendor_types/requisitions.dm b/code/game/machinery/vending/vendor_types/requisitions.dm index 9ce8390095e8..6eb5a333ec81 100644 --- a/code/game/machinery/vending/vendor_types/requisitions.dm +++ b/code/game/machinery/vending/vendor_types/requisitions.dm @@ -208,14 +208,14 @@ /obj/structure/machinery/cm_vending/sorted/cargo_ammo/populate_product_list(scale) listed_products = list( list("REGULAR AMMUNITION", -1, null, null), - list("Box Of Buckshot Shells", round(scale * 20), /obj/item/ammo_magazine/shotgun/buckshot, VENDOR_ITEM_REGULAR), - list("Box Of Flechette Shells", round(scale * 8), /obj/item/ammo_magazine/shotgun/flechette, VENDOR_ITEM_REGULAR), - list("Box Of Shotgun Slugs", round(scale * 20), /obj/item/ammo_magazine/shotgun/slugs, VENDOR_ITEM_REGULAR), - list("M4RA Magazine (10x24mm)", round(scale * 30), /obj/item/ammo_magazine/rifle/m4ra, VENDOR_ITEM_REGULAR), - list("M41A MK2 Magazine (10x24mm)", round(scale * 50), /obj/item/ammo_magazine/rifle, VENDOR_ITEM_REGULAR), - list("M39 HV Magazine (10x20mm)", round(scale * 50), /obj/item/ammo_magazine/smg/m39, VENDOR_ITEM_REGULAR), - list("M44 Speed Loader (.44)", round(scale * 40), /obj/item/ammo_magazine/revolver, VENDOR_ITEM_REGULAR), - list("M4A3 Magazine (9mm)", round(scale * 50), /obj/item/ammo_magazine/pistol, VENDOR_ITEM_REGULAR), + list("Box Of Buckshot Shells", round(scale * 40), /obj/item/ammo_magazine/shotgun/buckshot, VENDOR_ITEM_REGULAR), + list("Box Of Flechette Shells", round(scale * 40), /obj/item/ammo_magazine/shotgun/flechette, VENDOR_ITEM_REGULAR), + list("Box Of Shotgun Slugs", round(scale * 40), /obj/item/ammo_magazine/shotgun/slugs, VENDOR_ITEM_REGULAR), + list("M4RA Magazine (10x24mm)", round(scale * 60), /obj/item/ammo_magazine/rifle/m4ra, VENDOR_ITEM_REGULAR), + list("M41A MK2 Magazine (10x24mm)", round(scale * 100), /obj/item/ammo_magazine/rifle, VENDOR_ITEM_REGULAR), + list("M39 HV Magazine (10x20mm)", round(scale * 100), /obj/item/ammo_magazine/smg/m39, VENDOR_ITEM_REGULAR), + list("M44 Speed Loader (.44)", round(scale * 80), /obj/item/ammo_magazine/revolver, VENDOR_ITEM_REGULAR), + list("M4A3 Magazine (9mm)", round(scale * 100), /obj/item/ammo_magazine/pistol, VENDOR_ITEM_REGULAR), list("ARMOR-PIERCING AMMUNITION", -1, null, null), list("88 Mod 4 AP Magazine (9mm)", round(scale * 50), /obj/item/ammo_magazine/pistol/mod88, VENDOR_ITEM_REGULAR), @@ -248,9 +248,9 @@ list("XM51 Magazine (16g)", round(scale * 3), /obj/item/ammo_magazine/rifle/xm51, VENDOR_ITEM_REGULAR), list("SHOTGUN SHELL BOXES", -1, null, null), - list("Shotgun Shell Box (Buckshot x 100)", round(scale * 2), /obj/item/ammo_box/magazine/shotgun/buckshot, VENDOR_ITEM_REGULAR), - list("Shotgun Shell Box (Flechette x 100)", round(scale * 2), /obj/item/ammo_box/magazine/shotgun/flechette, VENDOR_ITEM_REGULAR), - list("Shotgun Shell Box (Slugs x 100)", round(scale * 2), /obj/item/ammo_box/magazine/shotgun, VENDOR_ITEM_REGULAR), + list("Shotgun Shell Box (Buckshot x 100)", round(scale * 4), /obj/item/ammo_box/magazine/shotgun/buckshot, VENDOR_ITEM_REGULAR), + list("Shotgun Shell Box (Flechette x 100)", round(scale * 4), /obj/item/ammo_box/magazine/shotgun/flechette, VENDOR_ITEM_REGULAR), + list("Shotgun Shell Box (Slugs x 100)", round(scale * 4), /obj/item/ammo_box/magazine/shotgun, VENDOR_ITEM_REGULAR), list("Shotgun Shell Box (16g) (Breaching x 120)", 1, /obj/item/ammo_box/magazine/shotgun/light/breaching, VENDOR_ITEM_REGULAR), ) diff --git a/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm b/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm index 2736de3a981d..d3662c785890 100644 --- a/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm +++ b/code/game/machinery/vending/vendor_types/squad_prep/squad_prep.dm @@ -7,7 +7,7 @@ desc = "An automated weapon rack hooked up to a big storage of standard-issue weapons." icon_state = "guns" req_access = list() - req_one_access = list(ACCESS_MARINE_DATABASE, ACCESS_MARINE_PREP, ACCESS_MARINE_CARGO) + req_one_access = list(ACCESS_MARINE_DATABASE, ACCESS_MARINE_PREP) hackable = TRUE vend_flags = VEND_CLUTTER_PROTECTION | VEND_LIMITED_INVENTORY | VEND_TO_HAND diff --git a/code/modules/gear_presets/uscm_ship.dm b/code/modules/gear_presets/uscm_ship.dm index f817d7d421fa..cda77b4dd4f4 100644 --- a/code/modules/gear_presets/uscm_ship.dm +++ b/code/modules/gear_presets/uscm_ship.dm @@ -359,7 +359,7 @@ name = "USCM Cargo Technician (CT)" flags = EQUIPMENT_PRESET_START_OF_ROUND|EQUIPMENT_PRESET_MARINE - access = list(ACCESS_MARINE_CARGO, ACCESS_MARINE_PREP) + access = list(ACCESS_MARINE_CARGO) assignment = JOB_CARGO_TECH rank = JOB_CARGO_TECH paygrade = PAY_SHORT_ME2 From 44fa600808d263e08534d4902d6f77cc8f375bbe Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Sat, 6 Apr 2024 09:29:09 +0100 Subject: [PATCH 10/32] Automatic changelog for PR #6083 [ci skip] --- html/changelogs/AutoChangeLog-pr-6083.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-6083.yml diff --git a/html/changelogs/AutoChangeLog-pr-6083.yml b/html/changelogs/AutoChangeLog-pr-6083.yml new file mode 100644 index 000000000000..fa5606b7d685 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-6083.yml @@ -0,0 +1,4 @@ +author: "NervanCatos" +delete-after: True +changes: + - balance: "removes CT access to marine prep weapons racks, doubles ammo count of all regular ammo in req to compensate." \ No newline at end of file From 3e242330f74f4d04a7144bc4b9063ff272536efa Mon Sep 17 00:00:00 2001 From: forest2001 <41653574+realforest2001@users.noreply.github.com> Date: Sat, 6 Apr 2024 09:33:14 +0100 Subject: [PATCH 11/32] Project ARES: Supply Drop logging. (#6084) # About the pull request Adds ARES Interface (& staff) logs for launching Req supply drops. # Explain why it's good for the game I don't know how we never added staff logs for this, so here we go. ARES just makes it more useful from an IC perspective. # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: add: Added ARES logging for launching supply drops. admin: Added staff logs for launching supply drops. /:cl: --- code/game/supplyshuttle.dm | 20 +++++++++++--------- code/modules/cm_marines/overwatch.dm | 16 +++++++++------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm index c4698e5722c5..482139c03707 100644 --- a/code/game/supplyshuttle.dm +++ b/code/game/supplyshuttle.dm @@ -289,8 +289,8 @@ GLOBAL_DATUM_INIT(supply_controller, /datum/controller/supply, new()) /obj/structure/machinery/computer/supply_drop_console/proc/handle_supplydrop() SHOULD_NOT_SLEEP(TRUE) - var/obj/structure/closet/crate/C = check_pad() - if(!C) + var/obj/structure/closet/crate/crate = check_pad() + if(!crate) to_chat(usr, "[icon2html(src, usr)] [SPAN_WARNING("No crate was detected on the drop pad. Get Requisitions on the line!")]") return @@ -316,19 +316,21 @@ GLOBAL_DATUM_INIT(supply_controller, /datum/controller/supply, new()) to_chat(usr, "[icon2html(src, usr)] [SPAN_WARNING("The landing zone appears to be obstructed or out of bounds. Package would be lost on drop.")]") return - C.visible_message(SPAN_WARNING("\The [C] loads into a launch tube. Stand clear!")) - current_squad.send_message("'[C.name]' supply drop incoming. Heads up!") - current_squad.send_maptext(C.name, "Incoming Supply Drop:") + crate.visible_message(SPAN_WARNING("\The [crate] loads into a launch tube. Stand clear!")) + current_squad.send_message("'[crate.name]' supply drop incoming. Heads up!") + current_squad.send_maptext(crate.name, "Incoming Supply Drop:") COOLDOWN_START(src, next_fire, drop_cooldown) if(ismob(usr)) var/mob/M = usr M.count_niche_stat(STATISTICS_NICHE_CRATES) - playsound(C.loc,'sound/effects/bamf.ogg', 50, 1) //Ehh - var/obj/structure/droppod/supply/pod = new(null, C) - C.forceMove(pod) + playsound(crate.loc,'sound/effects/bamf.ogg', 50, 1) //Ehh + var/obj/structure/droppod/supply/pod = new(null, crate) + crate.forceMove(pod) pod.launch(T) - visible_message("[icon2html(src, viewers(src))] [SPAN_BOLDNOTICE("'[C.name]' supply drop launched! Another launch will be available in five minutes.")]") + log_ares_requisition("Supply Drop", "Launch [crate.name] to X[x_supply], Y[y_supply].", usr.real_name) + log_game("[key_name(usr)] launched supply drop '[crate.name]' to X[x_coord], Y[y_coord].") + visible_message("[icon2html(src, viewers(src))] [SPAN_BOLDNOTICE("'[crate.name]' supply drop launched! Another launch will be available in five minutes.")]") //A limited version of the above console //Can't pick squads, drops less often diff --git a/code/modules/cm_marines/overwatch.dm b/code/modules/cm_marines/overwatch.dm index e68ef467faa9..9232f26ade4b 100644 --- a/code/modules/cm_marines/overwatch.dm +++ b/code/modules/cm_marines/overwatch.dm @@ -816,8 +816,8 @@ to_chat(usr, "[icon2html(src, usr)] [SPAN_WARNING("The [name] is busy processing another action!")]") return - var/obj/structure/closet/crate/C = locate() in current_squad.drop_pad.loc //This thing should ALWAYS exist. - if(!istype(C)) + var/obj/structure/closet/crate/crate = locate() in current_squad.drop_pad.loc //This thing should ALWAYS exist. + if(!istype(crate)) to_chat(usr, "[icon2html(src, usr)] [SPAN_WARNING("No crate was detected on the drop pad. Get Requisitions on the line!")]") return @@ -844,17 +844,19 @@ return busy = TRUE - C.visible_message(SPAN_WARNING("\The [C] loads into a launch tube. Stand clear!")) - SEND_SIGNAL(C, COMSIG_STRUCTURE_CRATE_SQUAD_LAUNCHED, current_squad) + crate.visible_message(SPAN_WARNING("\The [crate] loads into a launch tube. Stand clear!")) + SEND_SIGNAL(crate, COMSIG_STRUCTURE_CRATE_SQUAD_LAUNCHED, current_squad) COOLDOWN_START(current_squad, next_supplydrop, 500 SECONDS) if(ismob(usr)) var/mob/M = usr M.count_niche_stat(STATISTICS_NICHE_CRATES) - playsound(C.loc,'sound/effects/bamf.ogg', 50, 1) //Ehh - var/obj/structure/droppod/supply/pod = new(null, C) + playsound(crate.loc,'sound/effects/bamf.ogg', 50, 1) //Ehh + var/obj/structure/droppod/supply/pod = new(null, crate) pod.launch(T) - visible_message("[icon2html(src, viewers(src))] [SPAN_BOLDNOTICE("'[C.name]' supply drop launched! Another launch will be available in five minutes.")]") + log_ares_requisition("Supply Drop", "Launch [crate.name] to X[x_supply], Y[y_supply].", usr.real_name) + log_game("[key_name(usr)] launched supply drop '[crate.name]' to X[x_coord], Y[y_coord].") + visible_message("[icon2html(src, viewers(src))] [SPAN_BOLDNOTICE("'[crate.name]' supply drop launched! Another launch will be available in five minutes.")]") busy = FALSE /obj/structure/machinery/computer/overwatch/almayer From 5be8f2950fa5565ceca6c6e394cc39186996cacc Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Sat, 6 Apr 2024 09:38:28 +0100 Subject: [PATCH 12/32] Automatic changelog for PR #6084 [ci skip] --- html/changelogs/AutoChangeLog-pr-6084.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-6084.yml diff --git a/html/changelogs/AutoChangeLog-pr-6084.yml b/html/changelogs/AutoChangeLog-pr-6084.yml new file mode 100644 index 000000000000..7ade3258f5ad --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-6084.yml @@ -0,0 +1,5 @@ +author: "realforest2001" +delete-after: True +changes: + - rscadd: "Added ARES logging for launching supply drops." + - admin: "Added staff logs for launching supply drops." \ No newline at end of file From 9b9ab1fd34c17c85a90d26cf951f5d9cca061388 Mon Sep 17 00:00:00 2001 From: cuberound <122645057+cuberound@users.noreply.github.com> Date: Sat, 6 Apr 2024 11:12:53 +0200 Subject: [PATCH 13/32] Faster snow removal for bigger xenomorphs (#6002) # About the pull request makes the snow removal dependant of xenomorph size, making it 1,5 ( lesser) to 4 times (big xenos) faster ( still takes a while even for the largest xenos to remove deap snow) # Explain why it's good for the game removing snow is painful job that makes maps with snow unwanted, huge xenomorphs should not have that hard time showeling some snow out of their way, makes it fair with the flames removing snow PR # Testing Photographs and Procedure
Screenshots & Videos Put screenshots and videos here with an empty line between the screenshots and the `
` tags.
# Changelog :cl: balance: greatly decreses snow removal time, now it depends on xenomorph size /:cl: --------- Co-authored-by: vincibrv --- code/game/turfs/auto_turf.dm | 3 ++- code/modules/mob/living/carbon/xenomorph/attack_alien.dm | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/code/game/turfs/auto_turf.dm b/code/game/turfs/auto_turf.dm index e07f7324bcc2..b1a956abf756 100644 --- a/code/game/turfs/auto_turf.dm +++ b/code/game/turfs/auto_turf.dm @@ -198,7 +198,8 @@ while(bleed_layer > 0) xeno_attack_delay(M) - if(!do_after(M, 12, INTERRUPT_ALL, BUSY_ICON_FRIENDLY)) + var/size = max(M.mob_size, 1) + if(!do_after(M, 12/size, INTERRUPT_ALL, BUSY_ICON_FRIENDLY)) return XENO_NO_DELAY_ACTION if(!bleed_layer) diff --git a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm index 56f908389966..c37a823fd0c5 100644 --- a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm +++ b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm @@ -878,7 +878,8 @@ while(bleed_layer > 0) xeno_attack_delay(M) - if(!do_after(M, 12, INTERRUPT_ALL, BUSY_ICON_FRIENDLY)) + var/size = max(M.mob_size, 1) + if(!do_after(M, 12/size, INTERRUPT_ALL, BUSY_ICON_FRIENDLY)) return XENO_NO_DELAY_ACTION if(!bleed_layer) From 62e94d5ec247a99ac620d411dcdd71b4212995c5 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Sat, 6 Apr 2024 10:17:44 +0100 Subject: [PATCH 14/32] Automatic changelog for PR #6002 [ci skip] --- html/changelogs/AutoChangeLog-pr-6002.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-6002.yml diff --git a/html/changelogs/AutoChangeLog-pr-6002.yml b/html/changelogs/AutoChangeLog-pr-6002.yml new file mode 100644 index 000000000000..86ff28a01a49 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-6002.yml @@ -0,0 +1,4 @@ +author: "cuberound" +delete-after: True +changes: + - balance: "greatly decreses snow removal time, now it depends on xenomorph size" \ No newline at end of file From 9101bfebd6ae03783e5846d15013115a9834be34 Mon Sep 17 00:00:00 2001 From: cuberound <122645057+cuberound@users.noreply.github.com> Date: Sat, 6 Apr 2024 12:44:41 +0200 Subject: [PATCH 15/32] Tactical reload does not get canceled by movement (#6086) # About the pull request allows movement during tactical reload # 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: balance: allows movement during tactical reload (to perform tactical reload click and drag from a magazine to gun in your hand) /:cl: --------- Co-authored-by: vincibrv --- code/modules/projectiles/gun_helpers.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/projectiles/gun_helpers.dm b/code/modules/projectiles/gun_helpers.dm index 781db8fc1222..1f407081f033 100644 --- a/code/modules/projectiles/gun_helpers.dm +++ b/code/modules/projectiles/gun_helpers.dm @@ -312,7 +312,7 @@ DEFINES in setup.dm, referenced here. var/tac_reload_time = 15 if(user.skills) tac_reload_time = max(15 - 5*user.skills.get_skill_level(SKILL_FIREARMS), 5) - if(do_after(user,tac_reload_time, INTERRUPT_ALL, BUSY_ICON_FRIENDLY) && magazine.loc == old_mag_loc && !current_mag) + if(do_after(user,tac_reload_time, (INTERRUPT_ALL & (~INTERRUPT_MOVED)) , BUSY_ICON_FRIENDLY) && magazine.loc == old_mag_loc && !current_mag) if(isstorage(magazine.loc)) var/obj/item/storage/master_storage = magazine.loc master_storage.remove_from_storage(magazine) From 13c8dedb732f1d36f43c11f8c9deddcca94a2332 Mon Sep 17 00:00:00 2001 From: cm13-github <128137806+cm13-github@users.noreply.github.com> Date: Sat, 6 Apr 2024 11:51:42 +0100 Subject: [PATCH 16/32] Automatic changelog for PR #6086 [ci skip] --- html/changelogs/AutoChangeLog-pr-6086.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-6086.yml diff --git a/html/changelogs/AutoChangeLog-pr-6086.yml b/html/changelogs/AutoChangeLog-pr-6086.yml new file mode 100644 index 000000000000..6802ba287e84 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-6086.yml @@ -0,0 +1,4 @@ +author: "cuberound" +delete-after: True +changes: + - balance: "allows movement during tactical reload (to perform tactical reload click and drag from a magazine to gun in your hand)" \ No newline at end of file From f923f9f2f5d108a79e30993eb1e8abda16f708b2 Mon Sep 17 00:00:00 2001 From: Drathek <76988376+Drulikar@users.noreply.github.com> Date: Sat, 6 Apr 2024 03:53:35 -0700 Subject: [PATCH 17/32] Cryo Tube Rework (#6058) # About the pull request This PR reworks the cryotubes. The effect of diluting or multiplying chemicals is no longer possible, but now the use of cryoxadone or clonexadone in a cryotube can allow chemicals to process in the dead. Ultimately usage of the cryo chemicals will be much higher, and you need to be careful not to introduce too many chemicals into your patient because the dosage is 5u whenever cryoxadone or clonexadone is available and can be administered. Cryotubes also now actually require power, update their icon if they lose power, and use the two-ping sfx for warnings (such as now warnings as the patient's revive timer is running out). For the critical messages, it will make an alert if the patient is dead, then once they hit the 50% mark (2.5 mins), then at the 1 minute mark. See testing for a demonstration. # Explain why it's good for the game Cryotubes in general are very underused with the exception of exploiting how it can multiply chemicals. This should give them a unique feature to medbay. It is likely that this may prove to be too powerful, but it puts more demand on chemistry to provide the cryoxadone or clonexadone in order to do so. # Testing Photographs and Procedure
Screenshots & Videos Initial testing: https://youtu.be/PA43YvzDRVM Critical (dead state) alert testing: https://youtu.be/PLjQxzv28l8 Notification changes: ![release](https://github.com/cmss13-devs/cmss13/assets/76988376/325e852a-79ee-4a68-9c3c-cd9001f6cc0f) Power fixes: ![power](https://github.com/cmss13-devs/cmss13/assets/76988376/afd952eb-3004-4c91-b255-83aa98fd539f)
# Changelog :cl: Drathek balance: Cryotubes no longer multiply chemicals. balance: Cryotubes can now allow chemicals to process in dead if cryoxadone or clonexadone is present. fix: Fixed cryotubes not actually updating their icons/power usage when they become unpowered. fix: Fixed cryotubes healing despite inoperable. fix: The cryotube Eject Occupant verb now works for people other than the occupant (useful if inoperable) ui: Cryotubes can optionally announce again on the medical channel. /:cl: --- code/game/machinery/cryo.dm | 193 ++++++++++++------ code/game/objects/objs.dm | 52 +++-- .../human/life/handle_chemicals_in_body.dm | 30 ++- tgui/packages/tgui/interfaces/Cryo.jsx | 27 ++- 4 files changed, 201 insertions(+), 101 deletions(-) diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm index afcc9686cff5..6643cd6b805c 100644 --- a/code/game/machinery/cryo.dm +++ b/code/game/machinery/cryo.dm @@ -1,4 +1,8 @@ #define HEAT_CAPACITY_HUMAN 100 //249840 J/K, for a 72 kg person. +#define DEATH_STAGE_NONE 0 +#define DEATH_STAGE_EARLY 1 +#define DEATH_STAGE_WARNING 2 +#define DEATH_STAGE_CRITICAL 3 /obj/structure/machinery/cryo_cell name = "cryo cell" @@ -19,6 +23,7 @@ var/mob/living/carbon/occupant = null var/obj/item/reagent_container/glass/beaker = null + var/occupant_death_stage = DEATH_STAGE_NONE /obj/structure/machinery/cryo_cell/Initialize() . = ..() @@ -28,19 +33,18 @@ QDEL_NULL(beaker) . = ..() - /obj/structure/machinery/cryo_cell/process() if(!on) updateUsrDialog() return if(occupant) - if(occupant.stat != DEAD) - process_occupant() - else + var/mob/living/carbon/human/human_occupant = occupant + if(occupant.stat == DEAD && (!istype(human_occupant) || human_occupant.undefibbable)) go_out(TRUE, TRUE) //Whether auto-eject is on or not, we don't permit literal deadbeats to hang around. - playsound(src.loc, 'sound/machines/ping.ogg', 25, 1) - visible_message("[icon2html(src, viewers(src))] [SPAN_WARNING("\The [src] pings: Patient is dead!")]") + display_message("Patient is dead!", warning = TRUE) + else + process_occupant() updateUsrDialog() return TRUE @@ -116,13 +120,14 @@ data["beakerContents"] = beakerContents return data -/obj/structure/machinery/cryo_cell/ui_act(action, list/params) +/obj/structure/machinery/cryo_cell/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() if(.) return switch(action) if("power") on = !on + update_use_power(on ? USE_POWER_ACTIVE : USE_POWER_IDLE) update_icon() . = TRUE if("eject") @@ -143,7 +148,8 @@ if("notice") release_notice = !release_notice . = TRUE - updateUsrDialog() + + updateUsrDialog(ui.user) /obj/structure/machinery/cryo_cell/attackby(obj/item/W, mob/living/user) if(istype(W, /obj/item/reagent_container/glass)) @@ -158,34 +164,59 @@ beaker = W var/reagentnames = "" - for(var/datum/reagent/R in beaker.reagents.reagent_list) - reagentnames += ";[R.name]" + for(var/datum/reagent/cur_reagent in beaker.reagents.reagent_list) + reagentnames += ";[cur_reagent.name]" - msg_admin_niche("[key_name(user)] put \a [beaker] into \the [src], containing [reagentnames] at ([src.loc.x],[src.loc.y],[src.loc.z]) [ADMIN_JMP(src.loc)].", 1) + msg_admin_niche("[key_name(user)] put \a [beaker] into [src], containing [reagentnames] at ([src.loc.x],[src.loc.y],[src.loc.z]) [ADMIN_JMP(src.loc)].", 1) if(user.drop_inv_item_to_loc(W, src)) - user.visible_message("[user] adds \a [W] to \the [src]!", "You add \a [W] to \the [src]!") + user.visible_message("[user] adds \a [W] to [src]!", "You add \a [W] to [src]!") else if(istype(W, /obj/item/grab)) - if(isxeno(user)) return - var/obj/item/grab/G = W - if(!ismob(G.grabbed_thing)) + if(isxeno(user)) + return + var/obj/item/grab/grabber = W + if(!ismob(grabber.grabbed_thing)) return - var/mob/M = G.grabbed_thing - put_mob(M) + var/mob/grabbed_mob = grabber.grabbed_thing + put_mob(grabbed_mob) - updateUsrDialog() + updateUsrDialog(user) +/obj/structure/machinery/cryo_cell/power_change(area/master_area) + . = ..() + if((occupant || on) && operable()) + update_use_power(USE_POWER_ACTIVE) + update_icon() /obj/structure/machinery/cryo_cell/update_icon() icon_state = initial(icon_state) - icon_state = "[icon_state]-[on ? "on" : "off"]-[occupant ? "occupied" : "empty"]" + var/is_on = on && operable() + icon_state = "[icon_state]-[is_on ? "on" : "off"]-[occupant ? "occupied" : "empty"]" /obj/structure/machinery/cryo_cell/proc/process_occupant() - if(occupant) - if(occupant.stat == DEAD) - return - occupant.bodytemperature += 2*(temperature - occupant.bodytemperature) - occupant.bodytemperature = max(occupant.bodytemperature, temperature) // this is so ugly i'm sorry for doing it i'll fix it later i promise + if(!occupant) + return + if(!operable()) + return + + occupant.bodytemperature += 2*(temperature - occupant.bodytemperature) + occupant.bodytemperature = max(occupant.bodytemperature, temperature) // this is so ugly i'm sorry for doing it i'll fix it later i promise + + // Warnings if dead + if(occupant.stat == DEAD && ishuman(occupant)) + var/mob/living/carbon/human/human_occupant = occupant + var/old_state = occupant_death_stage + if(world.time > occupant.timeofdeath + human_occupant.revive_grace_period - 1 MINUTES) + occupant_death_stage = DEATH_STAGE_CRITICAL + else if(world.time > occupant.timeofdeath + human_occupant.revive_grace_period - 2.5 MINUTES) + occupant_death_stage = DEATH_STAGE_WARNING + else + occupant_death_stage = DEATH_STAGE_EARLY + if(old_state != occupant_death_stage) + display_message("Patient is critical!", warning = TRUE) + + // Passive healing if alive and cold enough + if(occupant.stat != DEAD) occupant.recalculate_move_delay = TRUE occupant.set_stat(UNCONSCIOUS) if(occupant.bodytemperature < T0C) @@ -202,22 +233,39 @@ var/heal_brute = occupant.getBruteLoss() ? min(1, 20/occupant.getBruteLoss()) : 0 var/heal_fire = occupant.getFireLoss() ? min(1, 20/occupant.getFireLoss()) : 0 occupant.heal_limb_damage(heal_brute,heal_fire) - var/has_cryo = occupant.reagents.get_reagent_amount("cryoxadone") >= 1 - var/has_clonexa = occupant.reagents.get_reagent_amount("clonexadone") >= 1 - var/has_cryo_medicine = has_cryo || has_clonexa - if(beaker && !has_cryo_medicine) - beaker.reagents.trans_to(occupant, 1, 10) + + // Chemical healing if cryo meds are involved + if(beaker && occupant.reagents && beaker.reagents) + var/occupant_has_cryo_meds = occupant.reagents.get_reagent_amount("cryoxadone") >= 1 || occupant.reagents.get_reagent_amount("clonexadone") >= 1 + var/beaker_has_cryo_meds = beaker.reagents.get_reagent_amount("cryoxadone") >= 1 || beaker.reagents.get_reagent_amount("clonexadone") >= 1 + + // To administer, either the occupant has cryo meds and the beaker doesn't or vice versa (not both) + var/can_administer = (occupant_has_cryo_meds ^ beaker_has_cryo_meds) && length(beaker.reagents.reagent_list) + if(can_administer && occupant_has_cryo_meds) + // If its the case of the occupant has cryo meds and not the beaker, we need to pace out the dosage + // So lets make sure they don't already have some of the beaker drugs + for(var/datum/reagent/cur_beaker_reagent in beaker.reagents.reagent_list) + for(var/datum/reagent/cur_occupant_reagent in occupant.reagents.reagent_list) + if(cur_beaker_reagent.id == cur_occupant_reagent.id) + can_administer = FALSE + break + + if(can_administer) + beaker.reagents.trans_to(occupant, 5) beaker.reagents.reaction(occupant) - if(!occupant.getBruteLoss(TRUE) && !occupant.getFireLoss(TRUE) && !occupant.getCloneLoss() && autoeject) //release the patient automatically when brute and burn are handled on non-robotic limbs - display_message("external wounds are") + + if(autoeject) + //release the patient automatically when brute and burn are handled on non-robotic limbs + if(!occupant.getBruteLoss(TRUE) && !occupant.getFireLoss(TRUE) && !occupant.getCloneLoss()) + display_message("Patient's external wounds are healed.") go_out(TRUE) return - if(occupant.health >= 100 && autoeject) - display_message("external wounds are") + if(occupant.health >= occupant.maxHealth) + display_message("Patient's external wounds are healed.") go_out(TRUE) return -/obj/structure/machinery/cryo_cell/proc/go_out(auto_eject = null, dead = null) +/obj/structure/machinery/cryo_cell/proc/go_out(auto_eject = FALSE, dead = FALSE) if(!(occupant)) return if(occupant.client) @@ -235,66 +283,72 @@ if(occupant.bodytemperature < 261 && occupant.bodytemperature >= 70) occupant.bodytemperature = 261 occupant.recalculate_move_delay = TRUE - occupant = null if(auto_eject) //Turn off and announce if auto-ejected because patient is recovered or dead. on = FALSE if(release_notice) //If auto-release notices are on as it should be, let the doctors know what's up - playsound(src.loc, 'sound/machines/ping.ogg', 100, 14) - var/reason = "Reason for release: Patient recovery." + var/reason = "Reason for release: Patient recovery." if(dead) - reason = "Reason for release: Patient death." - ai_silent_announcement("Patient [occupant] has been automatically released from \the [src] at: [get_area(occupant)]. [reason]", MED_FREQ) + reason = "Reason for release: Patient death." + ai_silent_announcement("Patient [occupant] has been automatically released from [src] at: [sanitize_area((get_area(occupant))?.name)]. [reason]", ":m") + occupant = null update_use_power(USE_POWER_IDLE) update_icon() return -/obj/structure/machinery/cryo_cell/proc/put_mob(mob/living/carbon/M as mob) +/obj/structure/machinery/cryo_cell/proc/put_mob(mob/living/carbon/cur_mob) if(inoperable()) to_chat(usr, SPAN_DANGER("The cryo cell is not functioning.")) return - if(!istype(M) || isxeno(M)) - to_chat(usr, SPAN_DANGER("The cryo cell cannot handle such a lifeform!")) + if(!istype(cur_mob) || isxeno(cur_mob)) + to_chat(usr, SPAN_DANGER("The cryo cell cannot handle such a lifeform!")) return if(occupant) - to_chat(usr, SPAN_DANGER("The cryo cell is already occupied!")) + to_chat(usr, SPAN_DANGER("The cryo cell is already occupied!")) return - if(M.abiotic()) + if(cur_mob.abiotic()) to_chat(usr, SPAN_DANGER("Subject may not have abiotic items on.")) return - if(do_after(usr, 20, INTERRUPT_NO_NEEDHAND, BUSY_ICON_GENERIC)) - to_chat(usr, SPAN_NOTICE("You move [M.name] inside the cryo cell.")) - M.forceMove(src) - if(M.health >= -100 && (M.health <= 0 || M.sleeping)) - to_chat(M, SPAN_NOTICE("You feel cold liquid surround you. Your skin starts to freeze up.")) - occupant = M + if(do_after(usr, 2 SECONDS, INTERRUPT_NO_NEEDHAND, BUSY_ICON_GENERIC)) + visible_message(SPAN_NOTICE("[usr] moves [usr == cur_mob ? "" : "[cur_mob] "]inside the cryo cell.")) + cur_mob.forceMove(src) + if(cur_mob.health >= HEALTH_THRESHOLD_DEAD && (cur_mob.health <= 0 || cur_mob.sleeping)) + to_chat(cur_mob, SPAN_NOTICE("You feel cold liquid surround you. Your skin starts to freeze up.")) + occupant = cur_mob + occupant_death_stage = DEATH_STAGE_NONE update_use_power(USE_POWER_ACTIVE) update_icon() return TRUE -/obj/structure/machinery/cryo_cell/proc/display_message(msg) - playsound(src.loc, 'sound/machines/ping.ogg', 25, 1) - visible_message("[icon2html(src, viewers(src))] [SPAN_NOTICE("\The [src] pings: Patient's " + msg + " healed.")]") +/obj/structure/machinery/cryo_cell/proc/display_message(msg, silent = FALSE, warning = FALSE) + if(!silent) + if(warning) + playsound(loc, 'sound/machines/twobeep.ogg', 40) + else + playsound(loc, 'sound/machines/ping.ogg', 25, 1) + visible_message("[icon2html(src, viewers(src))] [SPAN_NOTICE("[src] [warning ? "beeps" : "pings"]: [msg]")]") /obj/structure/machinery/cryo_cell/verb/move_eject() set name = "Eject occupant" set category = "Object" set src in oview(1) if(usr == occupant)//If the user is inside the tube... - if(usr.stat == 2)//and he's not dead.... + if(usr.stat == DEAD)//and he's not dead.... return - if(alert(usr, "Would you like to activate the ejection sequence of the cryo cell? Healing may be in progress.", "Confirm", "Yes", "No") == "Yes") + if(tgui_alert(usr, "Would you like to activate the ejection sequence of the cryo cell? Healing may be in progress.", "Confirm", list("Yes", "No")) == "Yes") to_chat(usr, SPAN_NOTICE("Cryo cell release sequence activated. This will take thirty seconds.")) - visible_message(SPAN_WARNING ("The cryo cell's tank starts draining as its ejection lights blare!")) - sleep(300) - if(!src || !usr || !occupant || (occupant != usr)) //Check if someone's released/replaced/bombed him already - return - go_out()//and release him from the eternal prison. - else - if(usr.stat != 0) - return - go_out() - return + visible_message(SPAN_WARNING("The cryo cell's tank starts draining as its ejection lights blare!")) + addtimer(CALLBACK(src, PROC_REF(finish_eject), usr), 30 SECONDS, TIMER_UNIQUE|TIMER_NO_HASH_WAIT) + else + if(usr.stat != CONSCIOUS) + return + go_out() + +/obj/structure/machinery/cryo_cell/proc/finish_eject(mob/original) + //Check if someone's released/replaced/bombed him already + if(QDELETED(src) || QDELETED(original) || !occupant || occupant != original) + return + go_out()//and release him from the eternal prison. /obj/structure/machinery/cryo_cell/verb/move_inside() set name = "Move Inside" @@ -309,8 +363,8 @@ //clickdrag code - "resist to get out" code is in living_verbs.dm /obj/structure/machinery/cryo_cell/MouseDrop_T(mob/target, mob/user) . = ..() - var/mob/living/H = user - if(!istype(H) || target != user) //cant make others get in. grab-click for this + var/mob/living/living_mob = user + if(!istype(living_mob) || target != user) //cant make others get in. grab-click for this return put_mob(target) @@ -324,3 +378,8 @@ /datum/data/function/proc/display() return + +#undef DEATH_STAGE_NONE +#undef DEATH_STAGE_EARLY +#undef DEATH_STAGE_WARNING +#undef DEATH_STAGE_CRITICAL diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 8a37eef3ee73..13d1bbaefcf7 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -142,31 +142,39 @@ return "on [t_his] feet" return "...somewhere?" -/obj/proc/updateUsrDialog() - if(in_use) - var/is_in_use = 0 - var/list/nearby = viewers(1, src) - for(var/mob/M in nearby) - if ((M.client && M.interactee == src)) - is_in_use = 1 - attack_hand(M) - if (isSilicon(usr)) - if (!(usr in nearby)) - if (usr.client && usr.interactee==src) // && M.interactee == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh. - is_in_use = 1 - attack_remote(usr) - in_use = is_in_use +/obj/proc/updateUsrDialog(mob/user) + if(!user) + user = usr + if(!in_use || !user) + return + + var/is_in_use = FALSE + var/list/nearby = viewers(1, src) + for(var/mob/cur_mob in nearby) + if(cur_mob.client && cur_mob.interactee == src) + is_in_use = TRUE + attack_hand(cur_mob) + if(isSilicon(user)) + if(!(user in nearby)) + if(user.client && user.interactee == src) // && M.interactee == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh. + is_in_use = TRUE + attack_remote(user) + + in_use = is_in_use /obj/proc/updateDialog() // Check that people are actually using the machine. If not, don't update anymore. - if(in_use) - var/list/nearby = viewers(1, src) - var/is_in_use = 0 - for(var/mob/M in nearby) - if ((M.client && M.interactee == src)) - is_in_use = 1 - src.interact(M) - in_use = is_in_use + if(!in_use) + return + + var/is_in_use = FALSE + var/list/nearby = viewers(1, src) + for(var/mob/cur_mob in nearby) + if(cur_mob.client && cur_mob.interactee == src) + is_in_use = TRUE + interact(cur_mob) + + in_use = is_in_use /obj/proc/interact(mob/user) return diff --git a/code/modules/mob/living/carbon/human/life/handle_chemicals_in_body.dm b/code/modules/mob/living/carbon/human/life/handle_chemicals_in_body.dm index eafac03fd51f..9bf275a5448a 100644 --- a/code/modules/mob/living/carbon/human/life/handle_chemicals_in_body.dm +++ b/code/modules/mob/living/carbon/human/life/handle_chemicals_in_body.dm @@ -39,25 +39,35 @@ SHOULD_NOT_SLEEP(TRUE) if(!reagents || undefibbable) return // Double checking due to Life() funny background=1 - for(var/datum/reagent/generated/R in reagents.reagent_list) + + var/has_cryo_medicine = reagents.get_reagent_amount("cryoxadone") >= 1 || reagents.get_reagent_amount("clonexadone") >= 1 + if(has_cryo_medicine) + var/obj/structure/machinery/cryo_cell/cryo = loc + if(!istype(cryo) || !cryo.on || cryo.inoperable()) + has_cryo_medicine = FALSE + + for(var/datum/reagent/cur_reagent in reagents.reagent_list) + if(!has_cryo_medicine && !istype(cur_reagent, /datum/reagent/generated)) + continue + var/list/mods = list( REAGENT_EFFECT = TRUE, REAGENT_BOOST = FALSE, REAGENT_PURGE = FALSE, - REAGENT_FORCE = FALSE, + REAGENT_FORCE = has_cryo_medicine, REAGENT_CANCEL = FALSE) - for(var/datum/chem_property/P in R.properties) - var/list/A = P.pre_process(src) - if(!A) + for(var/datum/chem_property/cur_prop in cur_reagent.properties) + var/list/results = cur_prop.pre_process(src) + if(!results) continue - for(var/mod in A) - mods[mod] |= A[mod] + for(var/mod in results) + mods[mod] |= results[mod] if(mods[REAGENT_CANCEL]) return if(mods[REAGENT_FORCE]) - R.handle_processing(src, mods, delta_time) - R.holder.remove_reagent(R.id, R.custom_metabolism * delta_time) + cur_reagent.handle_processing(src, mods, delta_time) + cur_reagent.holder.remove_reagent(cur_reagent.id, cur_reagent.custom_metabolism * delta_time) - R.handle_dead_processing(src, mods, delta_time) + cur_reagent.handle_dead_processing(src, mods, delta_time) diff --git a/tgui/packages/tgui/interfaces/Cryo.jsx b/tgui/packages/tgui/interfaces/Cryo.jsx index 338717f2d0ca..be1dce801ada 100644 --- a/tgui/packages/tgui/interfaces/Cryo.jsx +++ b/tgui/packages/tgui/interfaces/Cryo.jsx @@ -34,6 +34,11 @@ export const Cryo = () => { const CryoContent = (props) => { const { act, data } = useBackend(); + + let soundicon = 'volume-high'; + if (!data.notify) { + soundicon = 'volume-xmark'; + } return ( <>
@@ -89,12 +94,30 @@ const CryoContent = (props) => { icon="eject" disabled={!data.hasOccupant} onClick={() => act('eject')} - content="eject patient" + content="Eject Patient" />