Files
Aurora.3/code/modules/shieldgen/shieldwallgen.dm
Fluffy c24b4c7097 Projectile refactoring madness (#19878)
Refactored the projectile code, mostly in line with TG's now.
Refactored various procs that are used or depends on it.
Projectiles can now ricochet if enabled to.
Damage falloffs with distance.
Homing projectiles can now have accuracy falloff with distance.
Projectiles have a maximum range.
Muzzle flash is configurable per projectile.
Impact effect of the projectile is configurable per projectile.
Accuracy decreases with distance.
Projectiles work with signals and emits them, for easy hooking up from
other parts of the code.
Meatshielding is now less effective .
Impact sound is now configurable per projectile.

High risk.
2024-09-23 10:12:57 +00:00

317 lines
8.9 KiB
Plaintext

#define POWER_INACTIVE 0
#define POWER_STARTING 1
#define POWER_ACTIVE 2
/obj/machinery/shieldwallgen
name = "shield generator"
desc = "A portable shield generator, capable of casting a shield to another powered generator in range."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "Shield_Gen"
anchored = FALSE
density = TRUE
req_access = list(ACCESS_ENGINE_EQUIP)
var/power_state = FALSE
var/is_powered = FALSE
var/wrenched = FALSE
var/steps = 0
var/last_check = 0
var/check_delay = 10
var/locked = TRUE
var/storedpower = 0
obj_flags = OBJ_FLAG_CONDUCTABLE
//There have to be at least two posts, so these are effectively doubled
var/power_draw = 30000 //30 kW. How much power is drawn from powernet. Increase this to allow the generator to sustain longer shields, at the cost of more power draw.
var/max_stored_power = 50000 //50 kW
use_power = POWER_USE_OFF //Draws directly from power net. Does not use APC power.
/obj/machinery/shieldwallgen/update_icon()
if(power_state >= POWER_STARTING)
icon_state = "Shield_Gen +a"
else
icon_state = "Shield_Gen"
/obj/machinery/shieldwallgen/attack_hand(mob/user)
if(!wrenched)
to_chat(user, SPAN_WARNING("The shield generator needs to be firmly secured to the floor first."))
return TRUE
if(locked && !issilicon(user))
to_chat(user, SPAN_WARNING("The controls are locked!"))
return TRUE
if(!is_powered)
to_chat(user, SPAN_WARNING("The shield generator needs to be powered by wire underneath."))
return TRUE
if(power_state >= POWER_STARTING)
power_state = POWER_INACTIVE
user.visible_message("<b>[user]</b> turns \the [src] off.", SPAN_NOTICE("You turn off \the [src]."), SPAN_NOTICE("You hear a heavy droning fade out."))
alldir_cleanup()
else
power_state = POWER_STARTING
user.visible_message("<b>[user]</b> turns \the [src] on.", SPAN_NOTICE("You turn on \the [src]."), SPAN_NOTICE("You hear a heavy droning start up."))
update_icon()
add_fingerprint(user)
/obj/machinery/shieldwallgen/proc/power()
if(!anchored)
is_powered = FALSE
return FALSE
var/turf/T = loc
if(!istype(T))
is_powered = FALSE
return FALSE
var/obj/structure/cable/C = T.get_cable_node()
var/datum/powernet/PN
if(C)
PN = C.powernet // find the powernet of the connected cable
if(!PN)
is_powered = FALSE
return FALSE
var/shieldload = between(500, max_stored_power - storedpower, power_draw) //what we try to draw
shieldload = PN.draw_power(shieldload) //what we actually get
storedpower += shieldload
//If we're still in the red, then there must not be enough available power to cover our load.
if(storedpower <= 0)
is_powered = FALSE
return FALSE
is_powered = TRUE // IVE GOT THE POWER!
return TRUE
/obj/machinery/shieldwallgen/process()
power()
if(is_powered)
storedpower -= 2500
storedpower = clamp(storedpower, 0, max_stored_power)
if(power_state == POWER_STARTING)
if(!wrenched)
power_state = POWER_INACTIVE
return
addtimer(CALLBACK(src, PROC_REF(setup_field), 1), 1)
addtimer(CALLBACK(src, PROC_REF(setup_field), 2), 2)
addtimer(CALLBACK(src, PROC_REF(setup_field), 3), 4)
addtimer(CALLBACK(src, PROC_REF(setup_field), 4), 8)
power_state = POWER_ACTIVE
if(power_state >= POWER_STARTING)
if(!is_powered)
visible_message(SPAN_WARNING("\The [src] shuts down due to a lack of power."), SPAN_NOTICE("You hear a heavy droning fade out."))
power_state = POWER_INACTIVE
update_icon()
alldir_cleanup()
/obj/machinery/shieldwallgen/proc/setup_field(var/NSEW)
var/turf/T = loc
var/turf/T2 = loc
var/obj/machinery/shieldwallgen/G
var/steps = 0
var/oNSEW = 0
if(!NSEW)//Make sure its ran right
return
oNSEW = reverse_direction(NSEW)
for(var/dist = 0, dist <= 9, dist++) // checks out to 8 tiles away for another generator
T = get_step(T2, NSEW)
T2 = T
steps += 1
if(locate(/obj/machinery/shieldwallgen) in T)
G = (locate(/obj/machinery/shieldwallgen) in T)
steps -= 1
if(!G.power_state)
return
G.cleanup(oNSEW)
break
if(isnull(G))
return
T2 = loc
for(var/dist = 0, dist < steps, dist++) // creates each field tile
var/field_dir = get_dir(T2, get_step(T2, NSEW))
T = get_step(T2, NSEW)
T2 = T
var/obj/shieldwall/CF = new /obj/shieldwall/(T, src, G) //(ref to this gen, ref to connected gen)
CF.set_dir(field_dir)
/obj/machinery/shieldwallgen/attackby(obj/item/attacking_item, mob/user)
if(attacking_item.iswrench())
if(power_state)
to_chat(user, SPAN_WARNING("You cannot unsecure \the [src] while it's active."))
return
wrenched = !wrenched
anchored = wrenched
attacking_item.play_tool_sound(get_turf(src), 75)
add_fingerprint(user)
var/others_msg = wrenched ? "<b>[user]</b> secures the external reinforcing bolts to the floor." : "<b>[user]</b> unsecures the external reinforcing bolts."
var/self_msg = wrenched ? "You secure the external reinforcing bolts to the floor." : "You unsecure the external reinforcing bolts."
user.visible_message(others_msg, SPAN_NOTICE(self_msg), SPAN_NOTICE("You hear a ratcheting noise."))
return
if(attacking_item.GetID())
add_fingerprint(user)
if(allowed(user))
locked = !locked
var/msg = "The controls are now [locked ? "locked" : "unlocked"]."
to_chat(user, SPAN_NOTICE(msg))
else
to_chat(user, SPAN_WARNING("Access denied."))
return
return ..()
/obj/machinery/shieldwallgen/proc/alldir_cleanup()
for(var/dir in list(NORTH, SOUTH, EAST, WEST))
cleanup(dir)
/obj/machinery/shieldwallgen/proc/cleanup(var/NSEW)
var/obj/shieldwall/F
var/obj/machinery/shieldwallgen/G
var/turf/T = loc
var/turf/T2 = loc
for(var/dist = 0, dist <= 9, dist++) // checks out to 8 tiles away for fields
T = get_step(T2, NSEW)
T2 = T
if(locate(/obj/shieldwall) in T)
F = (locate(/obj/shieldwall) in T)
qdel(F)
if(locate(/obj/machinery/shieldwallgen) in T)
G = (locate(/obj/machinery/shieldwallgen) in T)
if(!G.power_state)
break
/obj/machinery/shieldwallgen/Destroy()
alldir_cleanup()
return ..()
/obj/machinery/shieldwallgen/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
. = ..()
if(. != BULLET_ACT_HIT)
return .
storedpower -= 400 * hitting_projectile.get_structure_damage()
if(power_state >= POWER_STARTING)
visible_message(SPAN_WARNING("\The [src]'s shielding sparks as \the [hitting_projectile] hits it!"))
/obj/shieldwall
name = "energy shield"
desc = "An energy shield."
icon = 'icons/effects/effects.dmi'
icon_state = "shieldwall"
anchored = TRUE
density = TRUE
unacidable = TRUE
light_range = 3
light_color = LIGHT_COLOR_BLUE
var/needs_power = FALSE
var/power_state = POWER_STARTING
var/delay = 5
var/last_active
var/mob/U
var/obj/machinery/shieldwallgen/gen_primary
var/obj/machinery/shieldwallgen/gen_secondary
var/power_usage = 2500 //how much power it takes to sustain the shield
var/generate_power_usage = 7500 //how much power it takes to start up the shield
/obj/shieldwall/Initialize(mapload, var/obj/machinery/shieldwallgen/A, var/obj/machinery/shieldwallgen/B)
. = ..()
update_nearby_tiles()
gen_primary = A
gen_secondary = B
if(A?.power_state && B?.power_state)
needs_power = TRUE
A.storedpower -= generate_power_usage / 2
B.storedpower -= generate_power_usage / 2
START_PROCESSING(SSprocessing, src)
else
qdel(src) //need at least two generator posts
/obj/shieldwall/Destroy()
update_nearby_tiles()
STOP_PROCESSING(SSprocessing, src)
return ..()
/obj/shieldwall/attack_hand(mob/user)
to_chat(user, SPAN_WARNING("\The [src] pushes you back as you try to touch it."))
/obj/shieldwall/process()
if(needs_power)
if(!gen_primary || !gen_secondary)
qdel(src)
return
if(!gen_primary.power_state || !gen_secondary.power_state)
qdel(src)
return
gen_primary.storedpower -= power_usage / 2
gen_secondary.storedpower -= power_usage / 2
/obj/shieldwall/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
. = ..()
if(. != BULLET_ACT_HIT)
return .
if(needs_power)
var/obj/machinery/shieldwallgen/G
if(prob(50))
G = gen_primary
else
G = gen_secondary
visible_message(SPAN_WARNING("\The [src] wobbles precariously as \the [hitting_projectile] impacts it!"))
G.storedpower -= 400 * hitting_projectile.get_structure_damage()
/obj/shieldwall/ex_act(severity)
if(needs_power)
var/obj/machinery/shieldwallgen/G
switch(severity)
if(1.0) //big boom
if(prob(50))
G = gen_primary
else
G = gen_secondary
G.storedpower -= 120000
if(2.0) //medium boom
if(prob(50))
G = gen_primary
else
G = gen_secondary
G.storedpower -= 30000
if(3.0) //lil boom
if(prob(50))
G = gen_primary
else
G = gen_secondary
G.storedpower -= 12000
/obj/shieldwall/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0))
return TRUE
if(mover?.movement_type & PHASING)
return TRUE
if(istype(mover) && mover.pass_flags & PASSGLASS)
return prob(20)
else
if(istype(mover, /obj/projectile))
return prob(10)
else
return !density
#undef POWER_INACTIVE
#undef POWER_STARTING
#undef POWER_ACTIVE