mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-24 05:23:22 +01:00
Unfuck shields by not making them process a huge list constantly. (#21428)
Ship shields currently occupy something like 40% of every machinery process ticks. Basically generators make a fuckhuge list of all generated shields (1.5k in the Horizon's case) and then they iterate over this list every tick strengthening the shields. The idea in this PR is to shunt shield logic to an abstract datum. Fields no longer store strength individually; they store damage taken. They only process once they take damage, they reduce that damage by the field gain tick value every tick, and then they stop processing when they no longer need to. Shield strengthening is shunted off to a signal, so we only need to traverse the big ass list once every round probably. --------- Co-authored-by: Matt Atlas <liermattia@gmail.com>
This commit is contained in:
@@ -71,7 +71,7 @@
|
||||
//If there's shields and it's strong enough, the power of the explosion is reduced, but it won't stop it
|
||||
if(istype(A, /obj/effect/energy_field))
|
||||
var/obj/effect/energy_field/impacted_energy_field = A
|
||||
if(impacted_energy_field.strength > SHIELD_MINIMUM_STRENGTH_TO_REDUCE_EXPLOSION_POWER)
|
||||
if(impacted_energy_field.damage < 1)
|
||||
hitpwr *= 0.5
|
||||
qdel(impacted_energy_field)
|
||||
|
||||
|
||||
@@ -439,7 +439,7 @@ ABSTRACT_TYPE(/mob/living/simple_animal/hostile)
|
||||
found_obj = locate(/obj/effect/energy_field) in target_turf
|
||||
if(found_obj && !found_obj.invisibility && found_obj.density)
|
||||
var/obj/effect/energy_field/e = found_obj
|
||||
e.Stress(rand(0.5, 1.5))
|
||||
e.damage_field(rand(0.5, 1.5))
|
||||
visible_message(SPAN_DANGER("[capitalize_first_letters(src.name)] [attacktext] \the [e]!"))
|
||||
src.do_attack_animation(e)
|
||||
set_last_found_target(e)
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
return
|
||||
if(istype(last_found_target, /obj/effect/energy_field))
|
||||
var/obj/effect/energy_field/e = last_found_target
|
||||
e.Stress(rand(1,2))
|
||||
e.damage_field(rand(1,2))
|
||||
visible_message(SPAN_DANGER("\the [src] bites \the [e]!"))
|
||||
src.do_attack_animation(e)
|
||||
return e
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
|
||||
/datum/artifact_effect/forcefield
|
||||
effecttype = "forcefield"
|
||||
var/list/created_field = list()
|
||||
effect_type = 4
|
||||
|
||||
/datum/artifact_effect/forcefield/New()
|
||||
..()
|
||||
trigger = TRIGGER_TOUCH
|
||||
|
||||
/datum/artifact_effect/forcefield/ToggleActivate()
|
||||
..()
|
||||
if(created_field.len)
|
||||
for(var/obj/effect/energy_field/F in created_field)
|
||||
created_field.Remove(F)
|
||||
qdel(F)
|
||||
else if(holder)
|
||||
var/turf/T = get_turf(holder)
|
||||
while(created_field.len < 16)
|
||||
var/obj/effect/energy_field/E = new (locate(T.x,T.y,T.z))
|
||||
created_field.Add(E)
|
||||
E.strength = 1
|
||||
E.density = 1
|
||||
E.anchored = 1
|
||||
E.set_invisibility(0)
|
||||
spawn(10)
|
||||
UpdateMove()
|
||||
return 1
|
||||
|
||||
/datum/artifact_effect/forcefield/process()
|
||||
..()
|
||||
for(var/obj/effect/energy_field/E in created_field)
|
||||
if(E.strength < 1)
|
||||
E.Strengthen(0.15)
|
||||
else if(E.strength < 5)
|
||||
E.Strengthen(0.25)
|
||||
|
||||
/datum/artifact_effect/forcefield/UpdateMove()
|
||||
if(created_field.len && holder)
|
||||
var/turf/T = get_turf(holder)
|
||||
|
||||
if(!T)
|
||||
return
|
||||
while(created_field.len < 16)
|
||||
//for now, just instantly respawn the fields when they get destroyed
|
||||
var/obj/effect/energy_field/E = new (locate(T.x,T.y,T))
|
||||
created_field.Add(E)
|
||||
E.anchored = 1
|
||||
E.density = 1
|
||||
E.set_invisibility(0)
|
||||
|
||||
var/obj/effect/energy_field/E = created_field[1]
|
||||
E.forceMove(locate(T.x + 2,T.y + 2,T.z))
|
||||
E = created_field[2]
|
||||
E.forceMove(locate(T.x + 2,T.y + 1,T.z))
|
||||
E = created_field[3]
|
||||
E.forceMove(locate(T.x + 2,T.y,T.z))
|
||||
E = created_field[4]
|
||||
E.forceMove(locate(T.x + 2,T.y - 1,T.z))
|
||||
E = created_field[5]
|
||||
E.forceMove(locate(T.x + 2,T.y - 2,T.z))
|
||||
E = created_field[6]
|
||||
E.forceMove(locate(T.x + 1,T.y + 2,T.z))
|
||||
E = created_field[7]
|
||||
E.forceMove(locate(T.x + 1,T.y - 2,T.z))
|
||||
E = created_field[8]
|
||||
E.forceMove(locate(T.x,T.y + 2,T.z))
|
||||
E = created_field[9]
|
||||
E.forceMove(locate(T.x,T.y - 2,T.z))
|
||||
E = created_field[10]
|
||||
E.forceMove(locate(T.x - 1,T.y + 2,T.z))
|
||||
E = created_field[11]
|
||||
E.forceMove(locate(T.x - 1,T.y - 2,T.z))
|
||||
E = created_field[12]
|
||||
E.forceMove(locate(T.x - 2,T.y + 2,T.z))
|
||||
E = created_field[13]
|
||||
E.forceMove(locate(T.x - 2,T.y + 1,T.z))
|
||||
E = created_field[14]
|
||||
E.forceMove(locate(T.x - 2,T.y,T.z))
|
||||
E = created_field[15]
|
||||
E.forceMove(locate(T.x - 2,T.y - 1,T.z))
|
||||
E = created_field[16]
|
||||
E.forceMove(locate(T.x - 2,T.y - 2,T.z))
|
||||
@@ -0,0 +1,101 @@
|
||||
// This is an abstracted energy field to cut down on processing thousands of shields per process tick.
|
||||
/datum/energy_field
|
||||
/// A gigantic ass fucking list of energy fields.
|
||||
var/list/field = list()
|
||||
/// The actual strength of the field.
|
||||
var/field_strength = 0
|
||||
/// Current strengthening rate of a single field.
|
||||
var/strengthen_rate = 0.2
|
||||
/// Maximum rate by which an energy field can be strengthened.
|
||||
var/max_strengthen_rate = 0.5
|
||||
/// The percentage of the shield strength that needs to be replaced each second
|
||||
var/dissipation_rate = 0.030
|
||||
/// An energy field will dissipate by at least this rate in renwicks per field tile (otherwise field would never dissipate completely as dissipation is a percentage)
|
||||
var/min_dissipation = 0.01
|
||||
/// Our target field strength.
|
||||
var/target_field_strength = 10
|
||||
/// The maximum field strength we can go to.
|
||||
var/max_field_strength = 10
|
||||
/// The time passed since the last "fail", AKA losing charge faster than you can replenish it.
|
||||
var/time_since_fail = 100
|
||||
/// How many renwicks per watt.
|
||||
var/energy_conversion_rate = 0.0002
|
||||
/// If the field is strong, then the energy field objects will turn dense.
|
||||
var/strong_field = FALSE
|
||||
|
||||
/datum/energy_field/Destroy(force)
|
||||
clear_field()
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* This proc, called when a shield generator processes, makes the whole thing tick by updating strength and etc.
|
||||
* @assumed_charge: the charge that is given to this energy field. You have to get the required energy first, if you want a balanced field.
|
||||
*/
|
||||
/datum/energy_field/proc/handle_strength(assumed_charge = 0)
|
||||
if(length(field))
|
||||
time_since_fail++
|
||||
//the amount of renwicks that the generator can add this tick, over the entire field
|
||||
var/total_renwick_increase = assumed_charge * energy_conversion_rate
|
||||
|
||||
var/renwick_increase_per_field = total_renwick_increase / length(field) //per field tile
|
||||
var/renwick_upkeep_per_field = max(field_strength * dissipation_rate, min_dissipation)
|
||||
var/amount_to_strengthen = renwick_increase_per_field - renwick_upkeep_per_field
|
||||
field_strength = min(field_strength + amount_to_strengthen, max_field_strength)
|
||||
|
||||
if(field_strength < 1)
|
||||
if(strong_field)
|
||||
strong_field = FALSE
|
||||
SEND_SIGNAL(src, COMSIG_SHIELDS_UPDATE_STRENGTH_STATUS)
|
||||
time_since_fail = 0
|
||||
else
|
||||
if(!strong_field)
|
||||
strong_field = TRUE
|
||||
SEND_SIGNAL(src, COMSIG_SHIELDS_UPDATE_STRENGTH_STATUS)
|
||||
else
|
||||
field_strength = 0
|
||||
|
||||
/**
|
||||
* Returns the required energy upkeep for the field.
|
||||
*/
|
||||
/datum/energy_field/proc/get_required_energy()
|
||||
var/required_energy = 0
|
||||
if(length(field))
|
||||
var/renwick_upkeep_per_field = max(field_strength * dissipation_rate, min_dissipation)
|
||||
var/target_renwick_increase = min(target_field_strength - field_strength, strengthen_rate) + renwick_upkeep_per_field //per field tile
|
||||
required_energy = length(field) * target_renwick_increase / energy_conversion_rate
|
||||
return required_energy
|
||||
|
||||
/**
|
||||
* Clears the field of active field objects.
|
||||
*/
|
||||
/datum/energy_field/proc/clear_field()
|
||||
field_strength = 0
|
||||
strong_field = FALSE
|
||||
for(var/obj/effect/energy_field/D as anything in field)
|
||||
field.Remove(D)
|
||||
qdel(D)
|
||||
|
||||
/**
|
||||
* Sets the shielded turfs of the energy field.
|
||||
*/
|
||||
/datum/energy_field/proc/set_shielded_turfs(list/shielded_turfs)
|
||||
if(length(shielded_turfs))
|
||||
for(var/turf/T in shielded_turfs)
|
||||
var/obj/effect/energy_field/F = new(T, src)
|
||||
field += F
|
||||
|
||||
/**
|
||||
* Adds a bunch of UI data for TGUIs with relevant field data.
|
||||
*/
|
||||
/datum/energy_field/proc/add_field_ui_data(list/data)
|
||||
if(!istype(data))
|
||||
return
|
||||
|
||||
data["average_field"] = round(field_strength, 0.01)
|
||||
data["progress_field"] = (target_field_strength ? round(100 * field_strength / target_field_strength, 0.1) : "NA")
|
||||
data["power_take"] = round(length(field) * max(field_strength * dissipation_rate, min_dissipation) / energy_conversion_rate)
|
||||
data["shield_power"] = round(length(field) * min(strengthen_rate, target_field_strength - field_strength) / energy_conversion_rate)
|
||||
data["strengthen_rate"] = (strengthen_rate * 10)
|
||||
data["max_strengthen_rate"] = (max_strengthen_rate * 10)
|
||||
data["target_field_strength"] = target_field_strength
|
||||
return data
|
||||
@@ -11,20 +11,32 @@
|
||||
anchored = 1
|
||||
layer = ABOVE_HUMAN_LAYER
|
||||
density = 0
|
||||
var/strength = 0
|
||||
/// A ref holding the /datum/energy_field that this field object belongs to.
|
||||
var/datum/energy_field/energy_field
|
||||
/// The damage suffered by the field.
|
||||
var/damage = 0
|
||||
var/ticks_recovering = 10
|
||||
var/diffused_for = 0
|
||||
var/diffused = FALSE
|
||||
|
||||
var/is_strong = FALSE // if strength goes is 1 or above, this is set to TRUE, this is to prevent flickering and animate being called constantly
|
||||
/// If strength goes is 1 or above, this is set to TRUE, this is to prevent flickering and animate being called constantly
|
||||
var/is_strong = FALSE
|
||||
|
||||
atmos_canpass = CANPASS_ALWAYS
|
||||
|
||||
/obj/effect/energy_field/Initialize()
|
||||
/obj/effect/energy_field/Initialize(mapload, datum/energy_field/mother_field)
|
||||
. = ..()
|
||||
if(istype(mother_field))
|
||||
energy_field = mother_field
|
||||
else
|
||||
log_debug("Energy field generated without mother field, deleting.")
|
||||
qdel_self()
|
||||
RegisterSignal(mother_field, COMSIG_SHIELDS_UPDATE_STRENGTH_STATUS, PROC_REF(update_strength))
|
||||
update_nearby_tiles()
|
||||
|
||||
/obj/effect/energy_field/Destroy()
|
||||
if(istype(energy_field))
|
||||
energy_field.field -= src
|
||||
energy_field = null
|
||||
update_nearby_tiles()
|
||||
return ..()
|
||||
|
||||
@@ -39,7 +51,7 @@
|
||||
else
|
||||
user.visible_message(SPAN_WARNING("[user] attacks \the [src] with \the [attacking_item]."),
|
||||
SPAN_WARNING("You attack \the [src] with \the [attacking_item]."))
|
||||
Stress(attacking_item.force / 10)
|
||||
damage_field(attacking_item.force / 10)
|
||||
|
||||
/obj/effect/energy_field/attack_hand(mob/living/carbon/human/H)
|
||||
if(istype(H))
|
||||
@@ -47,35 +59,51 @@
|
||||
H.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
H.do_attack_animation(src, FIST_ATTACK_ANIMATION)
|
||||
H.visible_message(SPAN_WARNING("[H] shreds \the [src]!"), SPAN_WARNING("You shred \the [src]!"))
|
||||
Stress(1)
|
||||
damage_field(1)
|
||||
return
|
||||
to_chat(H, SPAN_WARNING("You touch \the [src], and it repulses your hand."))
|
||||
|
||||
/obj/effect/energy_field/ex_act(var/severity)
|
||||
Stress(0.5 + severity)
|
||||
damage_field(0.5 + severity)
|
||||
|
||||
/obj/effect/energy_field/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
Stress(hitting_projectile.get_structure_damage() / 10)
|
||||
damage_field(hitting_projectile.get_structure_damage() / 10)
|
||||
|
||||
/obj/effect/energy_field/proc/Stress(var/severity)
|
||||
strength -= severity
|
||||
/obj/effect/energy_field/proc/damage_field(var/severity)
|
||||
if(!severity)
|
||||
return
|
||||
|
||||
damage += severity
|
||||
|
||||
if(!(datum_flags & DF_ISPROCESSING))
|
||||
// Start processing ONLY when we're damaged. Through processing, we're going to slowly climb back up to field strength.
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
|
||||
var/shield_health = get_health()
|
||||
//if we take too much damage, drop out - the generator will bring us back up if we have enough power
|
||||
ticks_recovering = min(ticks_recovering + 2, 10)
|
||||
if(strength < 1 && is_strong)
|
||||
if(shield_health < 1 && is_strong)
|
||||
density_check(FALSE)
|
||||
is_strong = FALSE
|
||||
ticks_recovering = 10
|
||||
strength = 0
|
||||
else if(strength >= 1 && !is_strong)
|
||||
else if(shield_health >= 1 && !is_strong)
|
||||
density_check(TRUE)
|
||||
is_strong = TRUE
|
||||
|
||||
//
|
||||
/obj/effect/energy_field/process(seconds_per_tick)
|
||||
if(!damage) // No need to process anymore.
|
||||
update_strength()
|
||||
return PROCESS_KILL
|
||||
|
||||
if(ticks_recovering)
|
||||
ticks_recovering--
|
||||
else
|
||||
damage = max(damage - energy_field.strengthen_rate, 0)
|
||||
|
||||
/obj/effect/energy_field/proc/density_check(var/turn_on)
|
||||
if(turn_on && !diffused)
|
||||
alpha = 0
|
||||
@@ -99,17 +127,15 @@
|
||||
diffused = FALSE
|
||||
density_check(TRUE)
|
||||
|
||||
/obj/effect/energy_field/proc/Strengthen(var/severity)
|
||||
strength += severity
|
||||
if (strength < 0)
|
||||
strength = 0
|
||||
|
||||
/obj/effect/energy_field/proc/update_strength()
|
||||
SIGNAL_HANDLER
|
||||
//if we take too much damage, drop out - the generator will bring us back up if we have enough power
|
||||
var/old_density = density
|
||||
if(strength >= 1 && !is_strong)
|
||||
var/shield_health = get_health()
|
||||
if(shield_health >= 1 && !is_strong)
|
||||
is_strong = TRUE
|
||||
density_check(TRUE)
|
||||
else if(strength < 1 && is_strong)
|
||||
else if(shield_health < 1 && is_strong)
|
||||
is_strong = FALSE
|
||||
density_check(FALSE)
|
||||
|
||||
@@ -118,6 +144,12 @@
|
||||
|
||||
diffuse_check()
|
||||
|
||||
/**
|
||||
* Easy helper proc to return the shield's current health.
|
||||
*/
|
||||
/obj/effect/energy_field/proc/get_health()
|
||||
return max(energy_field.field_strength - damage, 0)
|
||||
|
||||
/obj/effect/energy_field/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
|
||||
@@ -10,41 +10,36 @@
|
||||
desc = "Machine that generates an impenetrable field of energy when activated."
|
||||
icon = 'icons/obj/machinery/shielding.dmi'
|
||||
icon_state = "generator0"
|
||||
var/active = FALSE
|
||||
var/field_radius = 3
|
||||
var/max_field_radius = 100
|
||||
var/list/field
|
||||
density = TRUE
|
||||
var/locked = FALSE
|
||||
var/average_field_strength = 0
|
||||
var/strengthen_rate = 0.2
|
||||
var/max_strengthen_rate = 0.5 //the maximum rate that the generator can increase the average field strength
|
||||
var/dissipation_rate = 0.030 //the percentage of the shield strength that needs to be replaced each second
|
||||
var/min_dissipation = 0.01 //will dissipate by at least this rate in renwicks per field tile (otherwise field would never dissipate completely as dissipation is a percentage)
|
||||
var/powered = FALSE
|
||||
var/check_powered = TRUE
|
||||
var/obj/machinery/shield_capacitor/owned_capacitor
|
||||
var/target_field_strength = 10
|
||||
var/max_field_strength = 10
|
||||
var/time_since_fail = 100
|
||||
var/energy_conversion_rate = 0.0002 //how many renwicks per watt?
|
||||
use_power = POWER_USE_OFF //doesn't use APC power
|
||||
var/multiz = TRUE
|
||||
var/multi_unlocked = TRUE
|
||||
req_one_access = list(ACCESS_CAPTAIN, ACCESS_SECURITY, ACCESS_ENGINE)
|
||||
/// Our owned energy field.
|
||||
var/datum/energy_field/energy_field
|
||||
/// If the machine is powered or not.
|
||||
var/powered = FALSE
|
||||
/// Whether the shield generator is active or not.
|
||||
var/active = FALSE
|
||||
/// ID lock.
|
||||
var/locked = FALSE
|
||||
/// Radius of the field.
|
||||
var/field_radius = 3
|
||||
/// Maximum field radius.
|
||||
var/max_field_radius = 100
|
||||
/// The shield capacitor attached to this shield generator.
|
||||
var/obj/machinery/shield_capacitor/owned_capacitor
|
||||
/// If this shield generator supports multi-z.
|
||||
var/multiz = TRUE
|
||||
|
||||
/obj/machinery/shield_gen/Initialize()
|
||||
for(var/obj/machinery/shield_capacitor/possible_cap in range(1, src))
|
||||
if(get_dir(possible_cap, src) == possible_cap.dir)
|
||||
owned_capacitor = possible_cap
|
||||
break
|
||||
field = list()
|
||||
energy_field = new(src, get_shielded_turfs())
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/shield_gen/Destroy()
|
||||
for(var/obj/effect/energy_field/D as anything in field)
|
||||
field.Remove(D)
|
||||
D.loc = null
|
||||
owned_capacitor = null
|
||||
return ..()
|
||||
|
||||
/obj/machinery/shield_gen/emag_act(var/remaining_charges, var/mob/user)
|
||||
@@ -77,7 +72,6 @@
|
||||
if(get_dir(cap, src) == cap.dir && cap.anchored)
|
||||
owned_capacitor = cap
|
||||
owned_capacitor.owned_gen = src
|
||||
updateDialog()
|
||||
break
|
||||
else
|
||||
if(owned_capacitor && owned_capacitor.owned_gen == src)
|
||||
@@ -128,46 +122,21 @@
|
||||
toggle()
|
||||
return PROCESS_KILL
|
||||
|
||||
average_field_strength = max(average_field_strength, 0)
|
||||
if(istype(energy_field))
|
||||
var/required_energy = energy_field.get_required_energy()
|
||||
var/assumed_charge = assume_charge(required_energy)
|
||||
energy_field.handle_strength(assumed_charge)
|
||||
|
||||
if(field.len)
|
||||
time_since_fail++
|
||||
var/total_renwick_increase = 0 //the amount of renwicks that the generator can add this tick, over the entire field
|
||||
var/renwick_upkeep_per_field = max(average_field_strength * dissipation_rate, min_dissipation)
|
||||
|
||||
//figure out how much energy we need to draw from the capacitor
|
||||
if(active && owned_capacitor?.active)
|
||||
var/target_renwick_increase = min(target_field_strength - average_field_strength, strengthen_rate) + renwick_upkeep_per_field //per field tile
|
||||
|
||||
var/required_energy = field.len * target_renwick_increase / energy_conversion_rate
|
||||
var/assumed_charge = min(owned_capacitor.stored_charge, required_energy)
|
||||
total_renwick_increase = assumed_charge * energy_conversion_rate
|
||||
assumed_charge = max(assumed_charge, 0)
|
||||
owned_capacitor.stored_charge -= assumed_charge
|
||||
else
|
||||
renwick_upkeep_per_field = max(renwick_upkeep_per_field, 0.5)
|
||||
|
||||
var/renwick_increase_per_field = total_renwick_increase/field.len //per field tile
|
||||
|
||||
average_field_strength = 0 //recalculate the average field strength
|
||||
for(var/obj/effect/energy_field/E as anything in field)
|
||||
if(!E)
|
||||
field -= E
|
||||
continue
|
||||
var/amount_to_strengthen = renwick_increase_per_field - renwick_upkeep_per_field
|
||||
if(E.ticks_recovering > 0 && amount_to_strengthen > 0)
|
||||
E.Strengthen( min(amount_to_strengthen / 10, 0.1) )
|
||||
E.ticks_recovering -= 1
|
||||
else
|
||||
E.Strengthen(amount_to_strengthen)
|
||||
|
||||
average_field_strength += E.strength
|
||||
|
||||
average_field_strength /= field.len
|
||||
if(average_field_strength < 1)
|
||||
time_since_fail = 0
|
||||
else
|
||||
average_field_strength = 0
|
||||
/**
|
||||
* Called whenever the field needs to take charge from the capacitor.
|
||||
*/
|
||||
/obj/machinery/shield_gen/proc/assume_charge(required_energy)
|
||||
if(!owned_capacitor)
|
||||
return 0
|
||||
var/assumed_charge = min(owned_capacitor.stored_charge, required_energy)
|
||||
assumed_charge = max(assumed_charge, 0)
|
||||
owned_capacitor.stored_charge -= assumed_charge
|
||||
return assumed_charge
|
||||
|
||||
/obj/machinery/shield_gen/ex_act(var/severity)
|
||||
if(active)
|
||||
@@ -178,22 +147,13 @@
|
||||
active = !active
|
||||
update_icon()
|
||||
if(active)
|
||||
var/list/covered_turfs = get_shielded_turfs()
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/turf/O as anything in covered_turfs - T)
|
||||
var/obj/effect/energy_field/E = new(O)
|
||||
field.Add(E)
|
||||
covered_turfs = null
|
||||
|
||||
for(var/mob/M as anything in hearers(5,src))
|
||||
to_chat(M, "[icon2html(src, M)] You hear heavy droning start up.")
|
||||
to_chat(M, SPAN_NOTICE("[icon2html(src, M)] You hear heavy droning start up."))
|
||||
energy_field.set_shielded_turfs(get_shielded_turfs())
|
||||
else
|
||||
for(var/obj/effect/energy_field/D as anything in field)
|
||||
field.Remove(D)
|
||||
D.loc = null
|
||||
|
||||
for(var/mob/M as anything in hearers(5,src))
|
||||
to_chat(M, "[icon2html(src, M)] You hear heavy droning fade out.")
|
||||
to_chat(M, SPAN_NOTICE("[icon2html(src, M)] You hear heavy droning fade out."))
|
||||
energy_field.clear_field()
|
||||
|
||||
/obj/machinery/shield_gen/update_icon()
|
||||
if(stat & BROKEN)
|
||||
@@ -212,7 +172,7 @@
|
||||
if(field_radius > 0 && T)
|
||||
var/connected_levels = list(T.z)
|
||||
if(multiz)
|
||||
for(var/turf/connected_z_turf as anything in (getzabove(src) + getzbelow(src)))
|
||||
for(var/turf/connected_z_turf as anything in (getzabove(T) + getzbelow(T)))
|
||||
connected_levels += connected_z_turf.z
|
||||
|
||||
. += block(\
|
||||
@@ -235,6 +195,8 @@
|
||||
locate(T.x + field_radius, T.y - field_radius + 1, max(connected_levels))\
|
||||
)
|
||||
|
||||
return . - get_turf(src)
|
||||
|
||||
/obj/machinery/shield_gen/ui_interact(mob/user, var/datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
@@ -246,19 +208,12 @@
|
||||
|
||||
data["owned_capacitor"] = !!owned_capacitor
|
||||
data["active"] = active
|
||||
data["time_since_fail"] = time_since_fail
|
||||
data["multi_unlocked"] = multi_unlocked
|
||||
data["time_since_fail"] = energy_field ? energy_field.time_since_fail : 0
|
||||
data["multiz"] = multiz
|
||||
data["field_radius"] = field_radius
|
||||
data["min_field_radius"] = 1
|
||||
data["max_field_radius"] = max_field_radius
|
||||
data["average_field"] = round(average_field_strength, 0.01)
|
||||
data["progress_field"] = (target_field_strength ? round(100 * average_field_strength / target_field_strength, 0.1) : "NA")
|
||||
data["power_take"] = round(field.len * max(average_field_strength * dissipation_rate, min_dissipation) / energy_conversion_rate)
|
||||
data["shield_power"] = round(field.len * min(strengthen_rate, target_field_strength - average_field_strength) / energy_conversion_rate)
|
||||
data["strengthen_rate"] = (strengthen_rate * 10)
|
||||
data["max_strengthen_rate"] = (max_strengthen_rate * 10)
|
||||
data["target_field_strength"] = target_field_strength
|
||||
data = energy_field.add_field_ui_data(data)
|
||||
|
||||
return data
|
||||
|
||||
@@ -278,10 +233,10 @@
|
||||
field_radius = between(1, text2num(params["size_set"]), max_field_radius)
|
||||
|
||||
if ("charge_set")
|
||||
strengthen_rate = (between(1, text2num(params["charge_set"]), (max_strengthen_rate * 10)) / 10)
|
||||
energy_field.strengthen_rate = (between(1, text2num(params["charge_set"]), (energy_field.max_strengthen_rate * 10)) / 10)
|
||||
|
||||
if ("field_set")
|
||||
target_field_strength = between(1, text2num(params["field_set"]), 10)
|
||||
energy_field.target_field_strength = between(1, text2num(params["field_set"]), 10)
|
||||
|
||||
add_fingerprint(usr)
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
/obj/machinery/shield_gen/external
|
||||
name = "hull shield generator"
|
||||
multi_unlocked = TRUE
|
||||
|
||||
//Search for space turfs within range that are adjacent to a simulated turf.
|
||||
/obj/machinery/shield_gen/external/get_shielded_turfs()
|
||||
|
||||
Reference in New Issue
Block a user