Files
Aurora.3/code/game/objects/structures/girders.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

387 lines
12 KiB
Plaintext

/obj/structure/girder
desc = "The basic building block of all walls."
desc_info = "Use metal sheets on this to build a normal wall.<br>\
A false wall can be made by using a crowbar on this girder, and then adding some material.<br>\
You can dismantle the grider with a wrench, or add support struts with a screwdriver to enable further reinforcement.<br>\
If reinforced, before you can dismantle it, you must first unscrew the support struts, then cut them with wirecutters."
icon_state = "girder"
anchored = 1
density = 1
layer = BELOW_OBJ_LAYER
w_class = WEIGHT_CLASS_HUGE
obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED
pass_flags_self = PASSTABLE
var/state = 0
var/health = 200
var/cover = 50 //how much cover the girder provides against projectiles.
build_amt = 2
var/material/reinf_material
var/reinforcing = 0
var/plating = FALSE
/obj/structure/girder/get_examine_text(mob/user, distance, is_adjacent, infix, suffix)
. = ..()
var/state
var/current_damage = health / initial(health)
switch(current_damage)
if(0 to 0.2)
state = SPAN_DANGER("The support struts are collapsing!")
if(0.2 to 0.4)
state = SPAN_WARNING("The support struts are warped!")
if(0.4 to 0.8)
state = SPAN_NOTICE("The support struts are dented, but holding together.")
if(0.8 to 1)
state = SPAN_NOTICE("The support struts look completely intact.")
. += state
/obj/structure/girder/displaced
name = "displaced girder"
icon_state = "displaced"
anchored = 0
health = 50
cover = 25
/obj/structure/girder/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
//Girders only provide partial cover. There's a chance that the projectiles will just pass through. (unless you are trying to shoot the girder)
if(hitting_projectile.original != src && !prob(cover))
return BULLET_ACT_HIT //pass through
var/damage = hitting_projectile.get_structure_damage()
if(!damage)
return BULLET_ACT_BLOCK
if(!istype(hitting_projectile, /obj/projectile/beam))
damage *= 0.4 //non beams do reduced damage
take_damage(damage)
return ..()
/obj/structure/girder/proc/take_damage(var/damage)
health -= damage
if(health <= 0)
visible_message(SPAN_WARNING("\The [src] falls apart!"))
dismantle()
/obj/structure/girder/proc/reset_girder()
anchored = 1
cover = initial(cover)
health = min(health,initial(health))
state = 0
icon_state = initial(icon_state)
reinforcing = 0
if(reinf_material)
reinforce_girder()
/obj/structure/girder/attackby(obj/item/attacking_item, mob/user)
if(attacking_item.iswrench() && state == 0)
if(anchored && !reinf_material)
to_chat(user, SPAN_NOTICE("Now disassembling the girder..."))
if(attacking_item.use_tool(src, user, 40, volume = 50))
if(!src) return
to_chat(user, SPAN_NOTICE("You dissasembled the girder!"))
dismantle()
else if(!anchored)
to_chat(user, SPAN_NOTICE("Now securing the girder..."))
if(attacking_item.use_tool(src, user, 40, volume = 50))
to_chat(user, SPAN_NOTICE("You secured the girder!"))
reset_girder()
else if(istype(attacking_item, /obj/item/gun/energy/plasmacutter))
var/obj/item/gun/energy/plasmacutter/PC = attacking_item
to_chat(user, SPAN_NOTICE("You start lining up \the [PC] to the joints of \the [src]..."))
if(do_after(user, 2 SECONDS))
if(!src)
return
playsound(loc, PC.fire_sound, 100, 1)
to_chat(user, SPAN_NOTICE("You blast apart the girder!"))
attacking_item.use_resource(user, 1)
dismantle()
else if(istype(attacking_item, /obj/item/melee/energy))
var/obj/item/melee/energy/WT = attacking_item
if(WT.active)
to_chat(user, SPAN_NOTICE("Now slicing apart the girder..."))
if(attacking_item.use_tool(src, user, 30, volume = 50))
if(!src) return
to_chat(user, SPAN_NOTICE("You slice apart the girder!"))
dismantle()
else
to_chat(user, SPAN_NOTICE("You need to activate the weapon to do that!"))
return
else if(istype(attacking_item, /obj/item/melee/energy/blade))
to_chat(user, SPAN_NOTICE("Now slicing apart the girder..."))
if(attacking_item.use_tool(src, user, 30, volume = 50))
if(!src) return
to_chat(user, SPAN_NOTICE("You slice apart the girder!"))
dismantle()
else if(istype(attacking_item, /obj/item/melee/chainsword))
var/obj/item/melee/chainsword/WT = attacking_item
if(WT.active)
to_chat(user, SPAN_NOTICE("Now slicing apart the girder..."))
if(WT.use_tool(src, user, 60, volume = 50))
if(!src) return
to_chat(user, SPAN_NOTICE("You slice apart the girder!"))
dismantle()
else
to_chat(user, SPAN_NOTICE("You need to activate the weapon to do that!"))
return
else if(istype(attacking_item, /obj/item/pickaxe/diamonddrill))
to_chat(user, SPAN_NOTICE("You drill through the girder!"))
dismantle()
else if(istype(attacking_item, /obj/item/melee/arm_blade/))
to_chat(user, SPAN_NOTICE("Now slicing apart the girder..."))
if(do_after(user,150))
if(!src)
return
to_chat(user, SPAN_NOTICE("You slice apart the girder!"))
dismantle()
else if(attacking_item.isscrewdriver())
if(state == 2)
to_chat(user, SPAN_NOTICE("Now unsecuring support struts..."))
if(attacking_item.use_tool(src, user, 40, volume = 50))
if(!src)
return
to_chat(user, SPAN_NOTICE("You unsecured the support struts!"))
state = 1
else if(anchored && !reinf_material)
attacking_item.play_tool_sound(get_turf(src), 50)
reinforcing = !reinforcing
to_chat(user, SPAN_NOTICE("\The [src] can now be [reinforcing? "reinforced" : "constructed"]!"))
return
else if(attacking_item.iswirecutter() && state == 1)
to_chat(user, SPAN_NOTICE("Now removing support struts..."))
if(attacking_item.use_tool(src, user, 40, volume = 50))
if(!src) return
to_chat(user, SPAN_NOTICE("You removed the support struts!"))
reinf_material = null
reset_girder()
else if(attacking_item.iscrowbar() && state == 0 && anchored)
to_chat(user, SPAN_NOTICE("Now dislodging the girder..."))
if(attacking_item.use_tool(src, user, 40, volume = 50))
if(!src) return
to_chat(user, SPAN_NOTICE("You dislodged the girder!"))
icon_state = "displaced"
anchored = 0
health = 50
cover = 25
else if(istype(attacking_item, /obj/item/stack/material))
if(reinforcing && !reinf_material)
if(!reinforce_with_material(attacking_item, user))
return ..()
else
if(!construct_wall(attacking_item, user))
return ..()
else if(attacking_item.force)
var/damage_to_deal = attacking_item.force
var/weaken = 0
if(reinf_material)
weaken += reinf_material.integrity * 3 //Since girders don't have a secondary material, buff 'em up a bit.
weaken /= 100
user.do_attack_animation(src)
playsound(src, 'sound/weapons/smash.ogg', 50)
if(damage_to_deal > weaken && (damage_to_deal > MIN_DAMAGE_TO_HIT))
damage_to_deal -= weaken
visible_message(SPAN_WARNING("[user] strikes \the [src] with \the [attacking_item], [is_sharp(attacking_item) ? "slicing" : "denting"] a support rod!"))
take_damage(damage_to_deal)
else
visible_message(SPAN_WARNING("[user] strikes \the [src] with \the [attacking_item], but it bounces off!"))
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
return
return ..()
/obj/structure/girder/proc/construct_wall(obj/item/stack/material/S, mob/user)
if(S.get_amount() < 2)
to_chat(user, SPAN_NOTICE("There isn't enough material here to construct a wall."))
return 0
var/material/M = SSmaterials.get_material_by_name(S.default_type)
if(!istype(M))
return 0
var/wall_fake
add_hiddenprint(usr)
if(M.integrity < 50)
to_chat(user, SPAN_NOTICE("This material is too soft for use in wall construction."))
return 0
if(!plating)
to_chat(user, SPAN_NOTICE("You begin adding the plating..."))
plating = TRUE
else
return TRUE
if(!do_after(user,40) || !S.use(2))
plating = FALSE
return 1 //once we've gotten this far don't call parent attackby()
plating = FALSE
if(anchored)
to_chat(user, SPAN_NOTICE("You added the plating!"))
else
to_chat(user, SPAN_NOTICE("You create a false wall! Push on it to open or close the passage."))
wall_fake = 1
var/turf/Tsrc = get_turf(src)
var/original_type = Tsrc.type
Tsrc.ChangeTurf(/turf/simulated/wall)
var/turf/simulated/wall/T = Tsrc
T.under_turf = original_type
T.set_material(M, reinf_material)
if(wall_fake)
T.can_open = 1
T.add_hiddenprint(usr)
qdel(src)
return 1
/obj/structure/girder/proc/reinforce_with_material(obj/item/stack/material/S, mob/user) //if the verb is removed this can be renamed.
if(reinf_material)
to_chat(user, SPAN_NOTICE("\The [src] is already reinforced."))
return 0
if(S.get_amount() < 2)
to_chat(user, SPAN_NOTICE("There isn't enough material here to reinforce the girder."))
return 0
var/material/M = SSmaterials.get_material_by_name(S.default_type)
if(!istype(M) || M.integrity < 50)
to_chat(user, "You cannot reinforce \the [src] with that; it is too soft.")
return 0
to_chat(user, SPAN_NOTICE("Now reinforcing..."))
if (!do_after(user,40) || !S.use(2))
return 1 //don't call parent attackby() past this point
to_chat(user, SPAN_NOTICE("You added reinforcement!"))
reinf_material = M
reinforce_girder()
return 1
/obj/structure/girder/proc/reinforce_girder()
cover = reinf_material.hardness
health = 500
state = 2
icon_state = "reinforced"
reinforcing = 0
/obj/structure/girder/attack_hand(mob/user as mob)
if((user.mutations & HULK))
visible_message(SPAN_DANGER("[user] smashes [src] apart!"))
dismantle()
return
return ..()
/obj/structure/girder/ex_act(severity)
switch(severity)
if(1.0)
qdel(src)
return
if(2.0)
if (prob(30))
dismantle()
return
else
health -= rand(60,180)
if(3.0)
if (prob(5))
dismantle()
return
else
health -= rand(40,80)
if(health <= 0)
dismantle()
return
/obj/structure/girder/attack_generic(var/mob/user, var/damage, var/attack_message = "smashes apart", var/wallbreaker)
if(!damage || !wallbreaker)
return FALSE
user.do_attack_animation(src)
visible_message(SPAN_DANGER("[user] [attack_message] \the [src]!"))
dismantle()
return TRUE
/obj/structure/girder/cult
icon= 'icons/obj/cult.dmi'
icon_state= "cultgirder"
health = 250
cover = 70
appearance_flags = NO_CLIENT_COLOR
/obj/structure/girder/cult/dismantle()
new /obj/effect/decal/remains/human(get_turf(src))
qdel(src)
/obj/structure/girder/cult/attackby(obj/item/attacking_item, mob/user)
if(attacking_item.iswrench())
to_chat(user, SPAN_NOTICE("Now disassembling the girder..."))
if(attacking_item.use_tool(src, user, 40, volume = 50))
to_chat(user, SPAN_NOTICE("You dissasembled the girder!"))
dismantle()
else if(istype(attacking_item, /obj/item/gun/energy/plasmacutter))
to_chat(user, SPAN_NOTICE("Now slicing apart the girder..."))
if(attacking_item.use_tool(src, user, 30, volume = 50))
to_chat(user, SPAN_NOTICE("You slice apart the girder!"))
dismantle()
else if(istype(attacking_item, /obj/item/pickaxe/diamonddrill))
to_chat(user, SPAN_NOTICE("You drill through the girder!"))
new /obj/effect/decal/remains/human(get_turf(src))
dismantle()
else if(istype(attacking_item, /obj/item/melee/energy))
var/obj/item/melee/energy/WT = attacking_item
if(WT.active)
to_chat(user, SPAN_NOTICE("Now slicing apart the girder..."))
if(attacking_item.use_tool(src, user, 30, volume = 50))
to_chat(user, SPAN_NOTICE("You slice apart the girder!"))
dismantle()
else
to_chat(user, SPAN_NOTICE("You need to activate the weapon to do that!"))
return
else if(istype(attacking_item, /obj/item/melee/energy/blade))
to_chat(user, SPAN_NOTICE("Now slicing apart the girder..."))
if(attacking_item.use_tool(src, user, 30, volume = 50))
to_chat(user, SPAN_NOTICE("You slice apart the girder!"))
dismantle()
else if(istype(attacking_item, /obj/item/melee/chainsword))
var/obj/item/melee/chainsword/WT = attacking_item
if(WT.active)
to_chat(user, SPAN_NOTICE("Now slicing apart the girder..."))
if(WT.use_tool(src, user, 60, volume = 50))
to_chat(user, SPAN_NOTICE("You slice apart the girder!"))
dismantle()
else
to_chat(user, SPAN_NOTICE("You need to activate the weapon to do that!"))
return
/obj/structure/girder/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if (!mover)
return 1
if(mover?.movement_type & PHASING)
return TRUE
if(istype(mover,/obj/projectile) && density)
if (prob(50))
return 1
else
return 0
return ..()