mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-13 09:05:11 +01:00
7a3ad79506
## About The Pull Request It's just a partial cleanup of anti-[STYLE](https://github.com/tgstation/tgstation/blob/master/.github/guides/STYLE.md) code from /tg/'s ancient history. I compiled & tested with my helpful assistant and damage is still working. <img width="1920" height="1040" alt="image" src="https://github.com/user-attachments/assets/26dabc17-088f-4008-b299-3ff4c27142c3" /> I'll upload the .cs script I used to do it shortly. ## Why It's Good For The Game Just minor code cleanup. Script used is located at https://metek.tech/camelTo-Snake.7z EDIT 11/23/25: Updated the script to use multithreading and sequential scan so it works a hell of a lot faster ``` /* // Copyright 2025 Joshua 'Joan Metekillot' Kidder This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. // */ using System.Text.RegularExpressions; class Program { static async Task Main(string[] args) { var readFile = new FileStreamOptions { Access = FileAccess.Read, Share = FileShare.ReadWrite, Options = FileOptions.Asynchronous | FileOptions.SequentialScan }; FileStreamOptions writeFile = new FileStreamOptions { Share = FileShare.ReadWrite, Access = FileAccess.ReadWrite, Mode = FileMode.Truncate, Options = FileOptions.Asynchronous }; RegexOptions regexOptions = RegexOptions.Multiline | RegexOptions.Compiled; Dictionary<string, int> changedProcs = new(); string regexPattern = @"(?<=\P{L})([a-z]+)([A-Z]{1,2}[a-z]+)*(Brute|Burn|Fire|Tox|Oxy|Organ|Stamina)(Loss)([A-Z]{1,2}[a-z]+)*"; Regex camelCaseProcRegex = new(regexPattern, regexOptions); string snakeify(Match matchingRegex) { var vals = matchingRegex.Groups.Cast<Group>().SelectMany(_ => _.Captures).Select(_ => _.Value).ToArray(); var newVal = string.Join("_", vals.Skip(1).ToArray()).ToLower(); string logString = $"{vals[0]} => {newVal}"; if (changedProcs.TryGetValue(logString, out int value)) { changedProcs[logString] = value + 1; } else { changedProcs.Add(logString, 1); } return newVal; } var dmFiles = Directory.EnumerateFiles(".", "*.dm", SearchOption.AllDirectories).ToAsyncEnumerable<string>(); // uses default ParallelOptions // https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.paralleloptions?view=net-10.0#main await Parallel.ForEachAsync(dmFiles, async (filePath, UnusedCancellationToken) => { var reader = new StreamReader(filePath, readFile); string oldContent = await reader.ReadToEndAsync(); string newContent = camelCaseProcRegex.Replace(oldContent, new MatchEvaluator((Func<Match, string>)snakeify)); if (oldContent != newContent) { var writer = new StreamWriter(filePath, writeFile); await writer.WriteAsync(newContent); await writer.DisposeAsync(); } reader.Dispose(); }); var logToList = changedProcs.Cast<KeyValuePair<string, int>>().ToList(); foreach (var pair in logToList) { Console.WriteLine($"{pair.Key}: {pair.Value} locations"); } } } ``` ## Changelog 🆑 Bisar code: All (Brute|Burn|Fire|Tox|Oxy|Organ|Stamina)(Loss) procs now use snake_case, in-line with the STYLE guide. Underscores rule! /🆑
192 lines
8.7 KiB
Plaintext
192 lines
8.7 KiB
Plaintext
///Stage two of the heart attack.
|
|
#define ATTACK_STAGE_TWO 100
|
|
///Stage three of the heart attack.
|
|
#define ATTACK_STAGE_THREE 70
|
|
///Stage four of the heart attack.
|
|
#define ATTACK_STAGE_FOUR 35
|
|
///If we reduce heart damage enough, it will recover on its own.
|
|
#define ATTACK_CURE_THRESHOLD 160
|
|
///What is the max oxyloss we're willing to deal, to prevent people from passing out early.
|
|
#define OXYLOSS_MAXIMUM 40
|
|
|
|
/datum/status_effect/heart_attack
|
|
id = "heart_attack"
|
|
remove_on_fullheal = TRUE
|
|
alert_type = null
|
|
///A timer that ticks down until the heart fully stops
|
|
var/time_until_stoppage = 150
|
|
///Does this show up on medhuds?
|
|
var/visible = FALSE
|
|
|
|
/datum/status_effect/heart_attack/on_apply()
|
|
var/mob/living/carbon/human/human_owner = owner
|
|
if(!istype(human_owner) || !human_owner.can_heartattack())
|
|
return FALSE
|
|
RegisterSignal(owner, COMSIG_CARBON_LOSE_ORGAN, PROC_REF(on_organ_removed))
|
|
RegisterSignal(owner, COMSIG_LIVING_MINOR_SHOCK, PROC_REF(minor_shock))
|
|
RegisterSignal(owner, COMSIG_HEARTATTACK_DEFIB, PROC_REF(defib_shock))
|
|
RegisterSignal(owner, COMSIG_LIVING_ELECTROCUTE_ACT, PROC_REF(electrocuted))
|
|
return TRUE
|
|
|
|
/datum/status_effect/heart_attack/on_remove()
|
|
UnregisterSignal(owner, list(COMSIG_CARBON_LOSE_ORGAN, COMSIG_LIVING_MINOR_SHOCK, COMSIG_HEARTATTACK_DEFIB, COMSIG_LIVING_ELECTROCUTE_ACT))
|
|
|
|
/datum/status_effect/heart_attack/tick(seconds_between_ticks)
|
|
var/mob/living/carbon/human/human_owner = owner
|
|
if(!istype(human_owner) || !human_owner.can_heartattack())
|
|
qdel(src) //No heart? No effects.
|
|
return
|
|
|
|
if(time_until_stoppage > ATTACK_CURE_THRESHOLD)
|
|
owner.visible_message(span_nicegreen("[owner] relaxes [owner.p_their()] body and stops clutching at [owner.p_their()] chest!"), span_nicegreen("The pain in your chest has subsided. You're cured!"))
|
|
qdel(src)
|
|
return
|
|
|
|
var/oxyloss_sum = 0 //A sum of the oxyloss we will inflict by the end of this cycle.
|
|
|
|
if(time_until_stoppage > ATTACK_STAGE_THREE)
|
|
if(SPT_PROB(5, seconds_between_ticks))
|
|
owner.playsound_local(owner, 'sound/effects/singlebeat.ogg', 25, FALSE, use_reverb = FALSE)
|
|
owner.adjust_stamina_loss(5)
|
|
|
|
if(time_until_stoppage <= ATTACK_STAGE_TWO && time_until_stoppage > ATTACK_STAGE_THREE) //This coughing gets replaced with worse coughing, no need to stack it.
|
|
if(SPT_PROB(10, seconds_between_ticks))
|
|
owner.emote("cough")
|
|
owner.adjust_stamina_loss(10)
|
|
oxyloss_sum += 4
|
|
|
|
if(time_until_stoppage <= ATTACK_STAGE_THREE) //At this point, we start with chat messages and make it clear that something is very wrong.
|
|
if(!visible)
|
|
ADD_TRAIT(owner, TRAIT_DISEASELIKE_SEVERITY_HIGH, type)
|
|
owner.med_hud_set_status()
|
|
visible = TRUE //We do not reset this status until it's fully cured. Once it's been made apparent, there's no reason to hide it again until it is resolved. It will only confuse players.
|
|
if(SPT_PROB(15, seconds_between_ticks))
|
|
to_chat(owner, span_danger("You feel a sharp pain in your chest!"))
|
|
if(SPT_PROB(15, seconds_between_ticks))
|
|
human_owner.vomit(VOMIT_CATEGORY_DEFAULT, lost_nutrition = 95)
|
|
owner.emote("cough")
|
|
oxyloss_sum += 1
|
|
if(SPT_PROB(8, seconds_between_ticks))
|
|
to_chat(owner, span_danger("You feel very weak and dizzy..."))
|
|
owner.adjust_confusion_up_to(6 SECONDS, 10 SECONDS)
|
|
owner.adjust_stamina_loss(20)
|
|
owner.emote("cough")
|
|
oxyloss_sum += 8
|
|
|
|
if(time_until_stoppage <= ATTACK_STAGE_FOUR) //And now we compound it with even worse effects.
|
|
|
|
if(SPT_PROB(5, seconds_between_ticks))
|
|
to_chat(owner, span_userdanger("It feels like you're shutting down..."))
|
|
owner.adjust_dizzy_up_to(4 SECONDS, 10 SECONDS)
|
|
owner.adjust_eye_blur_up_to(4 SECONDS, 20 SECONDS)
|
|
owner.adjust_stamina_loss(20)
|
|
|
|
if(SPT_PROB(5, seconds_between_ticks))
|
|
owner.emote("cough")
|
|
if(SPT_PROB(5, seconds_between_ticks))
|
|
to_chat(owner, span_userdanger("You cough. Everything goes dark. You're going to die soon."))
|
|
owner.adjust_temp_blindness(10 SECONDS) //Are you panicking yet? You should be panicking by now.
|
|
else
|
|
to_chat(owner, span_userdanger("As you cough, your chest surges in pain and darkness closes in around your sight."))
|
|
owner.adjust_temp_blindness(2 SECONDS)
|
|
owner.adjust_eye_blur_up_to(4 SECONDS, 20 SECONDS)
|
|
oxyloss_sum += 8
|
|
owner.Paralyze(1 SECONDS)
|
|
oxyloss_sum += 3
|
|
|
|
if(owner.get_oxy_loss() < OXYLOSS_MAXIMUM) //A bad enough roll on the verge of passing out might still push you over into unconciousness for a few seconds...?
|
|
owner.adjust_oxy_loss(oxyloss_sum)
|
|
|
|
if(time_until_stoppage <= 0)
|
|
if(owner.stat == CONSCIOUS)
|
|
to_chat(owner, span_userdanger("You feel a terrible pain in your chest, as if your heart has stopped!"))
|
|
owner.adjust_eye_blur(20 SECONDS)
|
|
human_owner.set_heartattack(TRUE)
|
|
owner.apply_status_effect(/datum/status_effect/heart_desperation) // To give the victim a final chance to shock their heart before losing consciousness
|
|
var/flash_type = /atom/movable/screen/fullscreen/flash
|
|
if(owner.client?.prefs?.read_preference(/datum/preference/toggle/darkened_flash))
|
|
flash_type = /atom/movable/screen/fullscreen/flash/black
|
|
owner.overlay_fullscreen("flash", flash_type)
|
|
addtimer(CALLBACK(owner, TYPE_PROC_REF(/mob/living, clear_fullscreen), "flash", 1 SECONDS), 1 SECONDS)
|
|
qdel(src)
|
|
return FALSE
|
|
|
|
if(time_until_stoppage <= ATTACK_STAGE_TWO)
|
|
if(time_until_stoppage <= ATTACK_STAGE_FOUR)
|
|
owner.playsound_local(owner, 'sound/effects/singlebeat.ogg', 100, FALSE, channel = CHANNEL_HEARTBEAT, use_reverb = FALSE)
|
|
else
|
|
owner.playsound_local(owner, 'sound/effects/health/slowbeat.ogg', 25, FALSE, channel = CHANNEL_HEARTBEAT, use_reverb = FALSE)
|
|
else
|
|
owner.stop_sound_channel(CHANNEL_HEARTBEAT)
|
|
|
|
time_until_stoppage--
|
|
|
|
/datum/status_effect/heart_attack/get_examine_text()
|
|
if(!time_until_stoppage <= ATTACK_STAGE_THREE)
|
|
return
|
|
var/mob/living/carbon/human/human_owner = owner
|
|
var/cannot_grasp = (human_owner.usable_hands <= 0 || owner.incapacitated & INCAPABLE_RESTRAINTS || HAS_TRAIT(owner, TRAIT_HANDS_BLOCKED))
|
|
return span_warning("[owner.p_they()] looks to be doubling over" + "[cannot_grasp ? " in pain!" : ", clutching [owner.p_their()] chest in pain!"]")
|
|
|
|
/datum/status_effect/heart_attack/on_remove()
|
|
REMOVE_TRAIT(owner, TRAIT_DISEASELIKE_SEVERITY_HIGH, type)
|
|
owner.med_hud_set_status()
|
|
return ..()
|
|
|
|
///End the heart attack due to heart removal.
|
|
/datum/status_effect/heart_attack/proc/on_organ_removed(datum/source, obj/item/organ)
|
|
SIGNAL_HANDLER
|
|
if(istype(organ, /obj/item/organ/heart))
|
|
qdel(src)
|
|
|
|
///Slightly reduces your timer. Can cure you if you really really want.
|
|
/datum/status_effect/heart_attack/proc/minor_shock(datum/source)
|
|
SIGNAL_HANDLER
|
|
time_until_stoppage += 18 //Good for keeping yourself up. Won't be easy to get over the cure threshold by yourself. You're going to need security beating the crap out of you with stunbatons, but it'll work.
|
|
if(prob(50)) //Also good for crafty solos who want to stunbaton themselves back to health. Timing will be key.
|
|
to_chat(owner, span_nicegreen("Something about being shocked makes the pain in your chest ease up!"))
|
|
|
|
///Makes major progress towards curing the attack.
|
|
/datum/status_effect/heart_attack/proc/defib_shock(obj/item/shockpaddles/source)
|
|
SIGNAL_HANDLER
|
|
time_until_stoppage += 50 //Three shocks should save pretty much anyone.
|
|
owner.visible_message(span_nicegreen("[owner] seems to be relieved of their pain as they're shocked by the [source]!"), span_nicegreen("The [source] shocks your heart awake, and you feel the pain in your chest ease up!"))
|
|
|
|
///Slightly reduces your timer, just like the minor shock signal. Slightly more relief because these use cases are generally more dangerous.
|
|
/datum/status_effect/heart_attack/proc/electrocuted(datum/source, shock_damage)
|
|
SIGNAL_HANDLER
|
|
time_until_stoppage += (20 + shock_damage * 1.15)
|
|
if(prob(50))
|
|
to_chat(owner, span_nicegreen("Something about being electrocuted makes the pain in your chest ease up!"))
|
|
|
|
///Alternative to penthrite that keeps you up for a few seconds after having a heart attack. Gives a bit of time to call for help regardless of when/where you've collapsed.
|
|
/datum/status_effect/heart_desperation
|
|
id = "heart_desperation"
|
|
duration = (4 SECONDS)
|
|
alert_type = null
|
|
/// List of traits to add/remove from our subject when we are in their system
|
|
var/static/list/subject_traits = list(
|
|
TRAIT_STABLEHEART,
|
|
TRAIT_NOHARDCRIT,
|
|
TRAIT_NOSOFTCRIT,
|
|
TRAIT_NOCRITDAMAGE,
|
|
)
|
|
|
|
/datum/status_effect/heart_desperation/on_apply()
|
|
owner.add_traits(subject_traits, type)
|
|
owner.Knockdown(2 SECONDS, 2 SECONDS)
|
|
return TRUE
|
|
|
|
/datum/status_effect/heart_desperation/tick(seconds_between_ticks)
|
|
owner.Knockdown(2 SECONDS, 2 SECONDS)
|
|
owner.set_silence_if_lower(2 SECONDS)
|
|
|
|
/datum/status_effect/heart_desperation/on_remove()
|
|
owner.remove_traits(subject_traits, type)
|
|
|
|
#undef ATTACK_STAGE_TWO
|
|
#undef ATTACK_STAGE_THREE
|
|
#undef ATTACK_STAGE_FOUR
|
|
#undef ATTACK_CURE_THRESHOLD
|
|
#undef OXYLOSS_MAXIMUM
|