Files
Cody Brittain 3f62424312 [MDB Ignore] [IDB Ignore] Kills off /obj/item/device (#21774)
This has zero reason to exist in our code base. We have no procs or
variables tied to this. I removed it to make future modifications
cleaner.

---------

Signed-off-by: Cody Brittain <1779662+Generalcamo@users.noreply.github.com>
2026-02-01 05:14:26 +00:00

518 lines
14 KiB
Plaintext

/obj/item/landmine
name = "land mine"
desc = "An anti-personnel explosive device used for area denial."
icon = 'icons/obj/item/landmine/mine.dmi'
icon_state = "landmine"
throwforce = 0
var/deployed = FALSE
/// Add wire to re-activate
var/deactivated = FALSE
/obj/item/landmine/Initialize()
. = ..()
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
)
AddElement(/datum/element/connect_loc, loc_connections)
/obj/item/landmine/update_icon()
..()
if(!deployed)
icon_state = "[initial(icon_state)]"
else
icon_state = "[initial(icon_state)]_on"
/obj/item/landmine/verb/hide_under()
set src in oview(1)
set name = "Hide"
set category = "Object"
if(use_check_and_message(usr, USE_DISALLOW_SILICONS))
return
layer = ABOVE_TILE_LAYER
to_chat(usr, SPAN_NOTICE("You hide \the [src]."))
/obj/item/landmine/attack_self(mob/user)
..()
if(deactivated)
to_chat(user, SPAN_WARNING("\The [src] is deactivated and needs specific rewiring!"))
return
if(!deployed && !use_check(user, USE_DISALLOW_SILICONS))
user.visible_message(
SPAN_DANGER("[user] starts to deploy \the [src]."),
SPAN_DANGER("You begin deploying \the [src]!")
)
if (do_after(user, 6 SECONDS, do_flags = DO_REPAIR_CONSTRUCT))
user.visible_message(
SPAN_DANGER("[user] has deployed \the [src]."),
SPAN_DANGER("You have deployed \the [src]!")
)
deploy(user)
/**
* Called when a landmine is deployed
*
* * deployer - The `/mob` that deployed the mine
*/
/obj/item/landmine/proc/deploy(mob/deployer)
SHOULD_CALL_PARENT(TRUE)
SHOULD_NOT_SLEEP(TRUE)
src.deployed = TRUE
deployer.drop_from_inventory(src)
update_icon()
src.anchored = TRUE
add_fingerprint(deployer)
add_fibers(deployer)
/**
* Called when a landmine was triggered, and is supposed to explode
*
* * triggerer - The `/mob/living` that triggered the mine
*/
/obj/item/landmine/proc/trigger(mob/living/triggerer)
spark(src, 3, GLOB.alldirs)
if(ishuman(triggerer))
triggerer.Weaken(2)
explosion(loc, 0, 2, 2, 3)
qdel(src)
/obj/item/landmine/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
SIGNAL_HANDLER
if(deployed)
if(ishuman(arrived))
var/mob/living/carbon/human/H = arrived
if(H.shoes?.item_flags & ITEM_FLAG_LIGHT_STEP)
return
if(isliving(arrived))
var/mob/living/L = arrived
if(L.pass_flags & PASSTABLE)
return
if(L.mob_size >= 5)
L.visible_message(
SPAN_DANGER("[L] steps on \the [src]."),
SPAN_DANGER("You step on \the [src]!"),
SPAN_DANGER("You hear a mechanical click!")
)
trigger(L)
/obj/item/landmine/attack_hand(mob/user as mob)
if(deployed && !use_check(user, USE_DISALLOW_SILICONS))
attack_hand_trigger(user)
else
..()
/**
* Called when the attack_hand is supposed to trigger the mine
*
* * user - The `/mob` that attacked the mine
*/
/obj/item/landmine/proc/attack_hand_trigger(mob/user)
user.visible_message(
SPAN_DANGER("[user] triggers \the [src]."),
SPAN_DANGER("You trigger \the [src]!"),
SPAN_DANGER("You hear a mechanical click!")
)
trigger(user)
/**
* Activates the landmine, arming it
*
* NOT the same as deploying it, which is putting it on the ground
*
* * user - The `/mob` that activated the mine
*/
/obj/item/landmine/proc/activate(mob/user)
SHOULD_NOT_SLEEP(TRUE)
src.deactivated = FALSE
/**
* Deactivates the landmine, disarming it
*
* NOT the same as removing it from the ground
*
* * user - The `/mob` that activated the mine
*/
/obj/item/landmine/proc/deactivate(mob/user)
SHOULD_NOT_SLEEP(TRUE)
src.deactivated = TRUE
/obj/item/landmine/attackby(obj/item/attacking_item, mob/user)
..()
if(deactivated && istype(attacking_item, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = attacking_item
if(C.use(1))
to_chat(user, SPAN_NOTICE("You start carefully start rewiring \the [src]."))
if(do_after(user, 10 SECONDS, do_flags = DO_REPAIR_CONSTRUCT))
to_chat(user, SPAN_NOTICE("You successfully rewire \the [src], priming it for use."))
activate(user)
return
else
to_chat(user, SPAN_WARNING("There's not enough cable to finish the task."))
return
else if(deployed && istype(attacking_item, /obj/item/wirecutters))
var/obj/item/wirecutters/W = attacking_item
user.visible_message(SPAN_WARNING("\The [user] starts snipping some wires in \the [src] with \the [W]..."), \
SPAN_NOTICE("You start snipping some wires in \the [src] with \the [W]..."))
if(attacking_item.use_tool(src, user, 150, volume = 50))
if(prob(W.bomb_defusal_chance))
to_chat(user, SPAN_NOTICE("You successfully defuse \the [src], though it's missing some essential wiring now."))
deactivate(user)
anchored = FALSE
deployed = FALSE
update_icon()
return
to_chat(user, FONT_LARGE(SPAN_DANGER("You slip, snipping the wrong wire!")))
trigger(user)
else if(attacking_item.force > 10 && deployed)
trigger(user)
/obj/item/landmine/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
. = ..()
if(. != BULLET_ACT_HIT)
return .
if(deployed)
trigger()
/obj/item/landmine/ex_act(var/severity = 2.0)
if(deployed)
trigger()
/*
##################
Subtypes
##################
*/
/**
* # Fragmentation Landmine
*
* A landmine that throws sharpnels around
*/
/obj/item/landmine/frag
var/num_fragments = 15
var/fragment_damage = 10
var/damage_step = 2
var/explosion_size = 3
var/spread_range = 7
/obj/item/landmine/frag/deployed
deployed = TRUE
/obj/item/landmine/frag/trigger(mob/living/triggerer)
spark(src, 3, GLOB.alldirs)
fragem(src,num_fragments,num_fragments,explosion_size,explosion_size+1,fragment_damage,damage_step,TRUE)
qdel(src)
/**
* # Door Rigging Landmine
*
* A landmine that will explode when the door it is attached to opens
*/
/obj/item/landmine/frag/door_rigging
name = "door rigging landmine"
fragment_damage = 10
///The airlock that we are observing for when it opens, to explode
var/obj/machinery/door/airlock/door_rigged
//Prevent this mine to be used like a normal one
/obj/item/landmine/frag/door_rigging/attack_self(mob/user)
to_chat(user, SPAN_ALERT("This landmine is not usable in this way, you need to apply it to a door."))
return
/obj/item/landmine/frag/door_rigging/resolve_attackby(atom/A, mob/user, click_parameters)
. = ..()
if(istype(A, /obj/machinery/door/airlock))
door_rigged = A
var/turf/turf_under_door = get_turf(door_rigged)
//Prevent people from exploding themselves by targeting a door that will open once clicked
if(!door_rigged.welded || !door_rigged.density || !istype(turf_under_door) || locate(/obj/item/landmine) in turf_under_door)
to_chat(user, SPAN_WARNING("The door is not welded, is open, is already rigged or does not have a turf below it."))
door_rigged = null //Clean up the var
return
//Take a little to do this
if(!do_after(user, 10 SECONDS, door_rigged))
door_rigged = null
return
RegisterSignal(door_rigged, COMSIG_QDELETING, PROC_REF(handle_door_qdel))
deploy(user)
src.forceMove(turf_under_door)
activate(user)
START_PROCESSING(SSfast_process, src)
/obj/item/landmine/frag/door_rigging/deactivate(mob/user)
STOP_PROCESSING(SSfast_process, src)
door_rigged = null
. = ..()
/obj/item/landmine/frag/door_rigging/process(seconds_per_tick)
if(QDELETED(door_rigged))
STOP_PROCESSING(SSfast_process, src)
qdel(src)
//If the door isn't dense, it means it is open, explode
if(!door_rigged.density)
STOP_PROCESSING(SSfast_process, src)
trigger(null)
///Clear the reference and delete the mine if the door gets deleted
/obj/item/landmine/frag/door_rigging/proc/handle_door_qdel()
SIGNAL_HANDLER
door_rigged = null
STOP_PROCESSING(SSfast_process, src)
qdel(src)
/**
* # Radiation Landmine
*
* A landmine that irradiates the victim
*/
/obj/item/landmine/radiation
icon_state = "radlandmine"
/obj/item/landmine/radiation/trigger(mob/living/L)
spark(src, 3, GLOB.alldirs)
if(L)
if(ishuman(L))
var/mob/living/carbon/human/H = L
H.apply_radiation(50)
qdel(src)
/**
* # Phoron Landmine
*
* A landmine that releases phoron
*/
/obj/item/landmine/phoron
icon_state = "phoronlandmine"
/obj/item/landmine/phoron/deployed
deployed = TRUE
/obj/item/landmine/phoron/trigger(mob/living/triggerer)
spark(src, 3, GLOB.alldirs)
for (var/turf/simulated/floor/target in range(1,src))
if(!target.blocks_air)
target.assume_gas(GAS_PHORON, 30)
target.hotspot_expose(1000, CELL_VOLUME)
qdel(src)
/**
* # Nitrous Oxide Landmine
*
* A landmine that releases nitrous oxide
*/
/obj/item/landmine/n2o
icon_state = "phoronlandmine"
/obj/item/landmine/n2o/deployed
deployed = TRUE
/obj/item/landmine/n2o/trigger(mob/living/L)
spark(src, 3, GLOB.alldirs)
for (var/turf/simulated/floor/target in range(1,src))
if(!target.blocks_air)
target.assume_gas(GAS_N2O, 30)
qdel(src)
/**
* # EMP Landmine
*
* A landmine that emits an EMP pulse
*/
/obj/item/landmine/emp
icon_state = "emplandmine"
/obj/item/landmine/emp/deployed
deployed = TRUE
/obj/item/landmine/emp/trigger(mob/living/triggerer)
spark(src, 3, GLOB.alldirs)
empulse(src.loc, 2, 4)
qdel(src)
/**
* # Phoron Landmine
*
* A landmine that only explodes when pressure is released
*/
/obj/item/landmine/standstill
name = "Standstill Landmine"
desc = "A landmine that only triggers if you release the pressure from the trigger."
icon_state = "standstill"
var/engaged_by = null
/obj/item/landmine/standstill/Initialize()
. = ..()
var/static/list/loc_connections = list(
COMSIG_ATOM_EXITED = PROC_REF(on_exited),
)
AddElement(/datum/element/connect_loc, loc_connections)
/obj/item/landmine/standstill/Destroy()
STOP_PROCESSING(SSfast_process, src)
engaged_by = null
. = ..()
/obj/item/landmine/standstill/trigger(mob/living/triggerer)
if(!engaged_by && !deactivated)
to_chat(triggerer, SPAN_HIGHDANGER("Something clicks below your feet, a sense of dread permeates your skin, better not move..."))
engaged_by = REF(triggerer)
//Because mobs can bump and swap with one another, and we use forcemove that doesn't call Crossed/Uncrossed/Entered/Exited, we have to
//keep looking if the victim is still on the mine, and otherwise explode the mine
START_PROCESSING(SSfast_process, src)
INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(tgui_alert), triggerer, "You feel your [pick("right", "left")] foot step down on a button with a click..., Uh..., Oh...", "Dread", list("Mom..."))
playsound(src, sound('sound/weapons/empty/empty6.ogg'), 50)
else
late_trigger(locate(engaged_by))
/obj/item/landmine/standstill/proc/on_exited(datum/source, atom/movable/gone, direction)
SIGNAL_HANDLER
//Oh no...
if(engaged_by && gone == locate(engaged_by))
var/mob/living/victim = gone
to_chat(victim, SPAN_HIGHDANGER("The mine clicks below your feet."))
addtimer(CALLBACK(src, PROC_REF(late_trigger), victim), 1 SECONDS)
/obj/item/landmine/standstill/process()
if(!engaged_by || deactivated)
STOP_PROCESSING(SSfast_process, src)
return
var/mob/living/victim = locate(engaged_by)
var/turf/our_turf = get_turf(src)
if(!(victim in our_turf))
late_trigger(locate(engaged_by))
/**
* Called when the actual explosion needs to be performed
*
* * victim - The `/mob` that triggers the explosion
*/
/obj/item/landmine/standstill/proc/late_trigger(mob/living/victim)
if(!deactivated)
for(var/mob/living/person_in_range in get_hearers_in_LOS(world.view, src))
to_chat(person_in_range, SPAN_HIGHDANGER("[victim] does a sudden move, releasing the feet from the trigger..."))
explosion(loc, 2, 3, 5, world.view)
qdel(src)
/obj/item/landmine/standstill/deactivate(mob/user)
src.engaged_by = null
. = ..()
/obj/item/landmine/standstill/attackby(obj/item/attacking_item, mob/user)
if(engaged_by && (user == locate(engaged_by)))
to_chat(user, SPAN_ALERT("You are unable to reach the mine without moving your foot, and you feel like doing so would not end well..."))
else
..()
/obj/item/landmine/standstill/attack_hand_trigger(mob/user)
if(!engaged_by)
return
late_trigger(locate(engaged_by))
/**
* # Claymore mine
*
* A landmine that projects sharpnels in a cone of explosion, towards one direction
*/
/obj/item/landmine/claymore
name = "Claymore Landmine"
desc = "A landmine that projects sharpnels in a cone of explosion, towards one direction."
desc_extended = "A household name, this mine finds extensive use amongst military forces due to its ability to provide area penetration denial and aid ambushes. \
It is narrated that Gadpathur, its largest manufacturer in modern times, have built more of these mines than the census of the core planets of the Solarian Alliance."
icon = 'icons/obj/item/landmine/claymore.dmi'
icon_state = "m20"
var/datum/wires/landmine/claymore/trigger_wire
var/obj/item/assembly/signaler/signaler
/obj/item/landmine/claymore/mechanics_hints(mob/user, distance, is_adjacent)
. += ..()
. += "This device can be fitted with a signaler device for remotely actuated detonations, or can be activated with the press of a button directly above it."
/obj/item/landmine/claymore/Initialize(mapload, ...)
. = ..()
trigger_wire = new(src)
/obj/item/landmine/claymore/Destroy()
trigger_wire.holder = null
QDEL_NULL(trigger_wire)
QDEL_NULL(signaler)
. = ..()
/obj/item/landmine/claymore/update_icon()
icon_state = (src.deployed) ? "[initial(icon_state)]_active" : initial(icon_state)
/obj/item/landmine/claymore/attackby(obj/item/attacking_item, mob/user)
if(istype(attacking_item, /obj/item/assembly/signaler))
if(!isnull(signaler))
to_chat(user, SPAN_NOTICE("There is already a signaler inserted in \the [src]."))
return
signaler = attacking_item
user.drop_from_inventory(attacking_item, src)
trigger_wire.attach_assembly(WIRE_EXPLODE, signaler)
else
. = ..()
/obj/item/landmine/claymore/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
return //Does nothing with mere crossing over
/obj/item/landmine/claymore/deploy(mob/deployer)
. = ..()
src.dir = deployer.dir
#define SHOTS_TO_LAUNCH 20
/obj/item/landmine/claymore/trigger(mob/living/triggerer)
if(deactivated || !deployed)
return
var/list/turf/candidate_turfs = get_turfs_in_cone(get_turf(src), dir2angle(src.dir), world.view, 60)
for(var/i = 0; i < SHOTS_TO_LAUNCH; i++)
var/turf/to_hit = pick(candidate_turfs)
var/obj/projectile/bullet/pellet/shotgun/pellet = new(get_turf(src))
pellet.fire(get_angle(get_turf(src), to_hit))
qdel(src)
#undef SHOTS_TO_LAUNCH