mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-11 08:06:33 +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! /🆑
221 lines
7.5 KiB
Plaintext
221 lines
7.5 KiB
Plaintext
/**
|
|
* Component allowing you to create a linked list of mobs.
|
|
* These mobs will follow each other and attack as one, as well as sharing damage taken.
|
|
*/
|
|
/datum/component/mob_chain
|
|
|
|
/// If true then damage we take is passed backwards along the line
|
|
var/pass_damage_back
|
|
/// If true then we will set our icon state based on line position
|
|
var/vary_icon_state
|
|
|
|
/// Mob in front of us in the chain
|
|
var/mob/living/front
|
|
/// Mob behind us in the chain
|
|
var/mob/living/back
|
|
|
|
/datum/component/mob_chain/Initialize(mob/living/front, pass_damage_back = TRUE, vary_icon_state = FALSE)
|
|
. = ..()
|
|
if (!isliving(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
src.front = front
|
|
src.pass_damage_back = pass_damage_back
|
|
src.vary_icon_state = vary_icon_state
|
|
if (!isnull(front))
|
|
SEND_SIGNAL(front, COMSIG_MOB_GAINED_CHAIN_TAIL, parent)
|
|
parent.AddComponent(/datum/component/leash, owner = front, distance = 1) // Handles catching up gracefully
|
|
var/mob/living/living_parent = parent
|
|
living_parent.set_glide_size(front.glide_size)
|
|
|
|
/datum/component/mob_chain/Destroy(force)
|
|
if (!isnull(front))
|
|
SEND_SIGNAL(front, COMSIG_MOB_LOST_CHAIN_TAIL, parent)
|
|
front = null
|
|
back = null
|
|
return ..()
|
|
|
|
/datum/component/mob_chain/RegisterWithParent()
|
|
RegisterSignal(parent, COMSIG_MOB_GAINED_CHAIN_TAIL, PROC_REF(on_gained_tail))
|
|
RegisterSignal(parent, COMSIG_MOB_LOST_CHAIN_TAIL, PROC_REF(on_lost_tail))
|
|
RegisterSignal(parent, COMSIG_MOB_CHAIN_CONTRACT, PROC_REF(on_contracted))
|
|
RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(on_death))
|
|
RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(on_deletion))
|
|
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved))
|
|
RegisterSignal(parent, COMSIG_ATOM_CAN_BE_PULLED, PROC_REF(on_pulled))
|
|
RegisterSignals(parent, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_MOB_ATTACK_RANGED), PROC_REF(on_attack))
|
|
RegisterSignal(parent, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, PROC_REF(on_glide_size_changed))
|
|
if (vary_icon_state)
|
|
RegisterSignal(parent, COMSIG_ATOM_UPDATE_ICON_STATE, PROC_REF(on_update_icon_state))
|
|
update_mob_appearance()
|
|
if (pass_damage_back)
|
|
RegisterSignals(parent, COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES, PROC_REF(on_adjust_damage))
|
|
RegisterSignal(parent, COMSIG_LIVING_ADJUST_STAMINA_DAMAGE, PROC_REF(on_adjust_stamina))
|
|
RegisterSignal(parent, COMSIG_CARBON_LIMB_DAMAGED, PROC_REF(on_limb_damage))
|
|
|
|
var/datum/action/cooldown/worm_contract/shrink = new(parent)
|
|
shrink.Grant(parent)
|
|
|
|
/datum/component/mob_chain/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(
|
|
COMSIG_ATOM_CAN_BE_PULLED,
|
|
COMSIG_ATOM_UPDATE_ICON_STATE,
|
|
COMSIG_CARBON_LIMB_DAMAGED,
|
|
COMSIG_LIVING_ADJUST_BRUTE_DAMAGE,
|
|
COMSIG_LIVING_ADJUST_BURN_DAMAGE,
|
|
COMSIG_LIVING_DEATH,
|
|
COMSIG_LIVING_ADJUST_OXY_DAMAGE,
|
|
COMSIG_LIVING_ADJUST_STAMINA_DAMAGE,
|
|
COMSIG_LIVING_ADJUST_TOX_DAMAGE,
|
|
COMSIG_LIVING_UNARMED_ATTACK,
|
|
COMSIG_MOB_ATTACK_RANGED,
|
|
COMSIG_MOB_CHAIN_CONTRACT,
|
|
COMSIG_MOB_GAINED_CHAIN_TAIL,
|
|
COMSIG_MOB_LOST_CHAIN_TAIL,
|
|
COMSIG_MOVABLE_MOVED,
|
|
COMSIG_MOVABLE_UPDATE_GLIDE_SIZE,
|
|
COMSIG_QDELETING,
|
|
))
|
|
qdel(parent.GetComponent(/datum/component/leash))
|
|
var/mob/living/living_parent = parent
|
|
var/datum/action/cooldown/worm_contract/shrink = locate() in living_parent.actions
|
|
qdel(shrink)
|
|
|
|
/// Update how we look
|
|
/datum/component/mob_chain/proc/update_mob_appearance()
|
|
if (!vary_icon_state)
|
|
return
|
|
var/mob/living/body = parent
|
|
body.update_appearance(UPDATE_ICON_STATE)
|
|
|
|
/// Called when something sets us as ITS front
|
|
/datum/component/mob_chain/proc/on_gained_tail(mob/living/body, mob/living/tail)
|
|
SIGNAL_HANDLER
|
|
back = tail
|
|
update_mob_appearance()
|
|
|
|
/// Called when our tail loses its chain component
|
|
/datum/component/mob_chain/proc/on_lost_tail()
|
|
SIGNAL_HANDLER
|
|
back = null
|
|
update_mob_appearance()
|
|
|
|
/// Called when our tail gets pulled up to our body
|
|
/datum/component/mob_chain/proc/on_contracted(mob/living/shrinking)
|
|
SIGNAL_HANDLER
|
|
if (isnull(back))
|
|
return
|
|
back.forceMove(shrinking.loc)
|
|
var/datum/action/cooldown/worm_contract/shrink = locate() in back.actions
|
|
if (isnull(shrink))
|
|
return
|
|
INVOKE_ASYNC(shrink, TYPE_PROC_REF(/datum/action, Trigger))
|
|
|
|
/// If we die so does the guy behind us, then stop following the leader
|
|
/datum/component/mob_chain/proc/on_death()
|
|
SIGNAL_HANDLER
|
|
back?.death()
|
|
qdel(src)
|
|
|
|
/// If we get deleted so does the guy behind us
|
|
/datum/component/mob_chain/proc/on_deletion()
|
|
SIGNAL_HANDLER
|
|
QDEL_NULL(back)
|
|
front?.update_appearance(UPDATE_ICON)
|
|
|
|
/// Pull our tail behind us when we move
|
|
/datum/component/mob_chain/proc/on_moved(mob/living/mover, turf/old_loc)
|
|
SIGNAL_HANDLER
|
|
if(isnull(back) || back.loc == old_loc)
|
|
return
|
|
back.Move(old_loc)
|
|
|
|
/// Update our visuals based on if we have someone in front and behind
|
|
/datum/component/mob_chain/proc/on_update_icon_state(mob/living/our_mob)
|
|
SIGNAL_HANDLER
|
|
var/current_icon_state = our_mob.base_icon_state
|
|
if(isnull(front))
|
|
current_icon_state = "[current_icon_state]_start"
|
|
else if(isnull(back))
|
|
current_icon_state = "[current_icon_state]_end"
|
|
else
|
|
current_icon_state = "[current_icon_state]_mid"
|
|
|
|
our_mob.icon_state = current_icon_state
|
|
if (isanimal_or_basicmob(our_mob))
|
|
var/mob/living/basic/basic_parent = our_mob
|
|
basic_parent.icon_living = current_icon_state
|
|
|
|
/// Do not allow someone to be pulled out of the chain
|
|
/datum/component/mob_chain/proc/on_pulled(mob/living/our_mob)
|
|
SIGNAL_HANDLER
|
|
if (!isnull(front))
|
|
return COMSIG_ATOM_CANT_PULL
|
|
|
|
/// Tell our tail to attack too
|
|
/datum/component/mob_chain/proc/on_attack(mob/living/our_mob, atom/target)
|
|
SIGNAL_HANDLER
|
|
if (target == back || target == front)
|
|
return COMPONENT_CANCEL_ATTACK_CHAIN
|
|
if (isnull(back) || QDELETED(target))
|
|
return
|
|
INVOKE_ASYNC(back, TYPE_PROC_REF(/mob, ClickOn), target)
|
|
|
|
/// Maintain glide size backwards
|
|
/datum/component/mob_chain/proc/on_glide_size_changed(mob/living/our_mob, new_size)
|
|
SIGNAL_HANDLER
|
|
back?.set_glide_size(new_size)
|
|
|
|
/// On gain or lose stamina, adjust our tail too
|
|
/datum/component/mob_chain/proc/on_adjust_stamina(mob/living/our_mob, type, amount, forced)
|
|
SIGNAL_HANDLER
|
|
if (forced)
|
|
return
|
|
back?.adjust_stamina_loss(amount, forced = forced)
|
|
|
|
/// On damage or heal, affect our furthest segment
|
|
/datum/component/mob_chain/proc/on_adjust_damage(mob/living/our_mob, type, amount, forced)
|
|
SIGNAL_HANDLER
|
|
if (isnull(back) || forced)
|
|
return
|
|
switch (type)
|
|
if(BRUTE)
|
|
back.adjust_brute_loss(amount, forced = forced)
|
|
if(BURN)
|
|
back.adjust_fire_loss(amount, forced = forced)
|
|
if(TOX)
|
|
back.adjust_tox_loss(amount, forced = forced)
|
|
if(OXY) // If all segments are suffocating we pile damage backwards until our ass starts dying forwards
|
|
back.adjust_oxy_loss(amount, forced = forced)
|
|
return COMPONENT_IGNORE_CHANGE
|
|
|
|
/// Special handling for if damage is delegated to a mob's limbs instead of its overall damage
|
|
/datum/component/mob_chain/proc/on_limb_damage(mob/living/our_mob, limb, brute, burn)
|
|
SIGNAL_HANDLER
|
|
if (isnull(back))
|
|
return
|
|
if (brute != 0)
|
|
back.adjust_brute_loss(brute, updating_health = FALSE)
|
|
if (burn != 0)
|
|
back.adjust_fire_loss(burn, updating_health = FALSE)
|
|
if (brute != 0 || burn != 0)
|
|
back.updatehealth()
|
|
return COMPONENT_PREVENT_LIMB_DAMAGE
|
|
|
|
/**
|
|
* Shrink the chain of mobs into one tile.
|
|
*/
|
|
/datum/action/cooldown/worm_contract
|
|
name = "Force Contract"
|
|
desc = "Forces your body to contract onto a single tile."
|
|
background_icon_state = "bg_heretic"
|
|
overlay_icon_state = "bg_heretic_border"
|
|
button_icon = 'icons/mob/actions/actions_ecult.dmi'
|
|
button_icon_state = "worm_contract"
|
|
cooldown_time = 30 SECONDS
|
|
melee_cooldown_time = 0 SECONDS
|
|
|
|
/datum/action/cooldown/worm_contract/Activate(atom/target)
|
|
SEND_SIGNAL(owner, COMSIG_MOB_CHAIN_CONTRACT)
|
|
StartCooldown()
|