mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 07:08:00 +01:00
[MIRROR] Modular Shield Generators, Also Adds a new perimeter algorithm to _helpers/math_dm [MDB IGNORE] (#21426)
* Modular Shield Generators, Also Adds a new perimeter algorithm to _helpers/math_dm (#75328) Disclaimer im mostly making this pr for the experience if anything. Also anyone can replace the sprites if they want to I`m just making them so itl be done, idk what a plasteel machine is supposed to look like. The circuit boards to make these machines are unlocked by the advanced power manipulation tech The entire shield - Has one big healthpool (base of 50) - Has a configurable radius - Takes damage from hot gas and emp - Has regeneration (it gets nerfed by alot of things that I have to talk about separately) - When the shield is broken the generator must regenerate at 0.25x speed before coming online again - can be configured to either only generate a shield externally (in space) or both internally and externally at the cost of half the regen rate - Regen rate is also reduced based on the ratio of the shield radius and the max radius that the generator is capable of generating - Alot more that im too tired to explain at the moment The base stats of the shield (max health, regen rate, max radius) all scale with the tier of parts used in the main generator. 4 other machines (3 are finished code-wise as of now) the charger (regen rate), the relay (max radius) the well (max health) the node (allows for more connections) can all be connected to the main generator to boost its core stats based on their part tiers In the future there is a possibility of specialization / modifications to the forcefield at the cost to the core stats * Modular Shield Generators, Also Adds a new perimeter algorithm to _helpers/math_dm --------- Co-authored-by: moocowswag <62126254+moocowswag@users.noreply.github.com>
This commit is contained in:
@@ -80,6 +80,41 @@
|
||||
line += locate(current_x_step, current_y_step, starting_z)
|
||||
return line
|
||||
|
||||
/**
|
||||
* Get a list of turfs in a perimeter given the `center_atom` and `radius`.
|
||||
* Automatically rounds down decimals and does not accept values less than positive 1 as they dont play well with it.
|
||||
* Is efficient on large circles but ugly on small ones
|
||||
* Uses [Jesko`s method to the midpoint circle Algorithm](https://en.wikipedia.org/wiki/Midpoint_circle_algorithm).
|
||||
*/
|
||||
/proc/get_perimeter(atom/center, radius)
|
||||
if(radius < 1)
|
||||
return
|
||||
var/rounded_radius = round(radius)
|
||||
var/x = center.x
|
||||
var/y = center.y
|
||||
var/z = center.z
|
||||
var/t1 = rounded_radius/16
|
||||
var/dx = rounded_radius
|
||||
var/dy = 0
|
||||
var/t2
|
||||
var/list/perimeter = list()
|
||||
while(dx >= dy)
|
||||
perimeter += locate(x + dx, y + dy, z)
|
||||
perimeter += locate(x - dx, y + dy, z)
|
||||
perimeter += locate(x + dx, y - dy, z)
|
||||
perimeter += locate(x - dx, y - dy, z)
|
||||
perimeter += locate(x + dy, y + dx, z)
|
||||
perimeter += locate(x - dy, y + dx, z)
|
||||
perimeter += locate(x + dy, y - dx, z)
|
||||
perimeter += locate(x - dy, y - dx, z)
|
||||
dy += 1
|
||||
t1 += dy
|
||||
t2 = t1 - dx
|
||||
if(t2 > 0)
|
||||
t1 = t2
|
||||
dx -= 1
|
||||
return perimeter
|
||||
|
||||
///Format a power value in W, kW, MW, or GW.
|
||||
/proc/display_power(powerused)
|
||||
if(powerused < 1000) //Less than a kW
|
||||
|
||||
@@ -0,0 +1,684 @@
|
||||
/obj/machinery/modular_shield_generator
|
||||
name = "Modular Shield Generator"
|
||||
desc = "A forcefield generator, it seems more stationary than its cousins."
|
||||
icon = 'icons/obj/machines/modular_shield_generator.dmi'
|
||||
icon_state = "gen_recovering_closed"
|
||||
density = TRUE
|
||||
circuit = /obj/item/circuitboard/machine/modular_shield_generator
|
||||
processing_flags = START_PROCESSING_ON_INIT
|
||||
|
||||
///Doesnt actually control it, just tells us if its running or not, you can control by calling procs activate_shields and deactivate_shields
|
||||
var/active = FALSE
|
||||
|
||||
///If the generator is currently spawning the forcefield in
|
||||
var/initiating = FALSE
|
||||
|
||||
///Determins if we can turn it on or not, no longer recovering when back to max strength
|
||||
var/recovering = TRUE
|
||||
|
||||
///Determins max health of the shield
|
||||
var/max_strength = 40
|
||||
|
||||
///Current health of shield
|
||||
var/stored_strength = 0 //starts at 0 to prevent rebuild abuse
|
||||
|
||||
///Shield Regeneration when at 100% efficiency
|
||||
var/max_regeneration = 3
|
||||
|
||||
///The regeneration that the shield can support
|
||||
var/current_regeneration
|
||||
|
||||
///Determins the max radius the shield can support
|
||||
var/max_radius = 3
|
||||
|
||||
///Current radius the shield is set to, minimum 3
|
||||
var/radius = 3
|
||||
|
||||
///Determins if we only generate a shield on space turfs or not
|
||||
var/exterior_only = FALSE
|
||||
|
||||
///The lazy list of shields that are ours
|
||||
var/list/deployed_shields
|
||||
|
||||
///The lazy list of turfs that are within the shield
|
||||
var/list/inside_shield
|
||||
|
||||
///The lazy list of machines that are connected to and boosting us
|
||||
var/list/obj/machinery/modular_shield/module/connected_modules
|
||||
|
||||
///Regeneration gained from machines connected to us
|
||||
var/regen_boost = 0
|
||||
|
||||
///Max Radius gained from machines connected to us
|
||||
var/radius_boost = 0
|
||||
|
||||
///Max Strength gained from machines connected to us
|
||||
var/max_strength_boost = 0
|
||||
|
||||
///Regeneration gained from our own parts
|
||||
var/innate_regen = 3
|
||||
|
||||
///Max radius gained from our own parts
|
||||
var/innate_radius = 3
|
||||
|
||||
///Max strength gained from our own parts
|
||||
var/innate_strength = 40
|
||||
|
||||
///This is the lazy list of perimeter turfs that we grab when making large shields of 10 or more radius
|
||||
var/list/list_of_turfs
|
||||
|
||||
/obj/machinery/modular_shield_generator/power_change()
|
||||
. = ..()
|
||||
if(!(machine_stat & NOPOWER))
|
||||
begin_processing()
|
||||
return
|
||||
|
||||
deactivate_shields()
|
||||
end_processing()
|
||||
|
||||
/obj/machinery/modular_shield_generator/RefreshParts()
|
||||
. = ..()
|
||||
|
||||
innate_regen = initial(innate_regen)
|
||||
innate_radius = initial(innate_radius)
|
||||
innate_strength = initial(innate_strength)
|
||||
|
||||
for(var/datum/stock_part/capacitor/new_capacitor in component_parts)
|
||||
innate_strength += new_capacitor.tier * 10
|
||||
|
||||
for(var/datum/stock_part/servo/new_servo in component_parts)
|
||||
innate_regen += new_servo.tier
|
||||
|
||||
for(var/datum/stock_part/micro_laser/new_laser in component_parts)
|
||||
innate_radius += new_laser.tier * 0.25
|
||||
|
||||
calculate_regeneration()
|
||||
calculate_max_strength()
|
||||
calculate_radius()
|
||||
|
||||
|
||||
/obj/machinery/modular_shield_generator/Initialize(mapload)
|
||||
. = ..()
|
||||
wires = new /datum/wires/modular_shield_generator(src)
|
||||
if(mapload && active && anchored)
|
||||
activate_shields()
|
||||
|
||||
/datum/wires/modular_shield_generator
|
||||
proper_name = "Modular shield generator"
|
||||
randomize = FALSE
|
||||
holder_type = /obj/machinery/modular_shield_generator
|
||||
|
||||
/datum/wires/modular_shield_generator/New(atom/holder)
|
||||
wires = list(WIRE_HACK)
|
||||
return ..()
|
||||
|
||||
/datum/wires/modular_shield_generator/on_pulse(wire)
|
||||
|
||||
var/obj/machinery/modular_shield_generator/shield_gen = holder
|
||||
switch(wire)
|
||||
if(WIRE_HACK)
|
||||
shield_gen.toggle_shields()
|
||||
|
||||
return ..()
|
||||
|
||||
///qdels the forcefield and calls calculate regen to update the regen value accordingly
|
||||
/obj/machinery/modular_shield_generator/proc/deactivate_shields()
|
||||
active = FALSE
|
||||
QDEL_LIST(deployed_shields)
|
||||
deployed_shields = null
|
||||
LAZYNULL(list_of_turfs)
|
||||
LAZYNULL(inside_shield)
|
||||
calculate_regeneration()
|
||||
|
||||
/obj/machinery/modular_shield_generator/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
|
||||
if(default_deconstruction_screwdriver(user,"gen_[!(machine_stat & NOPOWER) ? "[recovering ? "recovering_" : "ready_"]" : "no_power_"]open",
|
||||
"gen_[!(machine_stat & NOPOWER) ? "[recovering ? "recovering_" : "ready_"]" : "no_power_"]closed", tool))
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/modular_shield_generator/crowbar_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
|
||||
if(default_deconstruction_crowbar(tool))
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/modular_shield_generator/attackby(obj/item/W, mob/user, params)
|
||||
|
||||
if(is_wire_tool(W) && panel_open)
|
||||
wires.interact(user)
|
||||
return TRUE
|
||||
|
||||
return ..()
|
||||
|
||||
///toggles the forcefield on and off
|
||||
/obj/machinery/modular_shield_generator/proc/toggle_shields()
|
||||
if(initiating)
|
||||
return
|
||||
if(active)
|
||||
deactivate_shields()
|
||||
return
|
||||
if (recovering)
|
||||
return
|
||||
activate_shields()
|
||||
|
||||
|
||||
///generates the forcefield based on the given radius and calls calculate_regen to update the regen value accordingly
|
||||
/obj/machinery/modular_shield_generator/proc/activate_shields()
|
||||
if(active)//bug or did admin call proc on already active shield gen?
|
||||
return
|
||||
if(radius < 0)//what the fuck are admins doing
|
||||
radius = initial(radius)
|
||||
active = TRUE
|
||||
initiating = TRUE
|
||||
|
||||
if(radius >= 10) //the shield is large so we are going to use the midpoint formula and clamp it to the lowest full number in order to save processing power
|
||||
LAZYADD(inside_shield, circle_range_turfs(src, radius - 1))//in the future we might want to apply an effect to turfs inside the shield
|
||||
LAZYADD(list_of_turfs, get_perimeter(src, radius))
|
||||
|
||||
if(exterior_only)
|
||||
for(var/turf/target_tile as anything in list_of_turfs)
|
||||
if(isspaceturf(target_tile) && !(target_tile in inside_shield) && !(locate(/obj/structure/emergency_shield/modular) in target_tile))
|
||||
var/obj/structure/emergency_shield/modular/deploying_shield = new(target_tile)
|
||||
deploying_shield.shield_generator = src
|
||||
LAZYADD(deployed_shields, deploying_shield)
|
||||
addtimer(CALLBACK(src, PROC_REF(finish_field)), 2 SECONDS)
|
||||
calculate_regeneration()
|
||||
return
|
||||
|
||||
for(var/turf/target_tile as anything in list_of_turfs)
|
||||
if(isopenturf(target_tile) && !(target_tile in inside_shield) && !(locate(/obj/structure/emergency_shield/modular) in target_tile))
|
||||
var/obj/structure/emergency_shield/modular/deploying_shield = new(target_tile)
|
||||
deploying_shield.shield_generator = src
|
||||
LAZYADD(deployed_shields, deploying_shield)
|
||||
addtimer(CALLBACK(src, PROC_REF(finish_field)), 2 SECONDS)
|
||||
calculate_regeneration()
|
||||
return
|
||||
|
||||
//this code only runs on radius less than 10 and gives us a more accurate circle that is more compatible with decimal values
|
||||
LAZYADD(inside_shield, circle_range_turfs(src, radius - 1))//in the future we might want to apply an effect to the turfs inside the shield
|
||||
if(exterior_only)
|
||||
for(var/turf/target_tile as anything in circle_range_turfs(src, radius))
|
||||
if(isspaceturf(target_tile) && !(target_tile in inside_shield) && !(locate(/obj/structure/emergency_shield/modular) in target_tile))
|
||||
var/obj/structure/emergency_shield/modular/deploying_shield = new(target_tile)
|
||||
deploying_shield.shield_generator = src
|
||||
LAZYADD(deployed_shields, deploying_shield)
|
||||
addtimer(CALLBACK(src, PROC_REF(finish_field)), 2 SECONDS)
|
||||
calculate_regeneration()
|
||||
return
|
||||
|
||||
for(var/turf/target_tile as anything in circle_range_turfs(src, radius))
|
||||
if(isopenturf(target_tile) && !(target_tile in inside_shield) && !(locate(/obj/structure/emergency_shield/modular) in target_tile))
|
||||
var/obj/structure/emergency_shield/modular/deploying_shield = new(target_tile)
|
||||
deploying_shield.shield_generator = src
|
||||
LAZYADD(deployed_shields, deploying_shield)
|
||||
addtimer(CALLBACK(src, PROC_REF(finish_field)), 2 SECONDS)
|
||||
calculate_regeneration()
|
||||
|
||||
|
||||
///After giving people a grace period to react to we up the alpha value and make the forcefield dense
|
||||
/obj/machinery/modular_shield_generator/proc/finish_field()
|
||||
|
||||
for(var/obj/structure/emergency_shield/modular/current_shield in deployed_shields)
|
||||
current_shield.density = TRUE
|
||||
current_shield.alpha = 255
|
||||
initiating = FALSE
|
||||
|
||||
/obj/machinery/modular_shield_generator/Destroy()
|
||||
QDEL_LIST(deployed_shields)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/modular_shield_generator/update_icon_state()
|
||||
|
||||
icon_state = ("gen_[!(machine_stat & NOPOWER) ? "[recovering ? "recovering_" : "ready_"]" : "no_power_"][(panel_open)?"open" : "closed"]")
|
||||
return ..()
|
||||
|
||||
//ui stuff
|
||||
/obj/machinery/modular_shield_generator/ui_interact(mob/user, datum/tgui/ui)
|
||||
. = ..()
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "ModularShieldGen")
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/modular_shield_generator/ui_data(mob/user)
|
||||
|
||||
var/list/data = list()
|
||||
data["max_radius"] = max_radius
|
||||
data["current_radius"] = radius
|
||||
data["max_strength"] = max_strength
|
||||
data["max_regeneration"] = max_regeneration
|
||||
data["current_regeneration"] = current_regeneration
|
||||
data["current_strength"] = stored_strength
|
||||
data["active"] = active
|
||||
data["recovering"] = recovering
|
||||
data["exterior_only"] = exterior_only
|
||||
data["initiating_field"] = initiating
|
||||
return data
|
||||
|
||||
/obj/machinery/modular_shield_generator/ui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
switch(action)
|
||||
if ("set_radius")
|
||||
if (active)
|
||||
return
|
||||
var/change_radius = max(1,(text2num(params["new_radius"])))
|
||||
if(change_radius >= 10)
|
||||
radius = round(change_radius)//if its over 10 we dont allow decimals
|
||||
return
|
||||
radius = change_radius
|
||||
|
||||
if ("toggle_shields")
|
||||
toggle_shields()
|
||||
|
||||
if ("toggle_exterior")
|
||||
exterior_only = !exterior_only
|
||||
|
||||
|
||||
///calculations for the stats supplied by the network of machines that boost us
|
||||
/obj/machinery/modular_shield_generator/proc/calculate_boost()
|
||||
|
||||
regen_boost = initial(regen_boost)
|
||||
for (var/obj/machinery/modular_shield/module/charger/new_charger in connected_modules)
|
||||
regen_boost += new_charger.charge_boost
|
||||
|
||||
calculate_regeneration()
|
||||
|
||||
max_strength_boost = initial(max_strength_boost)
|
||||
for (var/obj/machinery/modular_shield/module/well/new_well in connected_modules)
|
||||
max_strength_boost += new_well.strength_boost
|
||||
|
||||
calculate_max_strength()
|
||||
|
||||
radius_boost = initial(radius_boost)
|
||||
for (var/obj/machinery/modular_shield/module/relay/new_relay in connected_modules)
|
||||
radius_boost += new_relay.range_boost
|
||||
|
||||
calculate_radius()
|
||||
|
||||
///Calculates the max radius the shield generator can support, modifiers go here
|
||||
/obj/machinery/modular_shield_generator/proc/calculate_radius()
|
||||
|
||||
max_radius = innate_radius + radius_boost
|
||||
|
||||
if(radius > max_radius)//the generator can no longer function at this capacity
|
||||
deactivate_shields()
|
||||
radius = max_radius
|
||||
|
||||
///Calculates the max strength or health of the forcefield, modifiers go here
|
||||
/obj/machinery/modular_shield_generator/proc/calculate_max_strength()
|
||||
|
||||
max_strength = innate_strength + max_strength_boost
|
||||
begin_processing()
|
||||
|
||||
///Calculates the regeneration based on the status of the generator and boosts from network, modifiers go here
|
||||
/obj/machinery/modular_shield_generator/proc/calculate_regeneration()
|
||||
|
||||
max_regeneration = innate_regen + regen_boost
|
||||
|
||||
if(!active)
|
||||
if(recovering)
|
||||
current_regeneration = max_regeneration * 0.25
|
||||
return
|
||||
current_regeneration = max_regeneration
|
||||
return
|
||||
|
||||
//we lose more than half the regeneration rate when generating a shield that is near the max
|
||||
//radius that we can handle but if we generate a shield with a very small fraction
|
||||
//of the max radius we can support we get a very small bonus multiplier
|
||||
current_regeneration = (max_regeneration / (0.5 + (radius * 2)/max_radius))
|
||||
|
||||
if(!exterior_only)
|
||||
current_regeneration *= 0.5
|
||||
|
||||
///Reduces the strength of the shield based on the given integer
|
||||
/obj/machinery/modular_shield_generator/proc/shield_drain(damage_amount)
|
||||
stored_strength -= damage_amount
|
||||
begin_processing()
|
||||
if (stored_strength < 5)
|
||||
recovering = TRUE
|
||||
deactivate_shields()
|
||||
stored_strength = 0
|
||||
update_icon_state()
|
||||
|
||||
/obj/machinery/modular_shield_generator/process(seconds_per_tick)
|
||||
stored_strength = min((stored_strength + (current_regeneration * seconds_per_tick)),max_strength)
|
||||
if(stored_strength == max_strength)
|
||||
if (recovering)
|
||||
recovering = FALSE
|
||||
calculate_regeneration()
|
||||
update_icon_state()
|
||||
end_processing() //we dont care about continuing to update the alpha, we want to show history of damage to show its unstable
|
||||
if (active)
|
||||
var/random_num = rand(1,deployed_shields.len)
|
||||
var/obj/structure/emergency_shield/modular/random_shield = deployed_shields[random_num]
|
||||
random_shield.alpha = max(255 * (stored_strength/max_strength), 40)
|
||||
|
||||
|
||||
|
||||
//Start of other machines
|
||||
///The general code used for machines that want to connect to the network
|
||||
/obj/machinery/modular_shield/module
|
||||
|
||||
name = "Modular Shield Debugger" //Filler name and sprite for testing
|
||||
desc = "This is filler for testing you shouldn`t see this."
|
||||
icon = 'icons/mecha/mech_bay.dmi'
|
||||
icon_state = "recharge_port"
|
||||
density = TRUE
|
||||
|
||||
///The shield generator we are connected to if we find one or a node provides us one
|
||||
var/obj/machinery/modular_shield_generator/shield_generator
|
||||
|
||||
///The node we are connected to if we find one
|
||||
var/obj/machinery/modular_shield/module/node/connected_node
|
||||
|
||||
///This is the turf that we are facing and able to search for connections through
|
||||
var/turf/connected_turf
|
||||
|
||||
/obj/machinery/modular_shield/module/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
connected_turf = get_step(loc, dir)
|
||||
|
||||
/obj/machinery/modular_shield/module/Destroy()
|
||||
|
||||
if(shield_generator)
|
||||
LAZYREMOVE(shield_generator.connected_modules, (src))
|
||||
shield_generator.calculate_boost()
|
||||
if(connected_node)
|
||||
LAZYREMOVE(connected_node.connected_through_us, (src))
|
||||
return ..()
|
||||
|
||||
/obj/machinery/modular_shield/module/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
if(isnull(shield_generator) && isnull(connected_node))
|
||||
. += "It can be loosened and rotated with a screwdriver and wrench. It can be connected to a node or generator with a multitool."
|
||||
return
|
||||
. += "It can be loosed and rotated with a screwdriver and wrench, rotating it will sever its connection."
|
||||
|
||||
/obj/machinery/modular_shield/module/screwdriver_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
|
||||
panel_open = !(panel_open)
|
||||
tool.play_tool_sound(src, 50)
|
||||
update_icon_state()
|
||||
if(panel_open)
|
||||
balloon_alert(user, "hatch opened")
|
||||
return TRUE
|
||||
balloon_alert(user, "hatch closed")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/modular_shield/module/multitool_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
|
||||
//rather than automatically checking for connections its probably alot less
|
||||
//expensive to just make the players manually multi tool sync each part
|
||||
try_connect(user)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/modular_shield/module/wrench_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
|
||||
if(default_change_direction_wrench(user, tool))
|
||||
if(shield_generator)
|
||||
LAZYREMOVE(shield_generator.connected_modules, (src))
|
||||
shield_generator.calculate_boost()
|
||||
shield_generator = null
|
||||
update_icon_state()
|
||||
if(connected_node)
|
||||
LAZYREMOVE(connected_node.connected_through_us, (src))
|
||||
connected_node = null
|
||||
connected_turf = get_step(loc, dir)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/modular_shield/module/crowbar_act(mob/living/user, obj/item/tool)
|
||||
. = ..()
|
||||
|
||||
if(default_deconstruction_crowbar(tool))
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/machinery/modular_shield/module/setDir(new_dir)
|
||||
. = ..()
|
||||
connected_turf = get_step(loc, dir)
|
||||
|
||||
///checks for a valid machine in front of us and connects to it
|
||||
/obj/machinery/modular_shield/module/proc/try_connect(user)
|
||||
|
||||
if(shield_generator || connected_node)
|
||||
balloon_alert(user, "already connected to something!")
|
||||
return
|
||||
|
||||
shield_generator = (locate(/obj/machinery/modular_shield_generator) in connected_turf)
|
||||
|
||||
if(shield_generator)
|
||||
|
||||
LAZYOR(shield_generator.connected_modules, (src))
|
||||
balloon_alert(user, "connected to generator")
|
||||
update_icon_state()
|
||||
shield_generator.calculate_boost()
|
||||
return
|
||||
|
||||
connected_node = (locate(/obj/machinery/modular_shield/module/node) in connected_turf)
|
||||
|
||||
if(connected_node)
|
||||
|
||||
LAZYOR(connected_node.connected_through_us, (src))
|
||||
shield_generator = connected_node.shield_generator
|
||||
if(shield_generator)
|
||||
LAZYOR(shield_generator.connected_modules, (src))
|
||||
balloon_alert(user, "connected to generator")
|
||||
update_icon_state()
|
||||
shield_generator.calculate_boost()
|
||||
return
|
||||
balloon_alert(user, "connected to node")
|
||||
return
|
||||
balloon_alert(user, "no connection!")
|
||||
|
||||
|
||||
|
||||
/obj/machinery/modular_shield/module/node
|
||||
|
||||
name = "Modular Shield Node"
|
||||
desc = "A waist high mess of humming pipes and wires that extend the modular shield network."
|
||||
icon = 'icons/obj/machines/modular_shield_generator.dmi'
|
||||
icon_state = "node_off_closed"
|
||||
active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.5
|
||||
circuit = /obj/item/circuitboard/machine/modular_shield_node
|
||||
///The lazy list of machines that are connected to us and want connection to a generator
|
||||
var/list/connected_through_us
|
||||
|
||||
/obj/machinery/modular_shield/module/node/update_icon_state()
|
||||
. = ..()
|
||||
if(isnull(shield_generator) || (machine_stat & NOPOWER))
|
||||
icon_state = "node_off_[panel_open ? "open" : "closed"]"
|
||||
return
|
||||
icon_state = "node_on_[panel_open ? "open" : "closed"]"
|
||||
|
||||
/obj/machinery/modular_shield/module/node/setDir(new_dir)
|
||||
. = ..()
|
||||
|
||||
disconnect_connected_through_us()
|
||||
if(isnull(shield_generator))
|
||||
return
|
||||
LAZYREMOVE(shield_generator.connected_modules, (src))
|
||||
shield_generator.calculate_boost()
|
||||
shield_generator = null
|
||||
update_icon_state()
|
||||
|
||||
//after trying to connect to a machine infront of us, we will try to link anything connected to us to a generator
|
||||
/obj/machinery/modular_shield/module/node/try_connect(user)
|
||||
. = ..()
|
||||
|
||||
if(isnull(shield_generator))
|
||||
return
|
||||
connect_connected_through_us()
|
||||
shield_generator.calculate_boost()
|
||||
|
||||
/obj/machinery/modular_shield/module/node/Destroy()
|
||||
. = ..()
|
||||
|
||||
disconnect_connected_through_us()
|
||||
for(var/obj/machinery/modular_shield/module/connected in connected_through_us)
|
||||
connected.connected_node = null
|
||||
if(shield_generator)
|
||||
shield_generator.calculate_boost()
|
||||
|
||||
///If we are connected to a shield generator this proc will connect anything connected to us to that generator
|
||||
/obj/machinery/modular_shield/module/node/proc/connect_connected_through_us()
|
||||
|
||||
if(shield_generator)
|
||||
for(var/obj/machinery/modular_shield/module/connected in connected_through_us)
|
||||
LAZYOR(shield_generator.connected_modules, connected)
|
||||
connected.shield_generator = shield_generator
|
||||
if(istype(connected, /obj/machinery/modular_shield/module/node))
|
||||
var/obj/machinery/modular_shield/module/node/connected_node = connected
|
||||
connected_node.connect_connected_through_us()
|
||||
connected.update_icon_state()
|
||||
|
||||
|
||||
///This proc disconnects modules connected through us from the shield generator in the event that we lose connection
|
||||
/obj/machinery/modular_shield/module/node/proc/disconnect_connected_through_us()
|
||||
|
||||
for(var/obj/machinery/modular_shield/module/connected in connected_through_us)
|
||||
LAZYREMOVE(shield_generator.connected_modules, connected)
|
||||
if(istype(connected, /obj/machinery/modular_shield/module/node))
|
||||
var/obj/machinery/modular_shield/module/node/connected_node = connected
|
||||
connected_node.disconnect_connected_through_us()
|
||||
connected.shield_generator = null
|
||||
connected.update_icon_state()
|
||||
|
||||
/obj/machinery/modular_shield/module/charger
|
||||
|
||||
name = "Modular Shield Charger"
|
||||
desc = "A machine that somehow fabricates hardlight using electrons."
|
||||
icon = 'icons/obj/machines/modular_shield_generator.dmi'
|
||||
icon_state = "charger_off_closed"
|
||||
|
||||
circuit = /obj/item/circuitboard/machine/modular_shield_charger
|
||||
|
||||
///Amount of regeneration this machine grants the connected generator
|
||||
var/charge_boost = 0
|
||||
|
||||
/obj/machinery/modular_shield/module/charger/update_icon_state()
|
||||
. = ..()
|
||||
if(isnull(shield_generator) || (machine_stat & NOPOWER))
|
||||
icon_state = "charger_off_[panel_open ? "open" : "closed"]"
|
||||
return
|
||||
icon_state = "charger_on_[panel_open ? "open" : "closed"]"
|
||||
|
||||
/obj/machinery/modular_shield/module/charger/RefreshParts()
|
||||
. = ..()
|
||||
charge_boost = initial(charge_boost)
|
||||
for(var/datum/stock_part/servo/new_servo in component_parts)
|
||||
charge_boost += new_servo.tier
|
||||
|
||||
if(shield_generator)
|
||||
shield_generator.calculate_boost()
|
||||
|
||||
/obj/machinery/modular_shield/module/relay
|
||||
|
||||
name = "Modular Shield Relay"
|
||||
desc = "It helps the shield generator project farther out."
|
||||
icon = 'icons/obj/machines/modular_shield_generator.dmi'
|
||||
icon_state = "relay_off_closed"
|
||||
|
||||
circuit = /obj/item/circuitboard/machine/modular_shield_relay
|
||||
|
||||
///Amount of max range this machine grants the connected generator
|
||||
var/range_boost = 0
|
||||
|
||||
/obj/machinery/modular_shield/module/relay/update_icon_state()
|
||||
. = ..()
|
||||
if(isnull(shield_generator) || (machine_stat & NOPOWER))
|
||||
icon_state = "relay_off_[panel_open ? "open" : "closed"]"
|
||||
return
|
||||
icon_state = "relay_on_[panel_open ? "open" : "closed"]"
|
||||
|
||||
/obj/machinery/modular_shield/module/relay/RefreshParts()
|
||||
. = ..()
|
||||
range_boost = initial(range_boost)
|
||||
for(var/datum/stock_part/micro_laser/new_laser in component_parts)
|
||||
range_boost += new_laser.tier * 0.25
|
||||
|
||||
if(shield_generator)
|
||||
shield_generator.calculate_boost()
|
||||
|
||||
/obj/machinery/modular_shield/module/well
|
||||
|
||||
name = "Modular Shield Well"
|
||||
desc = "A device used to hold more hardlight for the modular shield generator."
|
||||
icon = 'icons/obj/machines/modular_shield_generator.dmi'
|
||||
icon_state = "well_off_closed"
|
||||
|
||||
circuit = /obj/item/circuitboard/machine/modular_shield_well
|
||||
|
||||
///Amount of max strength this machine grants the connected generator
|
||||
var/strength_boost = 0
|
||||
|
||||
/obj/machinery/modular_shield/module/well/RefreshParts()
|
||||
. = ..()
|
||||
strength_boost = initial(strength_boost)
|
||||
for(var/datum/stock_part/capacitor/new_capacitor in component_parts)
|
||||
strength_boost += new_capacitor.tier * 10
|
||||
|
||||
if(shield_generator)
|
||||
shield_generator.calculate_boost()
|
||||
|
||||
/obj/machinery/modular_shield/module/well/update_icon_state()
|
||||
. = ..()
|
||||
if(isnull(shield_generator) || (machine_stat & NOPOWER))
|
||||
icon_state = "well_off_[panel_open ? "open" : "closed"]"
|
||||
return
|
||||
icon_state = "well_on_[panel_open ? "open" : "closed"]"
|
||||
|
||||
|
||||
//The shield itself
|
||||
/obj/structure/emergency_shield/modular
|
||||
name = "Modular energy shield"
|
||||
desc = "An energy shield with varying configurations."
|
||||
color = "#00ffff"
|
||||
density = FALSE
|
||||
alpha = 100
|
||||
resistance_flags = INDESTRUCTIBLE //the shield itself is indestructible or atleast should be
|
||||
|
||||
///The shield generator sustaining us
|
||||
var/obj/machinery/modular_shield_generator/shield_generator
|
||||
|
||||
|
||||
/obj/structure/emergency_shield/modular/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/atmos_sensitive, mapload)
|
||||
|
||||
/obj/structure/emergency_shield/modular/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
|
||||
return exposed_temperature > (T0C + 400) //starts taking damage from high temps at the same temperature that nonreinforced glass does
|
||||
|
||||
//Damage from atmos
|
||||
/obj/structure/emergency_shield/modular/atmos_expose(datum/gas_mixture/air, exposed_temperature)
|
||||
if(isnull(shield_generator))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
shield_generator.shield_drain(round(air.return_volume() / 400))//400 integer determines how much damage the shield takes from hot atmos (higher value = less damage)
|
||||
|
||||
|
||||
//Damage from direct attacks
|
||||
/obj/structure/emergency_shield/modular/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
|
||||
. = ..()
|
||||
if(damage_type == BRUTE || damage_type == BURN)
|
||||
if(isnull(shield_generator))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
shield_generator.shield_drain(damage_amount)//can add or subtract a flat value to buff or nerf crowd damage
|
||||
|
||||
//Damage from emp
|
||||
/obj/structure/emergency_shield/modular/emp_act(severity)
|
||||
if(isnull(shield_generator))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
shield_generator.shield_drain(15 / severity) //Light is 2 heavy is 1, note emp is usually a large aoe, tweak the number if not enough damage
|
||||
@@ -82,7 +82,8 @@
|
||||
/obj/item/stack/cable_coil = 1,
|
||||
/datum/stock_part/filter = 1,
|
||||
/datum/stock_part/crystal = 1,
|
||||
/datum/stock_part/micro_laser = 2)
|
||||
/datum/stock_part/micro_laser = 2,
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/telecomms/bus
|
||||
name = "Bus Mainframe"
|
||||
@@ -91,7 +92,8 @@
|
||||
req_components = list(
|
||||
/datum/stock_part/servo = 2,
|
||||
/obj/item/stack/cable_coil = 1,
|
||||
/datum/stock_part/filter = 1)
|
||||
/datum/stock_part/filter = 1,
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/telecomms/hub
|
||||
name = "Hub Mainframe"
|
||||
@@ -100,7 +102,8 @@
|
||||
req_components = list(
|
||||
/datum/stock_part/servo = 2,
|
||||
/obj/item/stack/cable_coil = 2,
|
||||
/datum/stock_part/filter = 2)
|
||||
/datum/stock_part/filter = 2,
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/telecomms/message_server
|
||||
name = "Messaging Server"
|
||||
@@ -109,7 +112,8 @@
|
||||
req_components = list(
|
||||
/datum/stock_part/servo = 2,
|
||||
/obj/item/stack/cable_coil = 1,
|
||||
/datum/stock_part/filter = 3)
|
||||
/datum/stock_part/filter = 3,
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/telecomms/processor
|
||||
name = "Processor Unit"
|
||||
@@ -121,7 +125,8 @@
|
||||
/datum/stock_part/treatment = 2,
|
||||
/datum/stock_part/analyzer = 1,
|
||||
/obj/item/stack/cable_coil = 2,
|
||||
/datum/stock_part/amplifier = 1)
|
||||
/datum/stock_part/amplifier = 1,
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/telecomms/receiver
|
||||
name = "Subspace Receiver"
|
||||
@@ -131,7 +136,8 @@
|
||||
/datum/stock_part/ansible = 1,
|
||||
/datum/stock_part/filter = 1,
|
||||
/datum/stock_part/servo = 2,
|
||||
/datum/stock_part/micro_laser = 1)
|
||||
/datum/stock_part/micro_laser = 1,
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/telecomms/relay
|
||||
name = "Relay Mainframe"
|
||||
@@ -140,7 +146,8 @@
|
||||
req_components = list(
|
||||
/datum/stock_part/servo = 2,
|
||||
/obj/item/stack/cable_coil = 2,
|
||||
/datum/stock_part/filter = 2)
|
||||
/datum/stock_part/filter = 2,
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/telecomms/server
|
||||
name = "Telecommunication Server"
|
||||
@@ -149,7 +156,8 @@
|
||||
req_components = list(
|
||||
/datum/stock_part/servo = 2,
|
||||
/obj/item/stack/cable_coil = 1,
|
||||
/datum/stock_part/filter = 1)
|
||||
/datum/stock_part/filter = 1,
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/tesla_coil
|
||||
name = "Tesla Controller"
|
||||
@@ -159,6 +167,53 @@
|
||||
req_components = list(/datum/stock_part/capacitor = 1)
|
||||
needs_anchored = FALSE
|
||||
|
||||
/obj/item/circuitboard/machine/modular_shield_generator
|
||||
name = "Modular Shield Generator"
|
||||
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
|
||||
build_path = /obj/machinery/modular_shield_generator
|
||||
req_components = list(
|
||||
/datum/stock_part/servo = 1,
|
||||
/datum/stock_part/micro_laser = 1,
|
||||
/datum/stock_part/capacitor = 1,
|
||||
/obj/item/stack/sheet/plasteel = 3,
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/modular_shield_node
|
||||
name = "Modular Shield Node"
|
||||
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
|
||||
build_path = /obj/machinery/modular_shield/module/node
|
||||
req_components = list(
|
||||
/obj/item/stack/cable_coil = 15,
|
||||
/obj/item/stack/sheet/plasteel = 2,
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/modular_shield_well
|
||||
name = "Modular Shield Well"
|
||||
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
|
||||
build_path = /obj/machinery/modular_shield/module/well
|
||||
req_components = list(
|
||||
/datum/stock_part/capacitor = 3,
|
||||
/obj/item/stack/sheet/plasteel = 2,
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/modular_shield_relay
|
||||
name = "Modular Shield Relay"
|
||||
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
|
||||
build_path = /obj/machinery/modular_shield/module/relay
|
||||
req_components = list(
|
||||
/datum/stock_part/micro_laser = 3,
|
||||
/obj/item/stack/sheet/plasteel = 2,
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/modular_shield_charger
|
||||
name = "Modular Shield Charger"
|
||||
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
|
||||
build_path = /obj/machinery/modular_shield/module/charger
|
||||
req_components = list(
|
||||
/datum/stock_part/servo = 3,
|
||||
/obj/item/stack/sheet/plasteel = 2,
|
||||
)
|
||||
|
||||
/obj/item/circuitboard/machine/cell_charger
|
||||
name = "Cell Charger"
|
||||
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
|
||||
|
||||
@@ -167,6 +167,56 @@
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_SCIENCE
|
||||
|
||||
/datum/design/board/modular_shield_generator
|
||||
name = "Modular Shield Generator Board"
|
||||
desc = "The circuit board for a modular shield generator."
|
||||
id = "modular_shield_generator"
|
||||
build_path = /obj/item/circuitboard/machine/modular_shield_generator
|
||||
category = list(
|
||||
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ENGINEERING
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING
|
||||
|
||||
/datum/design/board/modular_shield_node
|
||||
name = "Modular Shield Node Board"
|
||||
desc = "The circuit board for a modular shield node."
|
||||
id = "modular_shield_node"
|
||||
build_path = /obj/item/circuitboard/machine/modular_shield_node
|
||||
category = list(
|
||||
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ENGINEERING
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING
|
||||
|
||||
/datum/design/board/modular_shield_relay
|
||||
name = "Modular Shield Relay Board"
|
||||
desc = "The circuit board for a modular shield relay."
|
||||
id = "modular_shield_relay"
|
||||
build_path = /obj/item/circuitboard/machine/modular_shield_relay
|
||||
category = list(
|
||||
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ENGINEERING
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING
|
||||
|
||||
/datum/design/board/modular_shield_charger
|
||||
name = "Modular Shield Charger Board"
|
||||
desc = "The circuit board for a modular shield charger."
|
||||
id = "modular_shield_charger"
|
||||
build_path = /obj/item/circuitboard/machine/modular_shield_charger
|
||||
category = list(
|
||||
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ENGINEERING
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING
|
||||
|
||||
/datum/design/board/modular_shield_well
|
||||
name = "Modular Shield Well Board"
|
||||
desc = "The circuit board for a modular shield well."
|
||||
id = "modular_shield_well"
|
||||
build_path = /obj/item/circuitboard/machine/modular_shield_well
|
||||
category = list(
|
||||
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_ENGINEERING
|
||||
)
|
||||
departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING
|
||||
|
||||
/datum/design/board/teleconsole
|
||||
name = "Teleporter Console Board"
|
||||
desc = "Allows for the construction of circuit boards used to build a teleporter control console."
|
||||
|
||||
@@ -708,6 +708,11 @@
|
||||
"turbine_compressor",
|
||||
"turbine_rotor",
|
||||
"turbine_stator",
|
||||
"modular_shield_generator",
|
||||
"modular_shield_node",
|
||||
"modular_shield_relay",
|
||||
"modular_shield_charger",
|
||||
"modular_shield_well",
|
||||
)
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3500)
|
||||
discount_experiments = list(/datum/experiment/scanning/points/machinery_pinpoint_scan/tier2_capacitors = 2500)
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
@@ -1645,6 +1645,7 @@
|
||||
#include "code\game\machinery\mechlaunchpad.dm"
|
||||
#include "code\game\machinery\medical_kiosk.dm"
|
||||
#include "code\game\machinery\medipen_refiller.dm"
|
||||
#include "code\game\machinery\modular_shield.dm"
|
||||
#include "code\game\machinery\navbeacon.dm"
|
||||
#include "code\game\machinery\PDApainter.dm"
|
||||
#include "code\game\machinery\prisongate.dm"
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import { useBackend } from '../backend';
|
||||
import { Window } from '../layouts';
|
||||
import { Stack, Section, ProgressBar, Button, NumberInput, LabeledList } from '../components';
|
||||
import { BooleanLike } from 'common/react';
|
||||
|
||||
type ModularShieldGenData = {
|
||||
max_strength: number;
|
||||
current_strength: number;
|
||||
max_regeneration: number;
|
||||
current_regeneration: number;
|
||||
max_radius: number;
|
||||
current_radius: number;
|
||||
active: BooleanLike;
|
||||
recovering: BooleanLike;
|
||||
exterior_only: BooleanLike;
|
||||
initiating_field: BooleanLike;
|
||||
};
|
||||
|
||||
export const ModularShieldGen = (props, context) => {
|
||||
const { topLevel } = props;
|
||||
const { act, data } = useBackend<ModularShieldGenData>(context);
|
||||
const {
|
||||
max_strength,
|
||||
max_regeneration,
|
||||
current_regeneration,
|
||||
max_radius,
|
||||
current_radius,
|
||||
current_strength,
|
||||
active,
|
||||
exterior_only,
|
||||
recovering,
|
||||
initiating_field,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Window title="Modular Shield Generator" width={690} height={225}>
|
||||
<Window.Content>
|
||||
<Stack fill>
|
||||
<Stack.Item grow={2}>
|
||||
<Section
|
||||
title="Shield Strength"
|
||||
color={recovering ? 'red' : 'white'}>
|
||||
<ProgressBar
|
||||
title="Shield Strength"
|
||||
value={current_strength}
|
||||
maxValue={max_strength}
|
||||
ranges={{
|
||||
'good': [max_strength * 0.75, max_strength],
|
||||
'average': [max_strength * 0.25, max_strength * 0.75],
|
||||
'bad': [0, max_strength * 0.25],
|
||||
}}>
|
||||
{current_strength}/{max_strength}
|
||||
</ProgressBar>
|
||||
</Section>
|
||||
<Section title="Regeneration and Radius">
|
||||
<ProgressBar
|
||||
title="Regeneration rate"
|
||||
value={current_regeneration}
|
||||
maxValue={max_regeneration}
|
||||
ranges={{
|
||||
'good': [max_regeneration * 0.75, max_regeneration],
|
||||
'average': [max_regeneration * 0.25, max_regeneration * 0.75],
|
||||
'bad': [0, max_regeneration * 0.25],
|
||||
}}>
|
||||
Regeneration {current_regeneration}/{max_regeneration}
|
||||
</ProgressBar>
|
||||
<Section>
|
||||
<ProgressBar
|
||||
title="Shield radius"
|
||||
value={current_radius}
|
||||
maxValue={max_radius}
|
||||
ranges={{
|
||||
'good': [max_radius * 0.75, max_radius],
|
||||
'average': [max_radius * 0.25, max_radius * 0.75],
|
||||
'bad': [0, max_radius * 0.25],
|
||||
}}>
|
||||
Radius {current_radius}/{max_radius}
|
||||
</ProgressBar>
|
||||
</Section>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow>
|
||||
<Section title="Settings">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Set Radius">
|
||||
<NumberInput
|
||||
disabled={active}
|
||||
fluid
|
||||
value={current_radius}
|
||||
minValue={3}
|
||||
maxValue={max_radius}
|
||||
onChange={(e, value) =>
|
||||
act('set_radius', {
|
||||
new_radius: value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Limitations">
|
||||
<Button
|
||||
disabled={active}
|
||||
onClick={() => act('toggle_exterior')}>
|
||||
{exterior_only ? 'External only' : 'Internal & External'}
|
||||
</Button>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Toggle Power">
|
||||
<Button
|
||||
bold={1}
|
||||
disabled={recovering || initiating_field}
|
||||
selected={active}
|
||||
content={active ? 'On' : 'Off'}
|
||||
icon="power-off"
|
||||
onClick={() => act('toggle_shields')}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user