mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-31 12:01:47 +00:00
About The Pull Request Continuation of #64375, extracting tool behavior from attackby() and moving it into discrete _act procs. This is about as many files as I had in the last version, as I still want this to be reviewable. As before, I've tested everything in game and it works as it previously did. Why It's Good For The Game The more code moved out of attackby, the more modular things become. Changelog cl refactor: Moves more tool behavior out of attackby(). /cl
354 lines
12 KiB
Plaintext
354 lines
12 KiB
Plaintext
/// Max number of unanchored items that will be moved from a tile when attempting to add a window to a grille.
|
|
#define CLEAR_TILE_MOVE_LIMIT 20
|
|
|
|
/obj/structure/grille
|
|
desc = "A flimsy framework of iron rods."
|
|
name = "grille"
|
|
icon = 'icons/obj/structures.dmi'
|
|
icon_state = "grille"
|
|
base_icon_state = "grille"
|
|
density = TRUE
|
|
anchored = TRUE
|
|
pass_flags_self = PASSGRILLE
|
|
flags_1 = CONDUCT_1
|
|
pressure_resistance = 5*ONE_ATMOSPHERE
|
|
armor = list(MELEE = 50, BULLET = 70, LASER = 70, ENERGY = 100, BOMB = 10, BIO = 100, FIRE = 0, ACID = 0)
|
|
max_integrity = 50
|
|
integrity_failure = 0.4
|
|
var/rods_type = /obj/item/stack/rods
|
|
var/rods_amount = 2
|
|
var/rods_broken = TRUE
|
|
|
|
/obj/structure/grille/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/atmos_sensitive, mapload)
|
|
|
|
/obj/structure/grille/Destroy()
|
|
update_cable_icons_on_turf(get_turf(src))
|
|
return ..()
|
|
|
|
/obj/structure/grille/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
|
|
. = ..()
|
|
update_appearance()
|
|
|
|
/obj/structure/grille/update_appearance(updates)
|
|
if(QDELETED(src) || broken)
|
|
return
|
|
|
|
. = ..()
|
|
if((updates & UPDATE_SMOOTHING) && (smoothing_flags & (SMOOTH_CORNERS|SMOOTH_BITMASK)))
|
|
QUEUE_SMOOTH(src)
|
|
|
|
/obj/structure/grille/update_icon_state()
|
|
icon_state = "[base_icon_state][((atom_integrity / max_integrity) <= 0.5) ? "50_[rand(0, 3)]" : null]"
|
|
return ..()
|
|
|
|
/obj/structure/grille/examine(mob/user)
|
|
. = ..()
|
|
if(anchored)
|
|
. += span_notice("It's secured in place with <b>screws</b>. The rods look like they could be <b>cut</b> through.")
|
|
if(!anchored)
|
|
. += span_notice("The anchoring screws are <i>unscrewed</i>. The rods look like they could be <b>cut</b> through.")
|
|
|
|
/obj/structure/grille/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
|
|
switch(the_rcd.mode)
|
|
if(RCD_DECONSTRUCT)
|
|
return list("mode" = RCD_DECONSTRUCT, "delay" = 20, "cost" = 5)
|
|
if(RCD_WINDOWGRILLE)
|
|
var/cost = 8
|
|
var/delay = 2 SECONDS
|
|
|
|
if(the_rcd.window_glass == RCD_WINDOW_REINFORCED)
|
|
delay = 4 SECONDS
|
|
cost = 12
|
|
|
|
return rcd_result_with_memory(
|
|
list("mode" = RCD_WINDOWGRILLE, "delay" = delay, "cost" = cost),
|
|
get_turf(src), RCD_MEMORY_WINDOWGRILLE,
|
|
)
|
|
return FALSE
|
|
|
|
/obj/structure/grille/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode)
|
|
switch(passed_mode)
|
|
if(RCD_DECONSTRUCT)
|
|
to_chat(user, span_notice("You deconstruct the grille."))
|
|
qdel(src)
|
|
return TRUE
|
|
if(RCD_WINDOWGRILLE)
|
|
if(!isturf(loc))
|
|
return FALSE
|
|
var/turf/T = loc
|
|
|
|
if(repair_grille())
|
|
to_chat(user, span_notice("You rebuild the broken grille."))
|
|
|
|
if(!clear_tile(user))
|
|
return FALSE
|
|
|
|
if(!ispath(the_rcd.window_type, /obj/structure/window))
|
|
CRASH("Invalid window path type in RCD: [the_rcd.window_type]")
|
|
var/obj/structure/window/window_path = the_rcd.window_type
|
|
if(!valid_window_location(T, user.dir, is_fulltile = initial(window_path.fulltile)))
|
|
return FALSE
|
|
to_chat(user, span_notice("You construct the window."))
|
|
var/obj/structure/window/WD = new the_rcd.window_type(T, user.dir)
|
|
WD.set_anchored(TRUE)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/obj/structure/grille/proc/clear_tile(mob/user)
|
|
var/at_users_feet = get_turf(user)
|
|
|
|
var/unanchored_items_on_tile
|
|
var/obj/item/last_item_moved
|
|
for(var/obj/item/item_to_move in loc.contents)
|
|
if(!item_to_move.anchored)
|
|
if(unanchored_items_on_tile <= CLEAR_TILE_MOVE_LIMIT)
|
|
item_to_move.forceMove(at_users_feet)
|
|
last_item_moved = item_to_move
|
|
unanchored_items_on_tile++
|
|
|
|
if(!unanchored_items_on_tile)
|
|
return TRUE
|
|
|
|
to_chat(user, span_notice("You move [unanchored_items_on_tile == 1 ? "[last_item_moved]" : "some things"] out of the way."))
|
|
|
|
if(unanchored_items_on_tile - CLEAR_TILE_MOVE_LIMIT > 0)
|
|
to_chat(user, span_warning("There's still too much stuff in the way!"))
|
|
return FALSE
|
|
|
|
return TRUE
|
|
|
|
/obj/structure/grille/Bumped(atom/movable/AM)
|
|
if(!ismob(AM))
|
|
return
|
|
var/mob/M = AM
|
|
shock(M, 70)
|
|
|
|
/obj/structure/grille/attack_animal(mob/user, list/modifiers)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
if(!shock(user, 70) && !QDELETED(src)) //Last hit still shocks but shouldn't deal damage to the grille
|
|
take_damage(rand(5,10), BRUTE, MELEE, 1)
|
|
|
|
/obj/structure/grille/attack_paw(mob/user, list/modifiers)
|
|
return attack_hand(user, modifiers)
|
|
|
|
/obj/structure/grille/hulk_damage()
|
|
return 60
|
|
|
|
/obj/structure/grille/attack_hulk(mob/living/carbon/human/user)
|
|
if(shock(user, 70))
|
|
return
|
|
. = ..()
|
|
|
|
/obj/structure/grille/attack_hand(mob/living/user, list/modifiers)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
user.changeNext_move(CLICK_CD_MELEE)
|
|
user.do_attack_animation(src, ATTACK_EFFECT_KICK)
|
|
user.visible_message(span_warning("[user] hits [src]."), null, null, COMBAT_MESSAGE_RANGE)
|
|
log_combat(user, src, "hit")
|
|
if(!shock(user, 70))
|
|
take_damage(rand(5,10), BRUTE, MELEE, 1)
|
|
|
|
/obj/structure/grille/attack_alien(mob/living/user, list/modifiers)
|
|
user.do_attack_animation(src)
|
|
user.changeNext_move(CLICK_CD_MELEE)
|
|
user.visible_message(span_warning("[user] mangles [src]."), null, null, COMBAT_MESSAGE_RANGE)
|
|
if(!shock(user, 70))
|
|
take_damage(20, BRUTE, MELEE, 1)
|
|
|
|
/obj/structure/grille/CanAllowThrough(atom/movable/mover, border_dir)
|
|
. = ..()
|
|
if(!. && istype(mover, /obj/projectile))
|
|
return prob(30)
|
|
|
|
/obj/structure/grille/CanAStarPass(obj/item/card/id/ID, to_dir, atom/movable/caller)
|
|
. = !density
|
|
if(istype(caller))
|
|
. = . || (caller.pass_flags & PASSGRILLE)
|
|
|
|
/obj/structure/grille/wirecutter_act(mob/living/user, obj/item/tool)
|
|
add_fingerprint(user)
|
|
if(shock(user, 100))
|
|
return
|
|
tool.play_tool_sound(src, 100)
|
|
deconstruct()
|
|
return TOOL_ACT_TOOLTYPE_SUCCESS
|
|
|
|
/obj/structure/grille/screwdriver_act(mob/living/user, obj/item/tool)
|
|
if(!isturf(loc) || !anchored)
|
|
return FALSE
|
|
add_fingerprint(user)
|
|
if(shock(user, 90))
|
|
return FALSE
|
|
tool.play_tool_sound(src, 100)
|
|
set_anchored(!anchored)
|
|
user.visible_message(span_notice("[user] [anchored ? "fastens" : "unfastens"] [src]."), \
|
|
span_notice("You [anchored ? "fasten [src] to" : "unfasten [src] from"] the floor."))
|
|
return TOOL_ACT_TOOLTYPE_SUCCESS
|
|
|
|
/obj/structure/grille/attackby(obj/item/W, mob/user, params)
|
|
user.changeNext_move(CLICK_CD_MELEE)
|
|
add_fingerprint(user)
|
|
if(istype(W, /obj/item/stack/rods) && broken)
|
|
if(shock(user, 90))
|
|
return
|
|
var/obj/item/stack/rods/R = W
|
|
user.visible_message(span_notice("[user] rebuilds the broken grille."), \
|
|
span_notice("You rebuild the broken grille."))
|
|
repair_grille()
|
|
R.use(1)
|
|
return TRUE
|
|
|
|
//window placing begin
|
|
else if(is_glass_sheet(W) || istype(W, /obj/item/stack/sheet/bronze))
|
|
if (!broken)
|
|
var/obj/item/stack/ST = W
|
|
if (ST.get_amount() < 2)
|
|
to_chat(user, span_warning("You need at least two sheets of glass for that!"))
|
|
return
|
|
var/dir_to_set = SOUTHWEST
|
|
if(!anchored)
|
|
to_chat(user, span_warning("[src] needs to be fastened to the floor first!"))
|
|
return
|
|
for(var/obj/structure/window/WINDOW in loc)
|
|
to_chat(user, span_warning("There is already a window there!"))
|
|
return
|
|
if(!clear_tile(user))
|
|
return
|
|
to_chat(user, span_notice("You start placing the window..."))
|
|
if(do_after(user,20, target = src))
|
|
if(!src.loc || !anchored) //Grille broken or unanchored while waiting
|
|
return
|
|
for(var/obj/structure/window/WINDOW in loc) //Another window already installed on grille
|
|
return
|
|
if(!clear_tile(user))
|
|
return
|
|
var/obj/structure/window/WD
|
|
if(istype(W, /obj/item/stack/sheet/plasmarglass))
|
|
WD = new/obj/structure/window/reinforced/plasma/fulltile(drop_location()) //reinforced plasma window
|
|
else if(istype(W, /obj/item/stack/sheet/plasmaglass))
|
|
WD = new/obj/structure/window/plasma/fulltile(drop_location()) //plasma window
|
|
else if(istype(W, /obj/item/stack/sheet/rglass))
|
|
WD = new/obj/structure/window/reinforced/fulltile(drop_location()) //reinforced window
|
|
else if(istype(W, /obj/item/stack/sheet/titaniumglass))
|
|
WD = new/obj/structure/window/reinforced/shuttle(drop_location())
|
|
else if(istype(W, /obj/item/stack/sheet/plastitaniumglass))
|
|
WD = new/obj/structure/window/reinforced/plasma/plastitanium(drop_location())
|
|
else if(istype(W, /obj/item/stack/sheet/bronze))
|
|
WD = new/obj/structure/window/bronze/fulltile(drop_location())
|
|
else
|
|
WD = new/obj/structure/window/fulltile(drop_location()) //normal window
|
|
WD.setDir(dir_to_set)
|
|
WD.set_anchored(FALSE)
|
|
WD.state = 0
|
|
ST.use(2)
|
|
to_chat(user, span_notice("You place [WD] on [src]."))
|
|
return
|
|
//window placing end
|
|
|
|
else if(istype(W, /obj/item/shard) || !shock(user, 70))
|
|
return ..()
|
|
|
|
/obj/structure/grille/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
|
switch(damage_type)
|
|
if(BRUTE)
|
|
if(damage_amount)
|
|
playsound(src, 'sound/effects/grillehit.ogg', 80, TRUE)
|
|
else
|
|
playsound(src, 'sound/weapons/tap.ogg', 50, TRUE)
|
|
if(BURN)
|
|
playsound(src, 'sound/items/welder.ogg', 80, TRUE)
|
|
|
|
|
|
/obj/structure/grille/deconstruct(disassembled = TRUE)
|
|
if(!loc) //if already qdel'd somehow, we do nothing
|
|
return
|
|
if(!(flags_1&NODECONSTRUCT_1))
|
|
var/obj/R = new rods_type(drop_location(), rods_amount)
|
|
transfer_fingerprints_to(R)
|
|
qdel(src)
|
|
..()
|
|
|
|
/obj/structure/grille/atom_break()
|
|
. = ..()
|
|
if(!broken && !(flags_1 & NODECONSTRUCT_1))
|
|
icon_state = "brokengrille"
|
|
set_density(FALSE)
|
|
atom_integrity = 20
|
|
broken = TRUE
|
|
rods_amount = 1
|
|
rods_broken = FALSE
|
|
var/obj/R = new rods_type(drop_location(), rods_broken)
|
|
transfer_fingerprints_to(R)
|
|
|
|
/obj/structure/grille/proc/repair_grille()
|
|
if(broken)
|
|
icon_state = "grille"
|
|
set_density(TRUE)
|
|
atom_integrity = max_integrity
|
|
broken = FALSE
|
|
rods_amount = 2
|
|
rods_broken = TRUE
|
|
return TRUE
|
|
return FALSE
|
|
|
|
// shock user with probability prb (if all connections & power are working)
|
|
// returns 1 if shocked, 0 otherwise
|
|
|
|
/obj/structure/grille/proc/shock(mob/user, prb)
|
|
if(!anchored || broken) // anchored/broken grilles are never connected
|
|
return FALSE
|
|
if(!prob(prb))
|
|
return FALSE
|
|
if(!in_range(src, user))//To prevent TK and mech users from getting shocked
|
|
return FALSE
|
|
var/turf/T = get_turf(src)
|
|
var/obj/structure/cable/C = T.get_cable_node()
|
|
if(C)
|
|
if(electrocute_mob(user, C, src, 1, TRUE))
|
|
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
|
s.set_up(3, 1, src)
|
|
s.start()
|
|
return TRUE
|
|
else
|
|
return FALSE
|
|
return FALSE
|
|
|
|
/obj/structure/grille/should_atmos_process(datum/gas_mixture/air, exposed_temperature)
|
|
return exposed_temperature > T0C + 1500 && !broken
|
|
|
|
/obj/structure/grille/atmos_expose(datum/gas_mixture/air, exposed_temperature)
|
|
take_damage(1, BURN, 0, 0)
|
|
|
|
/obj/structure/grille/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
|
if(isobj(AM))
|
|
if(prob(50) && anchored && !broken)
|
|
var/obj/O = AM
|
|
if(O.throwforce != 0)//don't want to let people spam tesla bolts, this way it will break after time
|
|
var/turf/T = get_turf(src)
|
|
var/obj/structure/cable/C = T.get_cable_node()
|
|
if(C)
|
|
playsound(src, 'sound/magic/lightningshock.ogg', 100, TRUE, extrarange = 5)
|
|
tesla_zap(src, 3, C.newavail() * 0.01, ZAP_MOB_DAMAGE | ZAP_OBJ_DAMAGE | ZAP_MOB_STUN | ZAP_LOW_POWER_GEN | ZAP_ALLOW_DUPLICATES) //Zap for 1/100 of the amount of power. At a million watts in the grid, it will be as powerful as a tesla revolver shot.
|
|
C.add_delayedload(C.newavail() * 0.0375) // you can gain up to 3.5 via the 4x upgrades power is halved by the pole so thats 2x then 1X then .5X for 3.5x the 3 bounces shock.
|
|
return ..()
|
|
|
|
/obj/structure/grille/get_dumping_location()
|
|
return null
|
|
|
|
/obj/structure/grille/broken // Pre-broken grilles for map placement
|
|
icon_state = "brokengrille"
|
|
density = FALSE
|
|
broken = TRUE
|
|
rods_amount = 1
|
|
rods_broken = FALSE
|
|
|
|
/obj/structure/grille/broken/Initialize(mapload)
|
|
. = ..()
|
|
take_damage(max_integrity * 0.6)
|