Singulo engine buff (#26929)

* iteration 1

* oops

* Okay now it actually works

* remove rad cap

* Adds a singulo monitor

* comments and other fixes

* rebuild tgui

* updates last size now. breach alerts now go before warnings

* oops

* fix console lables for the field gens

* New generator lookup algorithm

* comment added

* sort out the return and checks on temp_gens

* Adds sprites to the singulo monitor

* fix sprite stuff and singulo alert

* rebuild tgui

* Adds a singulo monitor board to RnD.  Uses the correct icon when no singulo is being monitored.

* give commas some space

* Adds a singulo console board to the singulo engine crate

* style fixes and fixes the check for singularity location and type

* Rebuild Tgui

* style fixes and a comment

* Removes redundant brackets

* Correct the check for there being containing generators

* Changes the generator_field variable to a more generic name

* adds a period to a comment

* Restore accidentally modified icons to their original state

* Rebuild TGUI

* Rebuild tgui

* rebuild tgui

* Rebuild TGUI

* rebuild tgui

* TGUI rebuild

* Style fixes

* TGUI rebuild

* rebuild tgui

* rebuild tgui

* Let's see if this works

* I didn't see that merge conflict. Rebuilding again

* rebuild tgui

* Rebuild TGUI

* Review changes

* Changes to the new variable name in the singulo monitor

* Adjusts bar values for each colour according to the reduced energy capacity of the new generators

* Rebuild TGUI

* Review changes

* missed a line
This commit is contained in:
Migratingcocofruit
2024-11-14 18:48:38 +02:00
committed by GitHub
parent 6520ce469c
commit 627fe1e059
14 changed files with 578 additions and 94 deletions
@@ -64,7 +64,7 @@
if(ismachinery(mover) || isstructure(mover) || ismecha(mover))
bump_field(mover)
/obj/machinery/field/containment/proc/set_master(master1,master2)
/obj/machinery/field/containment/proc/set_master(master1, master2)
if(!master1 || !master2)
return 0
FG1 = master1
@@ -99,7 +99,7 @@
/obj/machinery/field/proc/shock_field(mob/living/user)
if(isliving(user))
var/shock_damage = min(rand(30,40),rand(30,40))
var/shock_damage = min(rand(30, 40), rand(30, 40))
if(isliving(user) && !issilicon(user))
var/stun = (min(shock_damage, 15)) STATUS_EFFECT_CONSTANT
@@ -60,6 +60,50 @@ GLOBAL_LIST_EMPTY(field_generator_fields)
if(active == FG_ONLINE)
calc_energy()
/**
* Gets a list of generators that form a field that is enclosing a given singularity, if such a field exists.
*
* Arguments:
* * _dir - The direction in which we are currently going
* * singulo - The singularity we are looking to contain
* * containment_gens - A list of generators which is the portion of the potential result we have so far.
*/
/obj/machinery/field/generator/proc/find_containment_gens(_dir, obj/singularity/singulo, list/containment_gens = list())
// We can't go in a direction that doesn't exist
if(!dir)
return
containment_gens |= src
// This is used to evaluate a path before returning it. We don't want to stop after the first dead end.
var/list/temp_gens = list()
for(var/obj/machinery/field/generator/gen in connected_gens)
// We don't ever want to do anything with the generator behind us so this check comes first
if(get_dir(src, gen) == turn(_dir, 180))
continue
// If we completed a full circle and it contains the singularity return it. Otherwise continue
if(gen in containment_gens)
if(singulo.in_containment(containment_gens))
return containment_gens
continue
// Go right if we can, forward if we can't go right, and left if we can't go forward
if(get_dir(src, gen) == turn(_dir, -90))
temp_gens = gen.find_containment_gens(turn(_dir, -90), singulo, containment_gens)
if(length(temp_gens))
return temp_gens
if(get_dir(src, gen) == _dir)
temp_gens = gen.find_containment_gens(_dir, singulo, containment_gens)
if(length(temp_gens))
return temp_gens
if(get_dir(src, gen) == turn(_dir, 90))
temp_gens = gen.find_containment_gens(turn(_dir, 90), singulo, containment_gens)
if(length(temp_gens))
return temp_gens
// We got to a dead end, temp_gens should be empty here.
return temp_gens
/obj/machinery/field/generator/attack_hand(mob/user)
if(state == FG_WELDED)
if(get_dist(src, user) <= 1)//Need to actually touch the thing to turn it on
@@ -71,7 +115,7 @@ GLOBAL_LIST_EMPTY(field_generator_fields)
"<span class='notice'>You turn on [src].</span>", \
"<span class='italics'>You hear heavy droning.</span>")
turn_on()
investigate_log("<font color='green'>activated</font> by [user.key].","singulo")
investigate_log("<font color='green'>activated</font> by [user.key].", "singulo")
add_fingerprint(user)
else
@@ -283,11 +327,11 @@ GLOBAL_LIST_EMPTY(field_generator_fields)
T = loc
for(var/dist in 0 to steps) // creates each field tile
var/field_dir = get_dir(T,get_step(G.loc, NSEW))
var/field_dir = get_dir(T, get_step(G.loc, NSEW))
T = get_step(T, NSEW)
if(!locate(/obj/machinery/field/containment) in T)
var/obj/machinery/field/containment/CF = new/obj/machinery/field/containment()
CF.set_master(src,G)
CF.set_master(src, G)
CF.loc = T
CF.dir = field_dir
fields += CF
@@ -336,7 +380,7 @@ GLOBAL_LIST_EMPTY(field_generator_fields)
// [src ? "[get_location_name(src, TRUE)] [COORD(src)]" : "nonexistent location"] [ADMIN_JMP(src)] works much better and actually works at all
// Oh and yes, this exact comment was pasted from the exact same thing I did to tcomms code. Dont at me.
message_admins("A singularity exists and a containment field has failed on the same Z-Level. Singulo location: [O ? "[get_location_name(O, TRUE)] [COORD(O)]" : "nonexistent location"] [ADMIN_JMP(O)] | Field generator location: [src ? "[get_location_name(src, TRUE)] [COORD(src)]" : "nonexistent location"] [ADMIN_JMP(src)]")
investigate_log("has <font color='red'>failed</font> whilst a singulo exists.","singulo")
investigate_log("has <font color='red'>failed</font> whilst a singulo exists.", "singulo")
O.last_warning = world.time
/obj/machinery/field/generator/shock_field(mob/living/user)
@@ -1,3 +1,6 @@
/// Amount of singulos created during the round(note that this will include teslas as well)
GLOBAL_VAR_INIT(global_singulo_id, 1)
/obj/singularity
name = "gravitational singularity"
desc = "A gravitational singularity."
@@ -35,9 +38,12 @@
var/isnt_shutting_down = FALSE
/// Init list that has all the areas that we can possibly move to, to reduce processing impact
var/list/all_possible_areas = list()
/// Id for monitoring.
var/singulo_id = 1
/obj/singularity/Initialize(mapload, starting_energy = 50)
. = ..()
singulo_id = GLOB.global_singulo_id++
//CARN: admin-alert for chuckle-fuckery.
admin_investigate_setup()
@@ -109,15 +115,15 @@
switch(severity)
if(1)
if(current_size <= STAGE_TWO)
investigate_log("has been destroyed by a heavy explosion.","singulo")
investigate_log("has been destroyed by a heavy explosion.", "singulo")
qdel(src)
return
else
energy -= round(((energy+1)/2),1)
energy -= round(((energy + 1) / 2), 1)
if(2)
energy -= round(((energy+1)/3),1)
energy -= round(((energy + 1) / 3), 1)
if(3)
energy -= round(((energy+1)/4),1)
energy -= round(((energy + 1) / 4), 1)
return
@@ -143,7 +149,7 @@
// it might mean we are stuck in a corner somewere. So move around to try to expand.
move()
if(current_size >= STAGE_TWO)
radiation_pulse(src, min(5000, (energy * 4.5) + 1000), RAD_DISTANCE_COEFFICIENT * 0.5)
radiation_pulse(src, (energy * 4.5) + 1000, RAD_DISTANCE_COEFFICIENT, source_radius = consume_range + 1)
if(prob(event_chance))//Chance for it to run a special event TODO:Come up with one or two more that fit
event()
eat()
@@ -163,7 +169,7 @@
var/count = locate(/obj/machinery/field/containment) in urange(30, src, 1)
if(!count)
message_admins("A singularity has been created without containment fields active at [x], [y], [z] (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
investigate_log("was created. [count?"":"<font color='red'>No containment fields were active</font>"]","singulo")
investigate_log("was created. [count ? "" : "<font color='red'>No containment fields were active</font>"]", "singulo")
/obj/singularity/proc/do_dissipate()
if(!dissipate)
@@ -197,7 +203,7 @@
vis_contents -= warp
qdel(warp)
if(STAGE_TWO)
if((check_turfs_in(1,1))&&(check_turfs_in(2,1))&&(check_turfs_in(4,1))&&(check_turfs_in(8,1)))
if((check_turfs_in(1, 1))&&(check_turfs_in(2, 1))&&(check_turfs_in(4, 1))&&(check_turfs_in(8, 1)))
current_size = STAGE_TWO
icon = 'icons/effects/96x96.dmi'
icon_state = "singularity_s3"
@@ -212,7 +218,7 @@
warp = new(src)
vis_contents += warp
if(STAGE_THREE)
if((check_turfs_in(1,2))&&(check_turfs_in(2,2))&&(check_turfs_in(4,2))&&(check_turfs_in(8,2)))
if((check_turfs_in(1, 2))&&(check_turfs_in(2, 2))&&(check_turfs_in(4, 2))&&(check_turfs_in(8, 2)))
current_size = STAGE_THREE
icon = 'icons/effects/160x160.dmi'
icon_state = "singularity_s5"
@@ -227,7 +233,7 @@
warp = new(src)
vis_contents += warp
if(STAGE_FOUR)
if((check_turfs_in(1,3))&&(check_turfs_in(2,3))&&(check_turfs_in(4,3))&&(check_turfs_in(8,3)))
if((check_turfs_in(1, 3))&&(check_turfs_in(2, 3))&&(check_turfs_in(4, 3))&&(check_turfs_in(8, 3)))
current_size = STAGE_FOUR
icon = 'icons/effects/224x224.dmi'
icon_state = "singularity_s7"
@@ -238,7 +244,6 @@
dissipate_delay = 10
dissipate_track = 0
dissipate_strength = 10
notify_dead()
if(STAGE_FIVE)//this one also lacks a check for gens because it eats everything
current_size = STAGE_FIVE
icon = 'icons/effects/288x288.dmi'
@@ -257,8 +262,10 @@
grav_pull = 15
consume_range = 5
dissipate = FALSE
if(current_size >= STAGE_FIVE)
notify_dead()
if(current_size == allowed_size)
investigate_log("<font color='red'>grew to size [current_size]</font>","singulo")
investigate_log("<font color='red'>grew to size [current_size]</font>", "singulo")
return 1
else if(current_size < (--temp_allowed_size))
expand(temp_allowed_size)
@@ -268,20 +275,20 @@
/obj/singularity/proc/check_energy()
if(energy <= 0)
investigate_log("collapsed.","singulo")
investigate_log("collapsed.", "singulo")
qdel(src)
return 0
switch(energy)//Some of these numbers might need to be changed up later -Mport
if(1 to 199)
if(1 to (STAGE_TWO_THRESHOLD - 1))
allowed_size = STAGE_ONE
if(200 to 499)
if(STAGE_TWO_THRESHOLD to (STAGE_THREE_THRESHOLD - 1))
allowed_size = STAGE_TWO
if(500 to 999)
if(STAGE_THREE_THRESHOLD to (STAGE_FOUR_THRESHOLD - 1))
allowed_size = STAGE_THREE
if(1000 to 1999)
if(STAGE_FOUR_THRESHOLD to (STAGE_FIVE_THRESHOLD - 1))
allowed_size = STAGE_FOUR
if(2000 to INFINITY)
if(energy >= 3000 && consumedSupermatter)
if(STAGE_FIVE_THRESHOLD to INFINITY)
if(energy >= STAGE_SIX_THRESHOLD && consumedSupermatter)
allowed_size = STAGE_SIX
else
allowed_size = STAGE_FIVE
@@ -320,7 +327,7 @@
qdel(A)
else
visible_message("<span class='userdanger'>[GET_CULT_DATA(entity_name, A.name)] strikes down [src]!</span>")
investigate_log("has been destroyed by Nar'Sie","singulo")
investigate_log("has been destroyed by Nar'Sie", "singulo")
qdel(src)
return
@@ -369,7 +376,7 @@
var/list/turfs = list()
var/turf/T = src.loc
for(var/i = 1 to steps)
T = get_step(T,direction)
T = get_step(T, direction)
if(!isturf(T))
return 0
turfs.Add(T)
@@ -384,12 +391,12 @@
dir3 = 2
var/turf/T2 = T
for(var/j = 1 to steps-1)
T2 = get_step(T2,dir2)
T2 = get_step(T2, dir2)
if(!isturf(T2))
return 0
turfs.Add(T2)
for(var/k = 1 to steps-1)
T = get_step(T,dir3)
T = get_step(T, dir3)
if(!isturf(T))
return 0
turfs.Add(T)
@@ -400,6 +407,21 @@
return 0
return 1
// Returns a list of the field generators generating the containing field(if there is one within 10 tiles)
/obj/singularity/proc/find_field_gens()
for(var/_dir in list(NORTH, SOUTH, EAST, WEST))
var/turf/T = loc
for(var/i in 1 to 10)
T = get_step(T, _dir)
var/obj/cur_field_obj
cur_field_obj = locate(/obj/machinery/field/generator) in T
if(cur_field_obj)
var/obj/machinery/field/generator/gen = cur_field_obj
return gen.find_containment_gens(turn(_dir, -90), src)
cur_field_obj = locate(/obj/machinery/field/containment) in T
if(cur_field_obj)
var/obj/machinery/field/containment/field = cur_field_obj
return field.FG1.find_containment_gens(turn(_dir, -90), src)
/obj/singularity/proc/can_move(turf/T)
if(!T)
@@ -486,8 +508,8 @@
/obj/singularity/singularity_act()
var/gain = (energy/2)
var/dist = max((current_size - 2),1)
explosion(src.loc,(dist),(dist*2),(dist*4))
var/dist = max((current_size - 2), 1)
explosion(loc, (dist), (dist * 2), (dist * 4))
qdel(src)
return(gain)
@@ -564,3 +586,28 @@
/obj/singularity/deadchat_controlled/Initialize(mapload, starting_energy)
. = ..()
deadchat_plays(mode = DEADCHAT_DEMOCRACY_MODE)
/**
* Gets a list of field generators that generate the field that contains the singularity
* and returns their most extreme coordinates.
**/
/obj/singularity/proc/in_containment(list/containment_gens)
if(!length(containment_gens))
return FALSE
var/max_x = -1
var/max_y = -1
var/min_x = -1
var/min_y = -1
for(var/obj/machinery/field/generator/gen in containment_gens)
if(gen.x > max_x || max_x < 0)
max_x = gen.x
if(gen.y > max_y || max_y < 0)
max_y = gen.y
if(gen.x < min_x || min_x < 0)
min_x = gen.x
if(gen.y < min_y || min_y < 0)
min_y = gen.y
return (x <= max_x && x >= min_x && y <= max_y && y >= min_y)
@@ -302,6 +302,16 @@
build_path = /obj/item/circuitboard/sm_monitor
category = list("Computer Boards")
/datum/design/singulo_monitor
name = "Console Board (Singularity Monitoring)"
desc = "Allows for the construction of circuit boards used to build a singularity monitoring console."
id = "singulo_monitor"
req_tech = list("programming" = 2, "powerstorage" = 2)
build_type = IMPRINTER
materials = list(MAT_GLASS = 1000)
build_path = /obj/item/circuitboard/singulo_monitor
category = list("Computer Boards")
/datum/design/ordercomp
name = "Console Board (Supply Ordering Console)"
desc = "Allows for the construction of circuit boards used to build a supply ordering console."
@@ -123,7 +123,7 @@
/datum/supply_packs/engineering/engine/sing_gen
name = "Singularity Generator Crate"
contains = list(/obj/machinery/the_singularitygen)
contains = list(/obj/machinery/the_singularitygen, /obj/item/circuitboard/singulo_monitor)
cost = 350
containername = "singularity generator crate"