mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-27 09:41:40 +00:00
Refactored (second passage) how movement works, now it's mostly in line with TG handling and avoids calling 3 gazillion Cross() Uncross() etc. on every atom in a turf. Fixed EMP protection from species not actually protecting (this includes the surge prevention for IPCs). Fixed EMP 3D calculation runtiming because I forgot to make the value absolute and it was doing the square root of a negative number. It's now possible to queue the round to start with the Start Round verb even while the system is initializing, for an even faster pain train to enter the round and test things.
512 lines
15 KiB
Plaintext
512 lines
15 KiB
Plaintext
#define POWER_IDLE 0
|
|
#define POWER_UP 1
|
|
#define POWER_DOWN 2
|
|
|
|
#define GRAV_NEEDS_SCREWDRIVER 0
|
|
#define GRAV_NEEDS_WELDING 1
|
|
#define GRAV_NEEDS_PLASTEEL 2
|
|
#define GRAV_NEEDS_WRENCH 3
|
|
|
|
#define AREA_ERRNONE 0
|
|
#define AREA_STATION 1
|
|
#define AREA_SPACE 2
|
|
#define AREA_SPECIAL 3
|
|
//
|
|
// Abstract Generator
|
|
//
|
|
|
|
/obj/machinery/gravity_generator
|
|
name = "gravitational generator"
|
|
desc = "A device which produces a gravaton field when set up."
|
|
icon = 'icons/obj/machinery/gravity_generator.dmi'
|
|
anchored = 1
|
|
density = 1
|
|
use_power = POWER_USE_OFF
|
|
unacidable = 1
|
|
var/sprite_number = 0
|
|
light_color = LIGHT_COLOR_CYAN
|
|
light_power = 1
|
|
light_range = 8
|
|
var/datum/looping_sound/gravgen/soundloop
|
|
|
|
/obj/machinery/gravity_generator/ex_act(severity)
|
|
if(severity == 1) // Very sturdy.
|
|
set_broken()
|
|
|
|
/obj/machinery/gravity_generator/update_icon()
|
|
..()
|
|
icon_state = "[get_status()]_[sprite_number]"
|
|
|
|
/obj/machinery/gravity_generator/proc/get_status()
|
|
return "off"
|
|
|
|
// You aren't allowed to move.
|
|
/obj/machinery/gravity_generator/Move()
|
|
. = ..()
|
|
qdel(src)
|
|
|
|
/obj/machinery/gravity_generator/proc/set_broken()
|
|
stat |= BROKEN
|
|
|
|
/obj/machinery/gravity_generator/proc/set_fix()
|
|
stat &= ~BROKEN
|
|
|
|
/obj/machinery/gravity_generator/part/Destroy()
|
|
set_broken()
|
|
if(main_part)
|
|
qdel(main_part)
|
|
return ..()
|
|
|
|
//
|
|
// Part generator which is mostly there for looks
|
|
//
|
|
|
|
/obj/machinery/gravity_generator/part
|
|
var/obj/machinery/gravity_generator/main/main_part = null
|
|
|
|
/obj/machinery/gravity_generator/part/attackby(obj/item/attacking_item, mob/user)
|
|
return main_part.attackby(attacking_item, user)
|
|
|
|
/obj/machinery/gravity_generator/part/get_status()
|
|
return main_part.get_status()
|
|
|
|
/obj/machinery/gravity_generator/part/attack_hand(mob/user as mob)
|
|
return main_part.attack_hand(user)
|
|
|
|
/obj/machinery/gravity_generator/part/set_broken()
|
|
..()
|
|
if(main_part && !(main_part.stat & BROKEN))
|
|
main_part.set_broken()
|
|
|
|
//
|
|
// Generator which spawns with the station.
|
|
//
|
|
|
|
/obj/machinery/gravity_generator/main/station/Initialize()
|
|
. = ..()
|
|
setup_parts()
|
|
middle.AddOverlays("activated")
|
|
update_list(TRUE)
|
|
addtimer(CALLBACK(src, PROC_REF(round_startset)), 100)
|
|
|
|
/obj/machinery/gravity_generator/main/station/proc/round_startset()
|
|
if(round_start >= 1)
|
|
round_start--
|
|
set_light(8,1,LIGHT_COLOR_CYAN)
|
|
|
|
//
|
|
// Generator an admin can spawn
|
|
//
|
|
|
|
/obj/machinery/gravity_generator/main/station/admin/Initialize()
|
|
. = ..()
|
|
round_start = 1
|
|
|
|
//
|
|
// Main Generator with the main code
|
|
//
|
|
|
|
/obj/machinery/gravity_generator/main
|
|
icon_state = "on_8"
|
|
idle_power_usage = 0
|
|
active_power_usage = 3000
|
|
power_channel = AREA_USAGE_ENVIRON
|
|
sprite_number = 8
|
|
interact_offline = 1
|
|
var/on = 1
|
|
var/breaker = 1
|
|
var/list/parts = list()
|
|
var/obj/middle = null
|
|
var/charging_state = POWER_IDLE
|
|
var/charge_count = 100
|
|
var/current_overlay = null
|
|
var/broken_state = 0
|
|
var/list/localareas = list()
|
|
var/round_start = 2 //To help stop a bug with round start
|
|
var/backpanelopen = 0
|
|
var/eventon = 0
|
|
|
|
/obj/machinery/gravity_generator/main/Destroy()
|
|
LOG_DEBUG("Gravity Generator Destroyed")
|
|
investigate_log("was destroyed!", "gravity")
|
|
on = 0
|
|
QDEL_NULL(soundloop)
|
|
update_list(TRUE)
|
|
for(var/obj/machinery/gravity_generator/part/O in parts)
|
|
O.main_part = null
|
|
qdel(O)
|
|
linked?.gravity_generator = null
|
|
return ..()
|
|
|
|
/obj/machinery/gravity_generator/main/proc/eventshutofftoggle() // Used by the gravity event. Bypasses charging and all of that stuff.
|
|
breaker = 0
|
|
set_state(eventon)
|
|
sleep(20)
|
|
charge_count = 0
|
|
breaker = 1
|
|
charging_state = POWER_UP
|
|
set_power()
|
|
eventon = !eventon
|
|
addtimer(CALLBACK(src, PROC_REF(reset_event)), 100) // Because it takes 100 seconds for it to recharge. And we need to make sure we resen this var
|
|
|
|
/obj/machinery/gravity_generator/main/proc/reset_event()
|
|
eventon = !eventon
|
|
|
|
/obj/machinery/gravity_generator/main/proc/setup_parts()
|
|
var/turf/our_turf = get_turf(src)
|
|
// 9x9 block obtained from the bottom middle of the block
|
|
var/list/spawn_turfs = block(locate(our_turf.x - 1, our_turf.y + 2, our_turf.z), locate(our_turf.x + 1, our_turf.y, our_turf.z))
|
|
var/count = 10
|
|
for(var/turf/T in spawn_turfs)
|
|
count--
|
|
if(T == our_turf) // Skip our turf.
|
|
continue
|
|
var/obj/machinery/gravity_generator/part/part = new(T)
|
|
if(count == 5) // Middle
|
|
middle = part
|
|
if(count <= 3) // Their sprite is the top part of the generator
|
|
part.density = 0
|
|
part.layer = MOB_LAYER + 0.1
|
|
part.sprite_number = count
|
|
part.main_part = src
|
|
parts += part
|
|
part.update_icon()
|
|
|
|
/obj/machinery/gravity_generator/main/proc/connected_parts()
|
|
return parts.len == 8
|
|
|
|
/obj/machinery/gravity_generator/main/set_broken()
|
|
..()
|
|
for(var/obj/machinery/gravity_generator/M in parts)
|
|
if(!(M.stat & BROKEN))
|
|
M.set_broken()
|
|
middle.ClearOverlays()
|
|
charge_count = 0
|
|
breaker = 0
|
|
set_power()
|
|
set_state(0)
|
|
investigate_log("has broken down.", "gravity")
|
|
|
|
/obj/machinery/gravity_generator/main/set_fix()
|
|
..()
|
|
for(var/obj/machinery/gravity_generator/M in parts)
|
|
if(M.stat & BROKEN)
|
|
M.set_fix()
|
|
broken_state = 0
|
|
update_icon()
|
|
set_power()
|
|
|
|
// Interaction
|
|
|
|
// Fixing the gravity generator.
|
|
/obj/machinery/gravity_generator/main/attackby(obj/item/attacking_item, mob/user)
|
|
var/old_broken_state = broken_state
|
|
switch(broken_state)
|
|
if(GRAV_NEEDS_SCREWDRIVER)
|
|
if(attacking_item.isscrewdriver())
|
|
to_chat(user, SPAN_NOTICE("You secure the screws of the framework."))
|
|
attacking_item.play_tool_sound(get_turf(src), 50)
|
|
broken_state++
|
|
if(GRAV_NEEDS_WELDING)
|
|
if(attacking_item.iswelder())
|
|
var/obj/item/weldingtool/WT = attacking_item
|
|
if(WT.use(1, user))
|
|
to_chat(user, SPAN_NOTICE("You mend the damaged framework."))
|
|
playsound(src.loc, 'sound/items/welder_pry.ogg', 50, 1)
|
|
broken_state++
|
|
if(GRAV_NEEDS_PLASTEEL)
|
|
if(istype(attacking_item, /obj/item/stack/material/plasteel))
|
|
var/obj/item/stack/material/plasteel/PS = attacking_item
|
|
if(PS.amount >= 10)
|
|
PS.use(10)
|
|
to_chat(user, SPAN_NOTICE("You add the plating to the framework."))
|
|
playsound(src.loc, 'sound/machines/click.ogg', 75, 1)
|
|
broken_state++
|
|
else
|
|
to_chat(user, SPAN_NOTICE("You need 10 sheets of plasteel."))
|
|
if(GRAV_NEEDS_WRENCH)
|
|
if(attacking_item.iswrench())
|
|
to_chat(user, SPAN_NOTICE("You secure the plating to the framework."))
|
|
attacking_item.play_tool_sound(get_turf(src), 75)
|
|
set_fix()
|
|
else
|
|
..()
|
|
if(attacking_item.iscrowbar())
|
|
if(backpanelopen)
|
|
attacking_item.play_tool_sound(get_turf(src), 50)
|
|
to_chat(user, SPAN_NOTICE("You replace the back panel."))
|
|
backpanelopen = 0
|
|
else
|
|
attacking_item.play_tool_sound(get_turf(src), 50)
|
|
to_chat(user, SPAN_NOTICE("You open the back panel."))
|
|
backpanelopen = 1
|
|
|
|
if(old_broken_state != broken_state)
|
|
update_icon()
|
|
|
|
/obj/machinery/gravity_generator/main/attack_hand(mob/user as mob)
|
|
if(!..())
|
|
return interact(user)
|
|
|
|
/obj/machinery/gravity_generator/main/interact(mob/user as mob)
|
|
if(stat & BROKEN)
|
|
return
|
|
var/dat = "Gravity Generator Breaker: "
|
|
if(!eventon)
|
|
if(breaker)
|
|
dat += "<span class='linkOn'>ON</span> <A href='byond://?src=[REF(src)];gentoggle=1'>OFF</A>"
|
|
else
|
|
dat += "<A href='byond://?src=[REF(src)];gentoggle=1'>ON</A> <span class='linkOn'>OFF</span> "
|
|
if(backpanelopen)
|
|
dat += "<br>Emergency shutoff:<br>"
|
|
dat += "<A href='byond://?src=[REF(src)];eshutoff=1'>Red Button</A>"
|
|
|
|
dat += "<br>Generator Status:<br><div class='statusDisplay'>"
|
|
if(charging_state != POWER_IDLE)
|
|
dat += "<font class='bad'>WARNING</font> Radiation Detected. <br>[charging_state == POWER_UP ? "Charging..." : "Discharging..."]"
|
|
else if(on)
|
|
dat += "Powered."
|
|
else
|
|
dat += "Unpowered."
|
|
|
|
dat += "<br>Gravity Charge: [charge_count]%</div>"
|
|
else
|
|
dat += "<h3><font class='bad'>ERROR: SYSTEM MALFUNCTION. PLEASE WAIT...</font></h3>"
|
|
var/datum/browser/popup = new(user, "gravgen", name)
|
|
popup.set_content(dat)
|
|
popup.open()
|
|
|
|
|
|
/obj/machinery/gravity_generator/main/Topic(href, href_list)
|
|
|
|
if(..())
|
|
return
|
|
|
|
if(href_list["gentoggle"])
|
|
breaker = !breaker
|
|
investigate_log("was toggled [breaker ? "<font color='green'>ON</font>" : SPAN_WARNING("OFF")] by [usr.key].", "gravity")
|
|
set_power()
|
|
src.updateUsrDialog()
|
|
else if(href_list["eshutoff"])
|
|
investigate_log("was shut off by [usr.key].", "gravity")
|
|
eshutoff()
|
|
|
|
|
|
/obj/machinery/gravity_generator/main/power_change()
|
|
..()
|
|
breaker = (stat & NOPOWER) ? FALSE : TRUE
|
|
set_power()
|
|
investigate_log("has [stat & NOPOWER ? "lost" : "regained"] power.", "gravity")
|
|
|
|
/obj/machinery/gravity_generator/main/proc/eshutoff()
|
|
if(charge_count > 0)
|
|
charge_count = 0
|
|
playsound(src.loc, 'sound/effects/EMPulse.ogg', 100, 1)
|
|
pulse_radiation(100)
|
|
set_state(0)
|
|
if(middle)
|
|
middle.ClearOverlays()
|
|
if(prob(1)) //It will spawn a small one and eat the generator. Won't cause any other issues considering it's a 1x1 and will go away on it's own.
|
|
new /obj/singularity(src.loc)
|
|
if(prob(33)) //Releasing all that power at once is dangerous.
|
|
empulse(src.loc, 2, 4)
|
|
set_light(10,1,LIGHT_COLOR_FLARE)
|
|
sleep(5)
|
|
set_light(5,0.5,LIGHT_COLOR_FIRE)
|
|
sleep(5)
|
|
set_light(0,0,"#000000")
|
|
|
|
/obj/machinery/gravity_generator/main/get_status()
|
|
if(stat & BROKEN)
|
|
return "fix[min(broken_state, 3)]"
|
|
return on || charging_state != POWER_IDLE ? "on" : "off"
|
|
|
|
/obj/machinery/gravity_generator/main/update_icon()
|
|
..()
|
|
for(var/obj/O in parts)
|
|
O.update_icon()
|
|
|
|
// Set the charging state based on power/breaker.
|
|
/obj/machinery/gravity_generator/main/proc/set_power()
|
|
var/new_state = 0
|
|
if(stat & (NOPOWER|BROKEN) || !breaker)
|
|
new_state = 0
|
|
else if(breaker)
|
|
new_state = 1
|
|
|
|
charging_state = new_state ? POWER_UP : POWER_DOWN // Startup sequence animation.
|
|
investigate_log("is now [charging_state == POWER_UP ? "charging" : "discharging"].", "gravity")
|
|
update_icon()
|
|
|
|
// Set the state of the gravity.
|
|
/obj/machinery/gravity_generator/main/proc/set_state(var/new_state)
|
|
charging_state = POWER_IDLE
|
|
var/gravity_changed = (on != new_state)
|
|
on = new_state
|
|
update_use_power(on ? POWER_USE_ACTIVE : POWER_USE_IDLE)
|
|
// Sound the alert if gravity was just enabled or disabled.
|
|
var/alert = 0
|
|
var/area/area = get_area(src)
|
|
if(new_state) // If we turned on
|
|
if(!area.has_gravity())
|
|
alert = 1
|
|
GLOB.gravity_is_on = 1
|
|
soundloop.start(src)
|
|
investigate_log("was brought online and is now producing gravity for this level.", "gravity")
|
|
message_admins("The gravity generator was brought online. (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>[area.name]</a>)")
|
|
else
|
|
if(area.has_gravity())
|
|
alert = 1
|
|
GLOB.gravity_is_on = 0
|
|
soundloop.stop(src)
|
|
investigate_log("was brought offline and there is now no gravity for this level.", "gravity")
|
|
message_admins("The gravity generator was brought offline with no backup generator. (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>[area.name]</a>)")
|
|
|
|
update_icon()
|
|
update_list(gravity_changed)
|
|
src.updateUsrDialog()
|
|
if(alert)
|
|
shake_everyone()
|
|
|
|
// Charge/Discharge and turn on/off gravity when you reach 0/100 percent.
|
|
// Also emit radiation and handle the overlays.
|
|
/obj/machinery/gravity_generator/main/process()
|
|
if(stat & BROKEN)
|
|
return
|
|
if(charging_state != POWER_IDLE)
|
|
if(charging_state == POWER_UP && charge_count >= 100)
|
|
set_state(1)
|
|
else if(charging_state == POWER_DOWN && charge_count <= 0)
|
|
set_state(0)
|
|
else
|
|
if(charging_state == POWER_UP)
|
|
charge_count += 2
|
|
else if(charging_state == POWER_DOWN)
|
|
charge_count -= 2
|
|
|
|
if(charge_count % 4 == 0 && prob(75)) // Let them know it is charging/discharging.
|
|
playsound(src.loc, 'sound/effects/EMPulse.ogg', 100, 1)
|
|
|
|
updateDialog()
|
|
if(prob(30)) // To help stop "Your clothes feel warm" spam.
|
|
pulse_radiation()
|
|
|
|
var/overlay_state = null
|
|
switch(charge_count)
|
|
if(0 to 20)
|
|
overlay_state = null
|
|
set_light(0,0,"#000000")
|
|
if(21 to 40)
|
|
overlay_state = "startup"
|
|
set_light(4,0.2,LIGHT_COLOR_BLUE)
|
|
if(41 to 60)
|
|
overlay_state = "idle"
|
|
set_light(6,0.5,"#7D9BFF") //More of a washed out perywinkle than blue but shut up.
|
|
if(61 to 80)
|
|
overlay_state = "activating"
|
|
set_light(6,0.8,"#7DC3FF")
|
|
if(81 to 100)
|
|
overlay_state = "activated"
|
|
set_light(8,1,LIGHT_COLOR_CYAN)
|
|
|
|
if(overlay_state != current_overlay)
|
|
if(middle)
|
|
middle.ClearOverlays()
|
|
if(overlay_state)
|
|
middle.AddOverlays(overlay_state)
|
|
current_overlay = overlay_state
|
|
|
|
/obj/machinery/gravity_generator/main/proc/pulse_radiation(var/amount = 20)
|
|
for(var/mob/living/L in view(7, src))
|
|
L.apply_damage(amount, DAMAGE_RADIATION, damage_flags = DAMAGE_FLAG_DISPERSED)
|
|
|
|
// Shake everyone on the z level to let them know that gravity was enagaged/disenagaged.
|
|
/obj/machinery/gravity_generator/main/proc/shake_everyone()
|
|
var/turf/our_turf = get_turf(src)
|
|
for(var/mob/M in GLOB.mob_list)
|
|
var/turf/their_turf = get_turf(M)
|
|
if(their_turf && (their_turf.z == our_turf.z))
|
|
M.update_gravity(M.mob_has_gravity())
|
|
if(M.client)
|
|
if(!M) return
|
|
shake_camera(M, 5, 1)
|
|
M.playsound_local(our_turf, 'sound/effects/alert.ogg', 100, vary = TRUE, falloff_distance = 0.5)
|
|
|
|
/obj/machinery/gravity_generator/main/proc/update_list(var/gravity_changed = FALSE)
|
|
var/turf/T = get_turf(src.loc)
|
|
if(T)
|
|
if(!SSmachinery.gravity_generators)
|
|
SSmachinery.gravity_generators = list()
|
|
|
|
if(on && gravity_changed)
|
|
for(var/area/A in localareas)
|
|
A.gravitychange(TRUE)
|
|
SSmachinery.gravity_generators += src
|
|
else if (!on)
|
|
for(var/area/A in localareas)
|
|
A.gravitychange(FALSE)
|
|
SSmachinery.gravity_generators -= src
|
|
|
|
/obj/machinery/gravity_generator/main/Initialize()
|
|
. = ..()
|
|
soundloop = new(src, start_immediately = FALSE)
|
|
addtimer(CALLBACK(src, PROC_REF(updateareas)), 10)
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/obj/machinery/gravity_generator/main/LateInitialize()
|
|
if(SSatlas.current_map.use_overmap && !linked)
|
|
var/my_sector = GLOB.map_sectors["[z]"]
|
|
if (istype(my_sector, /obj/effect/overmap/visitable))
|
|
attempt_hook_up(my_sector)
|
|
if(linked)
|
|
linked.gravity_generator = src
|
|
|
|
/obj/machinery/gravity_generator/main/proc/updateareas()
|
|
for(var/area/A in get_sorted_areas())
|
|
if(!(get_area_type(A) == AREA_STATION))
|
|
continue
|
|
localareas += A
|
|
|
|
/obj/machinery/gravity_generator/main/proc/get_area_type(var/area/A = get_area(src))
|
|
if (A.name == "Space")
|
|
return AREA_SPACE
|
|
else if(A.alwaysgravity == 1 || A.nevergravity == 1)
|
|
return AREA_SPECIAL
|
|
else
|
|
return AREA_STATION
|
|
|
|
/obj/machinery/gravity_generator/main/proc/throw_up_and_down(var/area/Area)
|
|
if(!Area)
|
|
return
|
|
to_world("<h2 class='alert'>Station Announcement:</h2>")
|
|
to_world(SPAN_DANGER("Warning! Localized Gravity Failure in \the [Area]. Brace for dangerous gravity change!"))
|
|
sleep(50)
|
|
set_state(FALSE)
|
|
sleep(30)
|
|
set_state(TRUE)
|
|
for(var/mob/living/M in GLOB.mob_list)
|
|
var/turf/their_turf = get_turf(M)
|
|
if(their_turf?.loc == Area)
|
|
if(ishuman(M))
|
|
var/mob/living/carbon/human/H = M
|
|
var/obj/item/clothing/shoes/magboots/boots = H.get_equipped_item(slot_shoes)
|
|
if(istype(boots))
|
|
continue
|
|
to_chat(M, SPAN_DANGER("Suddenly the gravity pushed you up to the ceiling and dropped you back on the floor with great force!"))
|
|
M.fall_impact(1)
|
|
|
|
|
|
#undef POWER_IDLE
|
|
#undef POWER_UP
|
|
#undef POWER_DOWN
|
|
|
|
#undef GRAV_NEEDS_SCREWDRIVER
|
|
#undef GRAV_NEEDS_WELDING
|
|
#undef GRAV_NEEDS_PLASTEEL
|
|
#undef GRAV_NEEDS_WRENCH
|
|
|
|
#undef AREA_ERRNONE
|
|
#undef AREA_STATION
|
|
#undef AREA_SPACE
|
|
#undef AREA_SPECIAL
|