Skip to content

Commit

Permalink
Light replacer speeds up colony light repair (#5905)
Browse files Browse the repository at this point in the history
# About the pull request

This PR addresses several things:
- Colony lights and their switch were capitalized so they were treated
as proper nouns when examined
- Colony lights don't actually use power, only their switch, so their
power status text was incorrect
- The light replacer can now be used to speed up the repair of colony
lights by skipping 3 steps in the normal process
- APC and SMES interfaces now properly close/disable when you are not
adjacent to them or incapacitated
- General refactoring of the colony_floodlights file to bring it closer
to code standards

The APC and SMES UI fixes were just because I was very confused why they
weren't behaving during testing, so I fixed them.

# Explain why it's good for the game
I want to push power as a meaningful objective marines want to try to
secure if possible. Currently colony lights are too tedious to repair
and the light replacer is underused so I hope this can help rectify both
problems somewhat.

# Testing Photographs and Procedure
<details>
<summary>Screenshots & Videos</summary>

https://youtu.be/qJf1V-RdMok

</details>

# Changelog
:cl: Drathek
balance: The light replacer can now be used to skip the crowbar,
welding, and wire steps when repairing colony lights.
fix: Fixes SMES and APC interfaces not checking adjacency or
incapacitated states
spellcheck: Fixed examine text for colony lights (improper names and not
powered text)
/:cl:

---------

Co-authored-by: SabreML <[email protected]>
  • Loading branch information
Drulikar and SabreML authored Mar 14, 2024
1 parent 3c8c4f2 commit 6b835c0
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 67 deletions.
152 changes: 91 additions & 61 deletions code/game/machinery/colony_floodlights.dm
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
//Putting these here since it's power-related
/obj/structure/machinery/colony_floodlight_switch
name = "Colony Floodlight Switch"
name = "colony floodlight switch"
icon = 'icons/obj/structures/machinery/power.dmi'
icon_state = "panelnopower"
desc = "This switch controls the floodlights surrounding the archaeology complex. It only functions when there is power."
density = FALSE
anchored = TRUE
var/ispowered = FALSE
var/turned_on = 0 //has to be toggled in engineering
use_power = USE_POWER_IDLE
unslashable = TRUE
unacidable = TRUE
var/list/floodlist = list() // This will save our list of floodlights on the map
power_machine = TRUE
var/ispowered = FALSE
var/turned_on = FALSE //has to be toggled in engineering
///All floodlights under our control
var/list/floodlist = list()

/obj/structure/machinery/colony_floodlight_switch/Initialize(mapload, ...)
. = ..()
return INITIALIZE_HINT_LATELOAD

/obj/structure/machinery/colony_floodlight_switch/LateInitialize()
. = ..()
for(var/obj/structure/machinery/colony_floodlight/F in GLOB.machines)
floodlist += F
F.fswitch = src
for(var/obj/structure/machinery/colony_floodlight/floodlight in GLOB.machines)
floodlist += floodlight
floodlight.fswitch = src
start_processing()

/obj/structure/machinery/colony_floodlight_switch/Destroy()
Expand All @@ -31,7 +32,6 @@
floodlist = null
return ..()


/obj/structure/machinery/colony_floodlight_switch/update_icon()
if(!ispowered)
icon_state = "panelnopower"
Expand All @@ -42,10 +42,10 @@

/obj/structure/machinery/colony_floodlight_switch/process()
var/lightpower = 0
for(var/obj/structure/machinery/colony_floodlight/C in floodlist)
if(!C.is_lit)
for(var/obj/structure/machinery/colony_floodlight/floodlight as anything in floodlist)
if(!floodlight.is_lit)
continue
lightpower += C.power_tick
lightpower += floodlight.power_tick
use_power(lightpower)

/obj/structure/machinery/colony_floodlight_switch/power_change()
Expand All @@ -54,37 +54,29 @@
if(ispowered && turned_on)
toggle_lights()
ispowered = FALSE
turned_on = 0
turned_on = FALSE
update_icon()
else
ispowered = TRUE
update_icon()

/obj/structure/machinery/colony_floodlight_switch/proc/toggle_lights()
for(var/obj/structure/machinery/colony_floodlight/F in floodlist)
spawn(rand(0,50))
F.is_lit = !F.is_lit
if(!F.damaged)
if(F.is_lit) //Shut it down
F.set_light(F.lum_value)
else
F.set_light(0)
F.update_icon()
return 0
for(var/obj/structure/machinery/colony_floodlight/floodlight as anything in floodlist)
addtimer(CALLBACK(floodlight, TYPE_PROC_REF(/obj/structure/machinery/colony_floodlight, toggle_light)), rand(0, 5 SECONDS))

/obj/structure/machinery/colony_floodlight_switch/attack_hand(mob/user as mob)
if(!ishuman(user))
to_chat(user, "Nice try.")
return 0
return FALSE
if(!ispowered)
to_chat(user, "Nothing happens.")
return 0
return FALSE
playsound(src,'sound/items/Deconstruct.ogg', 30, 1)
use_power(5)
toggle_lights()
turned_on = !(src.turned_on)
turned_on = !turned_on
update_icon()
return 1
return TRUE


#define FLOODLIGHT_REPAIR_UNSCREW 0
Expand All @@ -94,21 +86,26 @@
#define FLOODLIGHT_REPAIR_SCREW 4

/obj/structure/machinery/colony_floodlight
name = "Colony Floodlight"
name = "colony floodlight"
icon = 'icons/obj/structures/machinery/big_floodlight.dmi'
icon_state = "flood_s_off"
density = TRUE
anchored = TRUE
layer = ABOVE_XENO_LAYER
var/damaged = 0 //Can be smashed by xenos
var/is_lit = 0 //whether the floodlight is switched to on or off. Does not necessarily mean it emits light.
unslashable = TRUE
unacidable = TRUE
var/power_tick = 50 // power each floodlight takes up per process
use_power = USE_POWER_NONE //It's the switch that uses the actual power, not the lights
var/obj/structure/machinery/colony_floodlight_switch/fswitch = null //Reverse lookup for power grabbing in area
needs_power = FALSE
///Whether it has been smashed by xenos
var/damaged = FALSE
///Whether the floodlight is switched to on or off. Does not necessarily mean it emits light.
var/is_lit = FALSE
///The power each floodlight takes up per process
var/power_tick = 50
///Reverse lookup for power grabbing in area
var/obj/structure/machinery/colony_floodlight_switch/fswitch = null
var/lum_value = 7
var/repair_state = 0
var/repair_state = FLOODLIGHT_REPAIR_UNSCREW
health = 150

/obj/structure/machinery/colony_floodlight/Destroy()
Expand All @@ -130,13 +127,13 @@
if(HAS_TRAIT(I, TRAIT_TOOL_SCREWDRIVER))
if(!skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_ENGI))
to_chat(user, SPAN_WARNING("You have no clue how to repair [src]."))
return 0
return FALSE

if(repair_state == FLOODLIGHT_REPAIR_UNSCREW)
playsound(loc, 'sound/items/Screwdriver.ogg', 25, 1)
user.visible_message(SPAN_NOTICE("[user] starts unscrewing [src]'s maintenance hatch."), \
SPAN_NOTICE("You start unscrewing [src]'s maintenance hatch."))
if(do_after(user, 20, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD))
if(do_after(user, 2 SECONDS, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD))
if(QDELETED(src) || repair_state != FLOODLIGHT_REPAIR_UNSCREW)
return
playsound(loc, 'sound/items/Screwdriver.ogg', 25, 1)
Expand All @@ -148,11 +145,11 @@
playsound(loc, 'sound/items/Screwdriver.ogg', 25, 1)
user.visible_message(SPAN_NOTICE("[user] starts screwing [src]'s maintenance hatch closed."), \
SPAN_NOTICE("You start screwing [src]'s maintenance hatch closed."))
if(do_after(user, 20, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD))
if(do_after(user, 2 SECONDS, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD))
if(QDELETED(src) || repair_state != FLOODLIGHT_REPAIR_SCREW)
return
playsound(loc, 'sound/items/Screwdriver.ogg', 25, 1)
damaged = 0
damaged = FALSE
repair_state = FLOODLIGHT_REPAIR_UNSCREW
health = initial(health)
user.visible_message(SPAN_NOTICE("[user] screws [src]'s maintenance hatch closed."), \
Expand All @@ -165,83 +162,109 @@
else if(HAS_TRAIT(I, TRAIT_TOOL_CROWBAR))
if(!skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_ENGI))
to_chat(user, SPAN_WARNING("You have no clue how to repair [src]."))
return 0
return FALSE

if(repair_state == FLOODLIGHT_REPAIR_CROWBAR)
playsound(src.loc, 'sound/items/Crowbar.ogg', 25, 1)
user.visible_message(SPAN_NOTICE("[user] starts prying [src]'s maintenance hatch open."),\
SPAN_NOTICE("You start prying [src]'s maintenance hatch open."))
if(do_after(user, 20, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD))
playsound(loc, 'sound/items/Crowbar.ogg', 25, 1)
user.visible_message(SPAN_NOTICE("[user] starts prying [src]'s damaged lighting assembly out."),\
SPAN_NOTICE("You start prying [src]'s damaged lighting assembly out."))
if(do_after(user, 2 SECONDS, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD))
if(QDELETED(src) || repair_state != FLOODLIGHT_REPAIR_CROWBAR)
return
playsound(src.loc, 'sound/items/Crowbar.ogg', 25, 1)
playsound(loc, 'sound/items/Crowbar.ogg', 25, 1)
repair_state = FLOODLIGHT_REPAIR_WELD
user.visible_message(SPAN_NOTICE("[user] pries [src]'s maintenance hatch open."),\
SPAN_NOTICE("You pry [src]'s maintenance hatch open."))
user.visible_message(SPAN_NOTICE("[user] pries [src]'s damaged lighting assembly out."),\
SPAN_NOTICE("You pry [src]'s damaged lighting assembly out."))
return TRUE

else if(iswelder(I))
if(!HAS_TRAIT(I, TRAIT_TOOL_BLOWTORCH))
to_chat(user, SPAN_WARNING("You need a stronger blowtorch!"))
return
var/obj/item/tool/weldingtool/WT = I
var/obj/item/tool/weldingtool/welder = I

if(!skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_ENGI))
to_chat(user, SPAN_WARNING("You have no clue how to repair [src]."))
return 0
return FALSE

if(repair_state == FLOODLIGHT_REPAIR_WELD)
if(WT.remove_fuel(1, user))
if(welder.remove_fuel(1, user))
playsound(loc, 'sound/items/weldingtool_weld.ogg', 25)
user.visible_message(SPAN_NOTICE("[user] starts welding [src]'s damage."),
SPAN_NOTICE("You start welding [src]'s damage."))
if(do_after(user, 40, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD))
if(QDELETED(src) || !WT.isOn() || repair_state != FLOODLIGHT_REPAIR_WELD)
if(do_after(user, 4 SECONDS, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_BUILD))
if(QDELETED(src) || !welder.isOn() || repair_state != FLOODLIGHT_REPAIR_WELD)
return
playsound(loc, 'sound/items/Welder2.ogg', 25, 1)
repair_state = FLOODLIGHT_REPAIR_CABLE
user.visible_message(SPAN_NOTICE("[user] welds [src]'s damage."),
SPAN_NOTICE("You weld [src]'s damage."))
return 1
return TRUE
else
to_chat(user, SPAN_WARNING("You need more welding fuel to complete this task."))
return TRUE

else if(iscoil(I))
var/obj/item/stack/cable_coil/C = I
var/obj/item/stack/cable_coil/coil = I
if(!skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_ENGI))
to_chat(user, SPAN_WARNING("You have no clue how to repair [src]."))
return 0
return FALSE

if(repair_state == FLOODLIGHT_REPAIR_CABLE)
if(C.get_amount() < 2)
if(coil.get_amount() < 2)
to_chat(user, SPAN_WARNING("You need two coils of wire to replace the damaged cables."))
return
playsound(loc, 'sound/items/Deconstruct.ogg', 25, 1)
user.visible_message(SPAN_NOTICE("[user] starts replacing [src]'s damaged cables."),\
SPAN_NOTICE("You start replacing [src]'s damaged cables."))
if(do_after(user, 20, INTERRUPT_ALL, BUSY_ICON_GENERIC))
if(do_after(user, 2 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC))
if(QDELETED(src) || repair_state != FLOODLIGHT_REPAIR_CABLE)
return
if(C.use(2))
if(coil.use(2))
playsound(loc, 'sound/items/Deconstruct.ogg', 25, 1)
repair_state = FLOODLIGHT_REPAIR_SCREW
user.visible_message(SPAN_NOTICE("[user] starts replaces [src]'s damaged cables."),\
user.visible_message(SPAN_NOTICE("[user] replaces [src]'s damaged cables."),\
SPAN_NOTICE("You replace [src]'s damaged cables."))
return TRUE

else if(istype(I, /obj/item/device/lightreplacer))
if(!skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_ENGI))
to_chat(user, SPAN_WARNING("You have no clue how to repair [src]."))
return FALSE

..()
return 0
if(repair_state == FLOODLIGHT_REPAIR_UNSCREW)
to_chat(user, SPAN_WARNING("You need to unscrew [src]'s maintenance hatch."))
return FALSE
if(repair_state == FLOODLIGHT_REPAIR_SCREW)
to_chat(user, SPAN_WARNING("You need to screw [src]'s maintenance hatch."))
return FALSE

var/obj/item/device/lightreplacer/replacer = I
if(!replacer.CanUse(user))
to_chat(user, replacer.failmsg)
return FALSE
playsound(loc, 'sound/items/Crowbar.ogg', 25, 1)
user.visible_message(SPAN_NOTICE("[user] starts replacing [src]'s damaged lighting assembly."),\
SPAN_NOTICE("You start replacing [src]'s damaged lighting assembly."))
if(do_after(user, 2 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC))
if(QDELETED(src) || repair_state == FLOODLIGHT_REPAIR_SCREW)
return
replacer.Use(user)
repair_state = FLOODLIGHT_REPAIR_SCREW
user.visible_message(SPAN_NOTICE("[user] replaces [src]'s damaged lighting assembly."),\
SPAN_NOTICE("You replace [src]'s damaged lighting assembly."))
return TRUE

return ..()

/obj/structure/machinery/colony_floodlight/attack_hand(mob/user)
if(ishuman(user))
if(damaged)
to_chat(user, SPAN_WARNING("[src] is damaged."))
else if(!is_lit)
to_chat(user, SPAN_WARNING("Nothing happens. Looks like it's powered elsewhere."))
return 0
..()
return FALSE
return ..()

/obj/structure/machinery/colony_floodlight/get_examine_text(mob/user)
. = ..()
Expand All @@ -251,13 +274,20 @@
if(skillcheck(user, SKILL_ENGINEER, SKILL_ENGINEER_ENGI))
switch(repair_state)
if(FLOODLIGHT_REPAIR_UNSCREW) . += SPAN_INFO("You must first unscrew its maintenance hatch.")
if(FLOODLIGHT_REPAIR_CROWBAR) . += SPAN_INFO("You must crowbar its maintenance hatch open.")
if(FLOODLIGHT_REPAIR_CROWBAR) . += SPAN_INFO("You must crowbar its lighting assembly out or use a light replacer.")
if(FLOODLIGHT_REPAIR_WELD) . += SPAN_INFO("You must weld the damage to it.")
if(FLOODLIGHT_REPAIR_CABLE) . += SPAN_INFO("You must replace its damaged cables.")
if(FLOODLIGHT_REPAIR_SCREW) . += SPAN_INFO("You must screw its maintenance hatch closed.")
else if(!is_lit)
. += SPAN_INFO("It doesn't seem powered.")

/obj/structure/machinery/colony_floodlight/proc/toggle_light()
is_lit = !is_lit
if(!damaged)
set_light(is_lit ? lum_value : 0)
update_icon()
return is_lit

#undef FLOODLIGHT_REPAIR_UNSCREW
#undef FLOODLIGHT_REPAIR_CROWBAR
#undef FLOODLIGHT_REPAIR_WELD
Expand Down
5 changes: 3 additions & 2 deletions code/modules/power/apc.dm
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,9 @@ GLOBAL_LIST_INIT(apc_wire_descriptions, list(
ui.open()

/obj/structure/machinery/power/apc/ui_status(mob/user)
if(!opened && can_use(user, 1))
. = UI_INTERACTIVE
. = ..()
if(opened || !can_use(user, TRUE))
return UI_DISABLED

/obj/structure/machinery/power/apc/ui_state(mob/user)
return GLOB.not_incapacitated_and_adjacent_state
Expand Down
7 changes: 3 additions & 4 deletions code/modules/power/smes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -281,14 +281,13 @@
// TGUI STUFF \\
/obj/structure/machinery/power/smes/ui_status(mob/user)
if(!(stat & BROKEN) && !open_hatch)
. = UI_INTERACTIVE

/obj/structure/machinery/power/smes/ui_state(mob/user)
. = ..()
if(stat & BROKEN)
return UI_CLOSE
if(open_hatch)
return UI_DISABLED

/obj/structure/machinery/power/smes/ui_state(mob/user)
return GLOB.not_incapacitated_and_adjacent_state

/obj/structure/machinery/power/smes/tgui_interact(mob/user, datum/tgui/ui)
Expand Down

0 comments on commit 6b835c0

Please sign in to comment.