Files
Batrachophreno 5277251959 Tool behaviors port (#21663)
For a robust crafting system, I need a new materials framework.
For a new materials framework, I need to clean up reagents.
To clean up reagents, I need to pare down foods from reagent holders.
To pare down foods from reagent holders, I need to port edibility
components.
To port edibility components, I need to port processing components.
To port processing components, I need to port tool behaviors.

This is all back-end code, no new features or functionality from this.
2026-01-27 08:44:49 +00:00

266 lines
7.8 KiB
Plaintext

//renwicks: fictional unit to describe shield strength
//a small meteor hit will deduct 1 renwick of strength from that shield tile
//light explosion range will do 1 renwick's damage
//medium explosion range will do 2 renwick's damage
//heavy explosion range will do 3 renwick's damage
//explosion damage is cumulative. if a tile is in range of light, medium and heavy damage, it will take a hit from all three
/obj/machinery/shield_gen
name = "bubble shield generator"
desc = "Machine that generates an impenetrable field of energy when activated."
icon = 'icons/obj/machinery/shielding.dmi'
icon_state = "generator0"
density = TRUE
use_power = POWER_USE_OFF //doesn't use APC power
req_one_access = list(ACCESS_CAPTAIN, ACCESS_SECURITY, ACCESS_ENGINE)
/// Our owned energy field.
var/datum/energy_field/energy_field
/// If the machine is powered or not.
var/powered = FALSE
/// Whether the shield generator is active or not.
var/active = FALSE
/// ID lock.
var/locked = FALSE
/// Radius of the field.
var/field_radius = 3
/// Maximum field radius.
var/max_field_radius = 100
/// The shield capacitor attached to this shield generator.
var/obj/machinery/shield_capacitor/owned_capacitor
/// If this shield generator supports multi-z.
var/multiz = TRUE
/obj/machinery/shield_gen/Initialize()
for(var/obj/machinery/shield_capacitor/possible_cap in range(1, src))
if(get_dir(possible_cap, src) == possible_cap.dir)
owned_capacitor = possible_cap
break
energy_field = new(src, get_shielded_turfs())
. = ..()
/obj/machinery/shield_gen/Destroy()
owned_capacitor = null
return ..()
/obj/machinery/shield_gen/emag_act(var/remaining_charges, var/mob/user)
if(prob(75))
locked = !locked
to_chat(user, "Controls are now [locked ? "locked." : "unlocked."]")
. = TRUE
updateDialog()
spark(src, 5, GLOB.alldirs)
/obj/machinery/shield_gen/attackby(obj/item/attacking_item, mob/user)
if(istype(attacking_item, /obj/item/card/id))
if(allowed(user))
locked = !locked
to_chat(user, "Controls are now [locked ? "locked." : "unlocked."]")
updateDialog()
else
to_chat(user, SPAN_ALERT("Access denied."))
else if(attacking_item.tool_behaviour == TOOL_WRENCH)
anchored = !anchored
visible_message(SPAN_NOTICE("\The [src] has been [anchored ? "bolted to the floor":"unbolted from the floor"] by \the [user]."))
if(active)
toggle()
if(anchored)
for(var/obj/machinery/shield_capacitor/cap in range(1, src))
if(cap.owned_gen)
continue
if(get_dir(cap, src) == cap.dir && cap.anchored)
owned_capacitor = cap
owned_capacitor.owned_gen = src
break
else
if(owned_capacitor && owned_capacitor.owned_gen == src)
owned_capacitor.owned_gen = null
owned_capacitor = null
else
..()
/obj/machinery/shield_gen/attack_ai(mob/user)
if(!ai_can_interact(user))
return
return attack_hand(user)
/obj/machinery/shield_gen/attack_hand(mob/user)
if(stat & BROKEN)
return
interact(user)
/obj/machinery/shield_gen/interact(mob/user)
if(locked)
to_chat(user, SPAN_WARNING("The device is locked. Swipe your ID to unlock it."))
return
if(!anchored)
to_chat(user, SPAN_WARNING("The device needs to be bolted to the ground first."))
return
else
if(owned_capacitor)
if(!((owned_capacitor in range(1, src)) && get_dir(owned_capacitor, src) == owned_capacitor.dir && owned_capacitor.anchored))
if(owned_capacitor.owned_gen == src)
owned_capacitor.owned_gen = null
owned_capacitor = null
if(!owned_capacitor)
for(var/obj/machinery/shield_capacitor/cap in range(1, src))
if(cap.owned_gen)
continue
if(get_dir(cap, src) == cap.dir && cap.anchored)
owned_capacitor = cap
owned_capacitor.owned_gen = src
updateDialog()
break
return ui_interact(user)
/obj/machinery/shield_gen/process()
if(active)
if(!anchored)
toggle()
if(stat & BROKEN)
toggle()
return PROCESS_KILL
if(istype(energy_field))
var/required_energy = energy_field.get_required_energy()
var/assumed_charge = assume_charge(required_energy)
energy_field.handle_strength(assumed_charge)
/**
* Called whenever the field needs to take charge from the capacitor.
*/
/obj/machinery/shield_gen/proc/assume_charge(required_energy)
if(!owned_capacitor)
return 0
var/assumed_charge = min(owned_capacitor.stored_charge, required_energy)
assumed_charge = max(assumed_charge, 0)
owned_capacitor.stored_charge -= assumed_charge
return assumed_charge
/obj/machinery/shield_gen/ex_act(var/severity)
if(active)
toggle()
return ..()
/obj/machinery/shield_gen/proc/toggle()
active = !active
update_icon()
if(active)
for(var/mob/M as anything in hearers(5,src))
to_chat(M, SPAN_NOTICE("[icon2html(src, M)] You hear heavy droning start up."))
energy_field.set_shielded_turfs(get_shielded_turfs())
else
for(var/mob/M as anything in hearers(5,src))
to_chat(M, SPAN_NOTICE("[icon2html(src, M)] You hear heavy droning fade out."))
energy_field.clear_field()
/obj/machinery/shield_gen/update_icon()
if(stat & BROKEN)
icon_state = "broke"
else
if (active)
icon_state = "generator1"
else
icon_state = "generator0"
//grab the border tiles in a square around this machine
/obj/machinery/shield_gen/proc/get_shielded_turfs()
var/turf/T = get_turf(src)
. = list()
if(field_radius > 0 && T)
var/connected_levels = list(T.z)
if(multiz)
for(var/turf/connected_z_turf as anything in (getzabove(T) + getzbelow(T)))
connected_levels += connected_z_turf.z
. += block(\
locate(T.x - field_radius, T.y + field_radius, min(connected_levels)),\
locate(T.x + field_radius - 1, T.y + field_radius, max(connected_levels))\
)
. += block(\
locate(T.x + field_radius, T.y - field_radius, min(connected_levels)),\
locate(T.x - field_radius + 1, T.y - field_radius, max(connected_levels))\
)
. += block(\
locate(T.x - field_radius, T.y + field_radius - 1, min(connected_levels)),\
locate(T.x - field_radius, T.y - field_radius, max(connected_levels))\
)
. += block(\
locate(T.x + field_radius, T.y + field_radius, min(connected_levels)),\
locate(T.x + field_radius, T.y - field_radius + 1, max(connected_levels))\
)
return . - get_turf(src)
/obj/machinery/shield_gen/ui_interact(mob/user, var/datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ShieldGenerator", "Shield Generator", 480, 400)
ui.open()
/obj/machinery/shield_gen/ui_data(mob/user)
var/list/data = list()
data["owned_capacitor"] = !!owned_capacitor
data["active"] = active
data["time_since_fail"] = energy_field ? energy_field.time_since_fail : 0
data["multiz"] = multiz
data["field_radius"] = field_radius
data["min_field_radius"] = 1
data["max_field_radius"] = max_field_radius
data = energy_field.add_field_ui_data(data)
return data
/obj/machinery/shield_gen/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
. = ..()
if(.)
return
switch(action)
if("toggle")
toggle()
if("multiz")
multiz = !multiz
if ("size_set")
field_radius = between(1, text2num(params["size_set"]), max_field_radius)
if ("charge_set")
energy_field.strengthen_rate = (between(1, text2num(params["charge_set"]), (energy_field.max_strengthen_rate * 10)) / 10)
if ("field_set")
energy_field.target_field_strength = between(1, text2num(params["field_set"]), 10)
add_fingerprint(usr)
/obj/machinery/shield_gen/proc/getzabove(var/turf/location)
var/connected = list()
var/turf/above = GET_TURF_ABOVE(location)
if(above)
connected += above
var/connected_levels = getzabove(above)
for(var/turf/z as anything in connected_levels)
connected += z
return connected
/obj/machinery/shield_gen/proc/getzbelow(var/turf/location)
var/connected = list()
var/turf/below = GET_TURF_BELOW(location)
if(below)
connected += below
var/connected_levels = getzbelow(below)
for(var/turf/z as anything in connected_levels)
connected += z
return connected