mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-12 16:44:43 +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! /🆑
280 lines
9.9 KiB
Plaintext
280 lines
9.9 KiB
Plaintext
/mob/living/basic/mining_drone
|
|
name = "\improper Nanotrasen minebot"
|
|
desc = "The instructions printed on the side read: This is a small robot used to support miners, can be set to search and collect loose ore, or to help fend off wildlife."
|
|
gender = NEUTER
|
|
icon = 'icons/mob/silicon/aibots.dmi'
|
|
icon_state = "mining_drone"
|
|
icon_living = "mining_drone"
|
|
basic_mob_flags = DEL_ON_DEATH
|
|
status_flags = CANSTUN|CANKNOCKDOWN|CANPUSH
|
|
mouse_opacity = MOUSE_OPACITY_ICON
|
|
combat_mode = TRUE
|
|
habitable_atmos = null
|
|
minimum_survivable_temperature = 0
|
|
health = 125
|
|
maxHealth = 125
|
|
melee_damage_lower = 15
|
|
melee_damage_upper = 15
|
|
obj_damage = 10
|
|
attack_verb_continuous = "drills"
|
|
attack_verb_simple = "drill"
|
|
attack_sound = 'sound/items/weapons/circsawhit.ogg'
|
|
sentience_type = SENTIENCE_MINEBOT
|
|
speak_emote = list("states")
|
|
mob_biotypes = MOB_ROBOTIC
|
|
faction = list(FACTION_STATION, FACTION_NEUTRAL)
|
|
death_message = "blows apart!"
|
|
light_system = OVERLAY_LIGHT
|
|
light_range = 6
|
|
// I want this to be a bit more dim, for vibes
|
|
light_power = 0.6
|
|
light_color = "#ff9933"
|
|
light_on = FALSE
|
|
combat_mode = FALSE
|
|
ai_controller = /datum/ai_controller/basic_controller/minebot
|
|
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, STAMINA = 0, OXY = 1)
|
|
///the gun we use to kill
|
|
var/obj/item/gun/energy/recharge/kinetic_accelerator/minebot/stored_gun
|
|
///our normal overlay
|
|
var/mutable_appearance/neutral_overlay
|
|
///our combat mode overlay
|
|
var/mutable_appearance/combat_overlay
|
|
///our current color, if any
|
|
var/selected_color
|
|
///the commands our owner can give us
|
|
var/static/list/pet_commands = list(
|
|
/datum/pet_command/idle/minebot,
|
|
/datum/pet_command/move,
|
|
/datum/pet_command/protect_owner/minebot,
|
|
/datum/pet_command/minebot_ability/light,
|
|
/datum/pet_command/minebot_ability/dump,
|
|
/datum/pet_command/automate_mining,
|
|
/datum/pet_command/free/minebot,
|
|
/datum/pet_command/follow/start_active,
|
|
/datum/pet_command/attack/minebot,
|
|
)
|
|
///possible colors the bot can have
|
|
var/static/list/possible_colors= list(
|
|
"Default" = null, //default color state
|
|
"Blue" = "#70d5e7",
|
|
"Red" = "#ee7fb9",
|
|
"Green" = "#5fea94",
|
|
)
|
|
|
|
/mob/living/basic/mining_drone/Initialize(mapload)
|
|
. = ..()
|
|
neutral_overlay = mutable_appearance(icon = 'icons/mob/silicon/aibots.dmi', icon_state = "mining_drone_grey")
|
|
combat_overlay = mutable_appearance(icon = 'icons/mob/silicon/aibots.dmi', icon_state = "mining_drone_offense_grey")
|
|
AddComponent(/datum/component/obeys_commands, pet_commands)
|
|
AddElement(/datum/element/death_drops, /obj/effect/decal/cleanable/blood/gibs/robot_debris/old)
|
|
add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE, TRAIT_MINING_AOE_IMMUNE), INNATE_TRAIT)
|
|
AddElement(/datum/element/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, sound_vary = TRUE)
|
|
|
|
var/static/list/innate_actions = list(
|
|
/datum/action/cooldown/mob_cooldown/missile_launcher = BB_MINEBOT_MISSILE_ABILITY,
|
|
/datum/action/cooldown/mob_cooldown/drop_landmine = BB_MINEBOT_LANDMINE_ABILITY,
|
|
/datum/action/cooldown/mob_cooldown/minedrone/toggle_light = BB_MINEBOT_LIGHT_ABILITY,
|
|
/datum/action/cooldown/mob_cooldown/minedrone/toggle_meson_vision = null,
|
|
/datum/action/cooldown/mob_cooldown/minedrone/dump_ore = BB_MINEBOT_DUMP_ABILITY,
|
|
)
|
|
|
|
grant_actions_by_list(innate_actions)
|
|
|
|
stored_gun = new(src)
|
|
var/obj/item/implant/radio/mining/comms = new(src)
|
|
comms.implant(src)
|
|
assign_access()
|
|
|
|
/mob/living/basic/mining_drone/set_combat_mode(new_mode, silent = TRUE)
|
|
. = ..()
|
|
icon_state = combat_mode ? "mining_drone_offense" : "mining_drone"
|
|
balloon_alert(src, "now [combat_mode ? "attacking" : "collecting"]")
|
|
|
|
/mob/living/basic/mining_drone/examine(mob/user)
|
|
. = ..()
|
|
if(health < maxHealth)
|
|
if(health >= maxHealth * 0.5)
|
|
. += span_warning("[p_They()] look slightly dented.")
|
|
else
|
|
. += span_boldwarning("[p_They()] look severely dented!")
|
|
|
|
if(isnull(stored_gun) || !stored_gun.max_mod_capacity)
|
|
return
|
|
|
|
. += "<b>[stored_gun.get_remaining_mod_capacity()]%</b> mod capacity remaining."
|
|
|
|
for(var/obj/item/borg/upgrade/modkit/modkit as anything in stored_gun.modkits)
|
|
. += span_notice("There is \a [modkit] installed, using <b>[modkit.cost]%</b> capacity.")
|
|
if(ai_controller && ai_controller.ai_status == AI_STATUS_IDLE)
|
|
. += "The [src] appears to be in <b>sleep mode</b>. You can restore normal functions by <b>tapping</b> it."
|
|
|
|
|
|
/mob/living/basic/mining_drone/welder_act(mob/living/user, obj/item/welder)
|
|
if(user.combat_mode)
|
|
return FALSE
|
|
if(combat_mode)
|
|
user.balloon_alert(user, "can't repair in attack mode!")
|
|
return TRUE
|
|
if(maxHealth == health)
|
|
user.balloon_alert(user, "at full integrity!")
|
|
return TRUE
|
|
if(welder.use_tool(src, user, 0, volume=40))
|
|
adjust_brute_loss(-15)
|
|
user.balloon_alert(user, "successfully repaired!")
|
|
return TRUE
|
|
|
|
/mob/living/basic/mining_drone/attackby(obj/item/item_used, mob/user, list/modifiers, list/attack_modifiers)
|
|
if(item_used.tool_behaviour == TOOL_CROWBAR || istype(item_used, /obj/item/borg/upgrade/modkit))
|
|
item_used.melee_attack_chain(user, stored_gun, modifiers)
|
|
return
|
|
|
|
return ..()
|
|
|
|
/mob/living/basic/mining_drone/attack_hand(mob/living/carbon/human/user, list/modifiers)
|
|
if(!user.combat_mode)
|
|
if(ai_controller && ai_controller.ai_status == AI_STATUS_IDLE)
|
|
ai_controller.set_ai_status(AI_STATUS_ON)
|
|
if(LAZYACCESS(modifiers, LEFT_CLICK)) //Lets Right Click be specifically for re-enabling their AI (and avoiding the UI popup), while Left Click simply does both.
|
|
ui_interact(user)
|
|
return
|
|
return ..()
|
|
|
|
/mob/living/basic/mining_drone/ui_interact(mob/user, datum/tgui/ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "MineBot", name)
|
|
ui.open()
|
|
|
|
/mob/living/basic/mining_drone/ui_data(mob/user)
|
|
var/list/data = list()
|
|
data["auto_defend"] = ai_controller.blackboard[BB_MINEBOT_AUTO_DEFEND]
|
|
data["repair_node_drone"] = ai_controller.blackboard[BB_MINEBOT_REPAIR_DRONE]
|
|
data["plant_mines"] = ai_controller.blackboard[BB_MINEBOT_PLANT_MINES]
|
|
data["bot_maintain_distance"] = ai_controller.blackboard[BB_MINIMUM_SHOOTING_DISTANCE]
|
|
data["bot_name"] = name
|
|
data["bot_mode"] = combat_mode
|
|
data["bot_health"] = health
|
|
data["bot_maxhealth"] = maxHealth
|
|
data["bot_color"] = ""
|
|
var/color_value = neutral_overlay.color
|
|
for(var/index in possible_colors)
|
|
if(possible_colors[index] == color_value)
|
|
data["bot_color"] = index
|
|
break
|
|
return data
|
|
|
|
/mob/living/basic/mining_drone/ui_static_data(mob/user)
|
|
var/list/data = list()
|
|
data["bot_icon"] = icon2base64(getFlatIcon(src, no_anim = TRUE))
|
|
data["possible_colors"] = list()
|
|
for(var/color in possible_colors)
|
|
data["possible_colors"] += list(list(
|
|
"color_name" = color,
|
|
"color_value" = possible_colors[color],
|
|
))
|
|
return data
|
|
|
|
/mob/living/basic/mining_drone/ui_act(action, params, datum/tgui/ui)
|
|
. = ..()
|
|
switch(action)
|
|
if("change_min_distance")
|
|
var/new_distance = clamp(params["distance"], 0, 5)
|
|
ai_controller.set_blackboard_key(BB_MINIMUM_SHOOTING_DISTANCE, new_distance)
|
|
if("toggle_defend")
|
|
var/new_toggle = !ai_controller.blackboard[BB_MINEBOT_AUTO_DEFEND]
|
|
ai_controller.set_blackboard_key(BB_MINEBOT_AUTO_DEFEND, new_toggle)
|
|
if("toggle_repair")
|
|
var/new_defend = !ai_controller.blackboard[BB_MINEBOT_REPAIR_DRONE]
|
|
ai_controller.set_blackboard_key(BB_MINEBOT_REPAIR_DRONE, new_defend)
|
|
if("toggle_mines")
|
|
var/new_mines = !ai_controller.blackboard[BB_MINEBOT_PLANT_MINES]
|
|
ai_controller.set_blackboard_key(BB_MINEBOT_PLANT_MINES, new_mines)
|
|
if("set_name")
|
|
var/input_name = sanitize_name(params["chosen_name"], allow_numbers = TRUE)
|
|
name = (input_name ? input_name : initial(name))
|
|
if("toggle_mode")
|
|
set_combat_mode(!combat_mode)
|
|
if("set_color")
|
|
change_color(params["chosen_color"])
|
|
update_static_data(ui.user, ui)
|
|
return TRUE
|
|
|
|
/mob/living/basic/mining_drone/proc/change_color(new_color)
|
|
selected_color = new_color
|
|
if(!isnull(selected_color))
|
|
neutral_overlay.color = selected_color
|
|
combat_overlay.color = selected_color
|
|
update_appearance()
|
|
|
|
/mob/living/basic/mining_drone/click_alt(mob/living/user)
|
|
if(user.combat_mode)
|
|
return CLICK_ACTION_BLOCKING
|
|
set_combat_mode(!combat_mode)
|
|
balloon_alert(user, "now [combat_mode ? "attacking wildlife" : "collecting loose ore"]")
|
|
return CLICK_ACTION_SUCCESS
|
|
|
|
/mob/living/basic/mining_drone/RangedAttack(atom/target, list/modifiers)
|
|
if(!combat_mode)
|
|
return
|
|
stored_gun.try_fire_gun(target, src, list2params(modifiers))
|
|
|
|
/mob/living/basic/mining_drone/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers)
|
|
. = ..()
|
|
|
|
if(!. || !proximity_flag || combat_mode)
|
|
return
|
|
|
|
if(istype(attack_target, /obj/item/stack/ore))
|
|
var/obj/item/target_ore = attack_target
|
|
target_ore.forceMove(src)
|
|
|
|
/mob/living/basic/mining_drone/proc/drop_ore()
|
|
to_chat(src, span_notice("You dump your stored ore."))
|
|
for(var/obj/item/stack/ore/dropped_item in contents)
|
|
dropped_item.forceMove(get_turf(src))
|
|
|
|
/mob/living/basic/mining_drone/death(gibbed)
|
|
drop_ore()
|
|
|
|
if(isnull(stored_gun))
|
|
return ..()
|
|
|
|
for(var/obj/item/borg/upgrade/modkit/modkit as anything in stored_gun.modkits)
|
|
modkit.uninstall(stored_gun)
|
|
|
|
return ..()
|
|
|
|
/mob/living/basic/mining_drone/Destroy()
|
|
QDEL_NULL(stored_gun)
|
|
return ..()
|
|
|
|
/mob/living/basic/mining_drone/early_melee_attack(atom/target, list/modifiers, ignore_cooldown)
|
|
. = ..()
|
|
if(!.)
|
|
return FALSE
|
|
|
|
if(!istype(target, /mob/living/basic/node_drone))
|
|
return TRUE
|
|
repair_node_drone(target)
|
|
return FALSE
|
|
|
|
/mob/living/basic/mining_drone/proc/repair_node_drone(mob/living/my_target)
|
|
do_sparks(5, FALSE, source = my_target)
|
|
if(!do_after(src, 6 SECONDS, my_target))
|
|
return
|
|
my_target.heal_overall_damage(brute = 50)
|
|
|
|
/mob/living/basic/mining_drone/update_overlays()
|
|
. = ..()
|
|
if(stat == DEAD || isnull(selected_color))
|
|
return
|
|
|
|
. += combat_mode ? combat_overlay : neutral_overlay
|
|
|
|
/mob/living/basic/mining_drone/proc/assign_access()
|
|
var/static/list/required_access
|
|
if(isnull(required_access))
|
|
var/datum/id_trim/access_card = SSid_access.trim_singletons_by_path[/datum/id_trim/job/shaft_miner]
|
|
required_access = access_card.access
|
|
AddElement(/datum/element/mob_access, required_access)
|