Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bluespace cannon update #11286

Merged
merged 15 commits into from
Aug 16, 2024
4 changes: 2 additions & 2 deletions code/modules/power/power.dm
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@
update_appearance()

// connect the machine to a powernet if a node cable is present on the turf
/obj/machinery/power/proc/connect_to_network()
var/turf/T = src.loc
/obj/machinery/power/proc/connect_to_network(var/turf/turf = loc)
var/turf/T = turf
if(!T || !istype(T))
return FALSE

Expand Down
4 changes: 4 additions & 0 deletions code/modules/power/terminal.dm
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,7 @@
/obj/machinery/power/terminal/wirecutter_act(mob/living/user, obj/item/I)
dismantle(user, I)
return TRUE

/obj/machinery/power/terminal/invisible
name = ""
icon_state = ""
152 changes: 117 additions & 35 deletions code/modules/station_goals/bsa.dm
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ GLOBAL_VAR_INIT(bsa_unlock, FALSE)
/datum/station_goal/bluespace_cannon/check_completion()
if(..())
return TRUE
var/obj/machinery/bsa/full/B = locate()
var/obj/machinery/power/bsa/full/B = locate()
if(B && !B.machine_stat)
return TRUE
return FALSE
Expand Down Expand Up @@ -129,68 +129,138 @@ DEFINE_BUFFER_HANDLER(/obj/machinery/bsa/middle)
return WEST


/obj/machinery/bsa/full
/obj/machinery/power/bsa/full
name = "Bluespace Artillery"
desc = "Long range bluespace artillery."
icon = 'icons/obj/lavaland/cannon.dmi'
icon_state = "cannon_west"
var/base_battery_icon_state = "bsa_west_capacitor"
var/static/mutable_appearance/top_layer
var/ex_power = 3
var/power_used_per_shot = 2000000 //enough to kil standard apc - todo : make this use wires instead and scale explosion power with it
var/ready

var/power_used_per_shot = 5000000
var/obj/item/stock_parts/cell/cell
var/obj/machinery/power/terminal/invisible/terminal
use_power = NO_POWER_USE
idle_power_usage = 50 // when idle

pixel_y = -32
pixel_x = -192
bound_width = 352
bound_x = -192
density = TRUE
appearance_flags = NONE //Removes default TILE_BOUND
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF

/obj/machinery/bsa/full/wrench_act(mob/living/user, obj/item/I)
var/sound/select_sound = 'sound/machines/bsa/bsa_charge.ogg'
var/select_sound_length = 17 SECONDS

var/sound/fire_sound = 'sound/machines/bsa/bsa_fire.ogg'
var/winding_up = FALSE // if true, sparks will be generated in the bullseye

var/last_charge_quarter = 0


/obj/machinery/power/bsa/full/wrench_act(mob/living/user, obj/item/I)
return FALSE

/obj/machinery/bsa/full/proc/get_front_turf()
/obj/machinery/power/bsa/full/Destroy()
. = ..()
QDEL_NULL(cell)
QDEL_NULL(terminal)

/obj/machinery/power/bsa/full/proc/get_front_turf()
switch(dir)
if(WEST)
return locate(x - 7,y,z)
if(EAST)
return locate(x + 4,y,z)
return get_turf(src)

/obj/machinery/bsa/full/proc/get_back_turf()
/obj/machinery/power/bsa/full/proc/get_back_turf()
switch(dir)
if(WEST)
return locate(x + 4,y,z)
if(EAST)
return locate(x - 6,y,z)
return get_turf(src)

/obj/machinery/bsa/full/proc/get_target_turf()
/obj/machinery/power/bsa/full/proc/get_target_turf()
switch(dir)
if(WEST)
return locate(1,y,z)
if(EAST)
return locate(world.maxx,y,z)
return get_turf(src)

/obj/machinery/bsa/full/Initialize(mapload, cannon_direction = WEST)
/obj/machinery/power/bsa/full/proc/make_terminal(turf/T)
// create a terminal object at the same position as original turf loc
// wires will attach to this
terminal = new /obj/machinery/power/terminal/invisible(T)
terminal.master = src

/obj/machinery/power/bsa/full/Initialize(mapload, cannon_direction = WEST)
. = ..()
cell = new /obj/item/stock_parts/cell(src, 5000000)
cell.charge = 0
top_layer = top_layer || mutable_appearance(icon, layer = ABOVE_MOB_LAYER)
switch(cannon_direction)
if(WEST)
setDir(WEST)
pixel_x = -192
top_layer.icon_state = "top_west"
icon_state = "cannon_west"
if(EAST)
setDir(EAST)
top_layer.icon_state = "top_east"
icon_state = "cannon_east"
add_overlay(top_layer)
reload()
update_icon_state()
make_terminal(get_back_turf())

/obj/machinery/bsa/full/proc/fire(mob/user, turf/bullseye)
reload()

/obj/machinery/power/bsa/full/update_icon_state()
. = ..()
icon_state = "cannon_[dir2text(dir)]"
base_battery_icon_state = "bsa_[dir2text(dir)]_capacitor"

/obj/machinery/power/bsa/full/update_overlays()
. = ..()
cut_overlays()
add_overlay(top_layer)
top_layer.icon_state = "top_[dir2text(dir)]"

var/charge_quarter = FLOOR(cell.percent() / 25, 1)
var/charge_sound = 'sound/machines/apc/PowerSwitch_Off.ogg'
if(charge_quarter >= 1)
add_overlay("[base_battery_icon_state]_25")
if(charge_quarter >= 2)
add_overlay("[base_battery_icon_state]_50")
if(charge_quarter >= 3)
add_overlay("[base_battery_icon_state]_75")
if(charge_quarter >= 4)
add_overlay("[base_battery_icon_state]_100")
charge_sound = 'sound/machines/apc/PowerUp_001.ogg'
if(charge_quarter > last_charge_quarter)
playsound(get_turf(src), charge_sound, 25, 1)


/obj/machinery/power/bsa/full/proc/charge_up(mob/user, turf/bullseye)
if(!cell.use(power_used_per_shot))
return FALSE
var/sound/charge_up = sound(select_sound)
playsound(get_turf(src), charge_up, 50, 1)
var/timerid = addtimer(CALLBACK(src, PROC_REF(fire), user, bullseye), select_sound_length, TIMER_STOPPABLE)
winding_up = TRUE
var/list/turfs = spiral_range_turfs(ex_power * 2, bullseye)
var/base_cooldown = 2 SECONDS
var/cooldown = base_cooldown
while(winding_up)
if(QDELETED(src))
break
new /obj/effect/particle_effect/sparks(pick(turfs))
cooldown = base_cooldown * ((timeleft(timerid)) / select_sound_length)
sleep(cooldown)

/obj/machinery/power/bsa/full/proc/fire(mob/user, turf/bullseye)
winding_up = FALSE
playsound(get_turf(src), fire_sound, 50, 1, world.maxx)
var/turf/point = get_front_turf()
var/turf/target = get_target_turf()
var/atom/movable/blocker
Expand Down Expand Up @@ -222,16 +292,26 @@ DEFINE_BUFFER_HANDLER(/obj/machinery/bsa/middle)
log_game("[key_name(user)] has launched an artillery strike targeting [AREACOORD(bullseye)] but it was blocked by [blocker] at [AREACOORD(target)].")


/obj/machinery/bsa/full/proc/reload()
/obj/machinery/power/bsa/full/proc/reload()
ready = FALSE
use_power(power_used_per_shot)
ui_update()
addtimer(CALLBACK(src,"ready_cannon"),600)

/obj/machinery/bsa/full/proc/ready_cannon()
/obj/machinery/power/bsa/full/proc/ready_cannon()
ready = TRUE
ui_update()

/obj/machinery/power/bsa/full/process(delta_time)
if(cell.percent() >= 100 || terminal.surplus() < 1)
return
terminal.add_load(idle_power_usage)
var/charge = terminal.surplus() * delta_time
terminal.add_load(charge)
cell.give(charge)
update_appearance(UPDATE_OVERLAYS)
last_charge_quarter = FLOOR(cell.percent() / 25, 1)
ui_update()

/obj/structure/filler
name = "big machinery part"
density = TRUE
Expand All @@ -254,7 +334,6 @@ DEFINE_BUFFER_HANDLER(/obj/machinery/bsa/middle)
canSmoothWith = null



var/datum/weakref/cannon_ref
var/notice
var/target
Expand All @@ -272,12 +351,14 @@ DEFINE_BUFFER_HANDLER(/obj/machinery/bsa/middle)
//Missing updates for: target GPS name changes

/obj/machinery/computer/bsa_control/ui_data()
var/obj/machinery/bsa/full/cannon = cannon_ref?.resolve()
var/obj/machinery/power/bsa/full/cannon = cannon_ref?.resolve()
var/list/data = list()
data["ready"] = cannon ? cannon.ready : FALSE
data["connected"] = cannon
data["notice"] = notice
data["unlocked"] = GLOB.bsa_unlock
data["charge"] = cannon ? cannon.cell.charge : 0
data["max_charge"] = cannon ? cannon.cell.maxcharge : 0
if(target)
data["target"] = get_target_name()
else
Expand All @@ -303,20 +384,20 @@ DEFINE_BUFFER_HANDLER(/obj/machinery/bsa/middle)
/obj/machinery/computer/bsa_control/proc/calibrate(mob/user)
if(!GLOB.bsa_unlock)
return
var/list/gps_locators = list()
for(var/datum/component/gps/G in GLOB.GPS_list) //nulls on the list somehow
var/list/targets = list()
// Find all active GPS
for(var/datum/component/gps/G in GLOB.GPS_list)
if(G.tracking)
gps_locators[G.gpstag] = G
targets[G.gpstag] = G

var/list/options = gps_locators
if(area_aim)
options += GLOB.teleportlocs
var/victim = tgui_input_list(user, "Select target", "Artillery Targeting", options)
targets += GLOB.teleportlocs
var/victim = tgui_input_list(user, "Select target", "Artillery Targeting", targets)
if(isnull(victim))
return
if(isnull(options[victim]))
if(isnull(targets[victim]))
return
target = options[victim]
target = targets[victim]
var/datum/component/gps/log_target = target
log_game("[key_name(user)] has aimed the bluespace artillery strike (BSA) at [get_area_name(log_target.parent)].")

Expand All @@ -335,19 +416,20 @@ DEFINE_BUFFER_HANDLER(/obj/machinery/bsa/middle)
var/datum/component/gps/G = target
return get_turf(G.parent)


/obj/machinery/computer/bsa_control/proc/fire(mob/user)
var/obj/machinery/bsa/full/cannon = cannon_ref?.resolve()
var/obj/machinery/power/bsa/full/cannon = cannon_ref?.resolve()
if(!cannon)
notice = "No Cannon Exists!"
return
if(cannon.machine_stat)
notice = "Cannon unpowered!"
if(cannon.cell.percent() < 100)
notice = "Cannon doesn't have enough charge!"
return
notice = null
cannon.fire(user, get_impact_turf())
cannon.charge_up(user, get_impact_turf())

/obj/machinery/computer/bsa_control/proc/deploy(force=FALSE)
var/obj/machinery/bsa/full/prebuilt = locate() in range(7) //In case of adminspawn
var/obj/machinery/power/bsa/full/prebuilt = locate() in range(7) //In case of adminspawn
if(prebuilt)
return prebuilt

Expand All @@ -362,7 +444,7 @@ DEFINE_BUFFER_HANDLER(/obj/machinery/bsa/middle)
var/datum/effect_system/smoke_spread/s = new
s.set_up(4,get_turf(centerpiece))
s.start()
var/obj/machinery/bsa/full/cannon = new(get_turf(centerpiece),centerpiece.get_cannon_direction())
var/obj/machinery/power/bsa/full/cannon = new(get_turf(centerpiece),centerpiece.get_cannon_direction())
QDEL_NULL(centerpiece.front_ref)
QDEL_NULL(centerpiece.back_ref)
qdel(centerpiece)
Expand Down
Binary file modified icons/obj/lavaland/cannon.dmi
Binary file not shown.
Binary file added sound/machines/bsa/bsa_charge.ogg
Binary file not shown.
Binary file added sound/machines/bsa/bsa_fire.ogg
Binary file not shown.
16 changes: 13 additions & 3 deletions tgui/packages/tgui/interfaces/BluespaceArtillery.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
import { useBackend } from '../backend';
import { Box, Button, LabeledList, NoticeBox, Section } from '../components';
import { Box, Button, LabeledList, NoticeBox, ProgressBar, Section } from '../components';
import { Window } from '../layouts';

export const BluespaceArtillery = (props, context) => {
const { act, data } = useBackend(context);
const { notice, connected, unlocked, target } = data;
const { notice, connected, unlocked, target, charge, max_charge } = data;
return (
<Window width={400} height={220}>
<Window width={400} height={280}>
<Window.Content>
{!!notice && <NoticeBox>{notice}</NoticeBox>}
{connected ? (
<>
<Section title="Charge">
<ProgressBar
ranges={{
good: [1, Infinity],
average: [0.2, 0.99],
bad: [-Infinity, 0.2],
}}
value={charge / max_charge}
/>
</Section>
<Section
title="Target"
buttons={<Button icon="crosshairs" disabled={!unlocked} onClick={() => act('recalibrate')} />}>
Expand Down
Loading