From 0218b541f242edf9be80fb5975973e710f885b50 Mon Sep 17 00:00:00 2001 From: Migratingcocofruit <69551563+Migratingcocofruit@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:23:41 +0200 Subject: [PATCH] Energy field generators Refactor/Tweak (#26919) * Reduces range for energy seeking of generators, adds energy spreading and changes instances of power to energy. Containment field destructor no longer crashes when it has no connected generators * review changes * undef * removes redundant line * review changes --- code/modules/admin/verbs/debug.dm | 2 +- .../engines/singularity/containment_field.dm | 8 +- .../engines/singularity/field_generator.dm | 103 ++++++++++-------- 3 files changed, 64 insertions(+), 49 deletions(-) diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index c64f7dc8357..dccd9904032 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -726,7 +726,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention) if(!F.active) F.active = TRUE F.state = 2 - F.power = 250 + F.energy = 125 F.anchored = TRUE F.warming_up = 3 F.start_fields() diff --git a/code/modules/power/engines/singularity/containment_field.dm b/code/modules/power/engines/singularity/containment_field.dm index e1c80554979..0c8f67e9c62 100644 --- a/code/modules/power/engines/singularity/containment_field.dm +++ b/code/modules/power/engines/singularity/containment_field.dm @@ -15,8 +15,10 @@ var/obj/machinery/field/generator/FG2 = null /obj/machinery/field/containment/Destroy() - FG1.fields -= src - FG2.fields -= src + if(FG1)// These checks are mostly in case a field is spawned in by accident. + FG1.fields -= src + if(FG2) + FG2.fields -= src return ..() /obj/machinery/field/containment/attack_hand(mob/user) @@ -50,7 +52,7 @@ return if(ismegafauna(M)) M.visible_message("[M] glows fiercely as the containment field flickers out!") - FG1.calc_power(INFINITY) //rip that 'containment' field + FG1.calc_energy(INFINITY) //rip that 'containment' field M.adjustHealth(-M.obj_damage) else ..() diff --git a/code/modules/power/engines/singularity/field_generator.dm b/code/modules/power/engines/singularity/field_generator.dm index c7238b8bdda..3d8a54279d1 100644 --- a/code/modules/power/engines/singularity/field_generator.dm +++ b/code/modules/power/engines/singularity/field_generator.dm @@ -1,14 +1,14 @@ /* -field_generator power level display - * The icon used for the field_generator need to have 'num_power_levels' number of icon states - * named 'Field_Gen +p[num]' where 'num' ranges from 1 to 'num_power_levels' - * The power level is displayed using overlays. The current displayed power level is stored in 'powerlevel'. - * The overlay in use and the powerlevel variable must be kept in sync. A powerlevel equal to 0 means that - * no power level overlay is currently in the overlays list. +field_generator energy level display + * The icon used for the field_generator need to have 'num_energy_levels' number of icon states + * named 'Field_Gen +p[num]' where 'num' ranges from 1 to 'num_energy_levels' + * The energy level is displayed using overlays. The current displayed energy level is stored in 'energylevel'. + * The overlay in use and the energylevel variable must be kept in sync. A energylevel equal to 0 means that + * no energy level overlay is currently in the overlays list. * -Aygar */ -#define field_generator_max_power 250 +#define FIELD_GENERATOR_MAX_ENERGY 125 #define FG_UNSECURED 0 #define FG_SECURED 1 @@ -31,10 +31,10 @@ GLOBAL_LIST_EMPTY(field_generator_fields) max_integrity = 500 //100% immune to lasers and energy projectiles since it absorbs their energy. armor = list(MELEE = 25, BULLET = 10, LASER = 100, ENERGY = 100, BOMB = 0, RAD = 0, FIRE = 50, ACID = 70) - var/const/num_power_levels = 6 // Total number of power level icon has - var/power_level = 0 + var/const/num_energy_levels = 6 // Total number of power level icon has + var/energy_level = 0 var/active = FG_OFFLINE - var/power = 20 // Current amount of power + var/energy = 20 // Current amount of energy var/state = FG_UNSECURED var/warming_up = 0 var/list/obj/machinery/field/containment/fields @@ -47,8 +47,8 @@ GLOBAL_LIST_EMPTY(field_generator_fields) . += "+a[warming_up]" if(length(fields)) . += "+on" - if(power_level) - . += "+p[power_level]" + if(energy_level) + . += "+p[energy_level]" /obj/machinery/field/generator/Initialize(mapload) . = ..() @@ -58,7 +58,7 @@ GLOBAL_LIST_EMPTY(field_generator_fields) /obj/machinery/field/generator/process() if(active == FG_ONLINE) - calc_power() + calc_energy() /obj/machinery/field/generator/attack_hand(mob/user) if(state == FG_WELDED) @@ -141,8 +141,8 @@ GLOBAL_LIST_EMPTY(field_generator_fields) /obj/machinery/field/generator/bullet_act(obj/item/projectile/Proj) if(Proj.flag != BULLET && !Proj.nodamage) - power = min(power + Proj.damage, field_generator_max_power) - check_power_level() + energy = min(energy + Proj.damage, FIELD_GENERATOR_MAX_ENERGY) + check_energy_level() return 0 @@ -151,10 +151,10 @@ GLOBAL_LIST_EMPTY(field_generator_fields) return ..() -/obj/machinery/field/generator/proc/check_power_level() - var/new_level = round(num_power_levels * power / field_generator_max_power) - if(new_level != power_level) - power_level = new_level +/obj/machinery/field/generator/proc/check_energy_level() + var/new_level = round(num_energy_levels * energy / FIELD_GENERATOR_MAX_ENERGY) + if(new_level != energy_level) + energy_level = new_level update_icon() /obj/machinery/field/generator/proc/turn_off() @@ -177,49 +177,60 @@ GLOBAL_LIST_EMPTY(field_generator_fields) start_fields() -/obj/machinery/field/generator/proc/calc_power() +/obj/machinery/field/generator/proc/calc_energy() var/power_draw = 2 + length(fields) - if(draw_power(round(power_draw/2, 1))) - check_power_level() - return 1 + if(draw_power(round(power_draw / 2, 1))) + spread_energy() + check_energy_level() + return TRUE else visible_message("[src] shuts down!", "You hear something shutting down.") turn_off() - investigate_log("ran out of power and deactivated","singulo") - power = 0 - check_power_level() - return 0 + investigate_log("ran out of energy and deactivated","singulo") + energy = 0 + check_energy_level() + return FALSE -//This could likely be better, it tends to start loopin if you have a complex generator loop setup. Still works well enough to run the engine fields will likely recode the field gens and fields sometime -Mport -/obj/machinery/field/generator/proc/draw_power(draw = 0, failsafe = 0, obj/machinery/field/generator/G = null, obj/machinery/field/generator/last = null) - if((G && (G == src)) || (failsafe >= 8))//Loopin, set fail +/** +* Draws power. If there isn't enough energy to sustain the draw, draw from connected generators, up to 3 generators away. +* We never do a 180, so at most we should be going around 270 degrees, and never loop. +* +* Arguments: +** draw - Amount of energy needed to sustain powerdraw during this cycle +** failsafe - Current depth of the recursion. We don't let this go above 3. +** last - should be src of the previous call, we check against this to prevent going back and forth between two field generators. +*/ +/obj/machinery/field/generator/proc/draw_power(draw = 0, failsafe = 0, obj/machinery/field/generator/last = null) + if(failsafe >= 3)// Asking at most 3 gens away so we can't loop. return 0 else failsafe++ - if(power >= draw)//We have enough power - power -= draw + if(energy >= draw)// We have enough energy + energy -= draw return 1 - else//Need more power - draw -= power - power = 0 + else//Need more energy + draw -= energy + energy = 0 for(var/CG in connected_gens) var/obj/machinery/field/generator/FG = CG - if(FG == last)//We just asked you + if(FG == last)// We just asked you continue - if(G)//Another gen is askin for power and we dont have it - if(FG.draw_power(draw,failsafe,G,src))//Can you take the load - return 1 - else - return 0 - else//We are askin another for power - if(FG.draw_power(draw,failsafe,src,src)) + else// We are askin another for energy + if(FG.draw_power(draw, failsafe, src)) return 1 else return 0 +/// Sends energy to every neighbour that has less energy +/obj/machinery/field/generator/proc/spread_energy() + for(var/obj/machinery/field/generator/gen as anything in connected_gens) + if(energy > gen.energy + 3) + var/diff = min(energy - gen.energy, FIELD_GENERATOR_MAX_ENERGY - gen.energy)// We don't want to delete energy + gen.energy += diff / 2 + energy -= diff / 2 /obj/machinery/field/generator/proc/start_fields() if(state != FG_WELDED || !anchored) @@ -299,8 +310,8 @@ GLOBAL_LIST_EMPTY(field_generator_fields) for(var/CG in connected_gens) var/obj/machinery/field/generator/FG = CG FG.connected_gens -= src - if(!FG.clean_up)//Makes the other gens clean up as well - FG.cleanup() + if(!FG.clean_up)//Makes the other gens clean up and shutdown as well + FG.turn_off() connected_gens -= FG clean_up = FALSE update_icon() @@ -343,3 +354,5 @@ GLOBAL_LIST_EMPTY(field_generator_fields) #undef FG_OFFLINE #undef FG_CHARGING #undef FG_ONLINE + +#undef FIELD_GENERATOR_MAX_ENERGY