Aurora: Vietnam Edition (#17859)

* standstill landmine

* more

* fsdfsa

* cl

* sdaf

* Apply suggestions from code review

Co-authored-by: Matt Atlas <mattiathebest2000@hotmail.it>

* sadsdf

* sdaf

* sdaf

---------

Co-authored-by: Matt Atlas <mattiathebest2000@hotmail.it>
This commit is contained in:
Fluffy
2023-12-09 21:28:54 +00:00
committed by GitHub
co-authored by Matt Atlas
parent bed6bc3d73
commit df03176859
21 changed files with 643 additions and 49 deletions
+8 -3
View File
@@ -64,8 +64,13 @@ Then check if it's true, if true return. This will stop the normal menu appearin
name = "hidden uplink"
desc = "There is something wrong if you're examining this."
var/active = 0
var/datum/uplink_category/category = 0 // The current category we are in
var/exploit_id // Id of the current exploit record we are viewing
/// The current category we are in, the open category
var/datum/uplink_category/category
/// ID of the current exploit record we are viewing
var/exploit_id
var/pda_code = ""
@@ -179,7 +184,7 @@ Then check if it's true, if true return. This will stop the normal menu appearin
tgui_data["items"] = items
else if(tgui_menu == 1)
var/items[0]
for(var/datum/uplink_item/item in category.items)
for(var/datum/uplink_item/item in category?.items)
if(item.can_view(src))
items[++items.len] = new_tgui_item_data(item)
tgui_data["items"] = items
+13 -10
View File
@@ -22,7 +22,6 @@
var/throw_amount = 100
var/lit = FALSE //on or off
var/operating = FALSE //cooldown
var/turf/previous_turf = null
var/obj/item/weldingtool/welding_tool = null
var/obj/item/device/assembly/igniter/igniter = null
var/obj/item/tank/gas_tank = null
@@ -100,7 +99,7 @@
if(user && user.get_active_hand() == src)
var/turf/target_turf = get_turf(target)
if(target_turf)
var/turflist = getline(user, target_turf)
var/turflist = get_turfs_in_cone(user, Get_Angle(user, target_turf), get_dist(user, target_turf), 30)
flame_turf(turflist)
/obj/item/flamethrower/attackby(obj/item/W, mob/user)
@@ -233,18 +232,22 @@
/obj/item/flamethrower/proc/flame_turf(turflist)
if(!lit || operating)
return
operating = TRUE
for(var/turf/T in turflist)
var/turf/operator_turf = get_turf(src)
for(var/turf/T in (turflist - operator_turf))
if(T.density || istype(T, /turf/space))
break
if(!previous_turf && length(turflist)>1)
previous_turf = get_turf(src)
continue //so we don't burn the tile we be standin on
if(previous_turf && LinkBlocked(previous_turf, T))
break
continue
if(LinkBlocked(operator_turf, T))
continue
ignite_turf(T)
sleep(1)
previous_turf = null
operating = FALSE
@@ -0,0 +1,12 @@
/obj/item/grenade/napalm
name = "napalm grenade"
desc = "A grenade that delivers napalm, not as classy as an airstrike bomb, but still effective."
desc_extended = "A Necropolis Industries (now known as Zavodskoi Interstellar) engineered device, this grenade is one of the most effective and destructive portable emergency sterilization \
device available, causing high-intensity sustained fires at over 2000K."
desc_antag = "This causes a 5-tiles large fire that burns for quite a while, don't be a dick with it."
/obj/item/grenade/napalm/prime()
. = ..()
for(var/turf/turf in view(5, src))
new /obj/effect/decal/cleanable/liquid_fuel/napalm(turf, 100, TRUE)
+250 -24
View File
@@ -1,7 +1,7 @@
/obj/item/landmine
name = "land mine"
desc = "An anti-personnel explosive device used for area denial."
icon = 'icons/obj/grenade.dmi'
icon = 'icons/obj/item/landmine/mine.dmi'
icon_state = "landmine"
throwforce = 0
var/deployed = FALSE
@@ -10,9 +10,9 @@
/obj/item/landmine/update_icon()
..()
if(!deployed)
icon_state = "[icon_state]"
icon_state = "[initial(icon_state)]"
else
icon_state = "[icon_state]_on"
icon_state = "[initial(icon_state)]_on"
/obj/item/landmine/verb/hide_under()
set src in oview(1)
@@ -37,21 +37,37 @@
"<span class='danger'>You begin deploying \the [src]!</span>"
)
if (do_after(user, 6 SECONDS, DO_REPAIR_CONSTRUCT))
if (do_after(user, 6 SECONDS, do_flags = DO_REPAIR_CONSTRUCT))
user.visible_message(
"<span class='danger'>[user] has deployed \the [src].</span>",
"<span class='danger'>You have deployed \the [src]!</span>"
)
deployed = TRUE
user.drop_from_inventory(src)
update_icon()
anchored = TRUE
deploy(user)
/obj/item/landmine/proc/trigger(mob/living/L)
/**
* 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
/**
* 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, alldirs)
if(ishuman(L))
L.Weaken(2)
if(ishuman(triggerer))
triggerer.Weaken(2)
explosion(loc, 0, 2, 2, 3)
qdel(src)
@@ -75,24 +91,56 @@
/obj/item/landmine/attack_hand(mob/user as mob)
if(deployed && !use_check(user, USE_DISALLOW_SILICONS))
user.visible_message(
"<span class='danger'>[user] triggers \the [src].</span>",
"<span class='danger'>You trigger \the [src]!</span>",
"<span class='danger'>You hear a mechanical click!</span>"
)
trigger(user)
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/I, mob/user)
..()
if(deactivated && istype(I, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = I
if(C.use(1))
to_chat(user, SPAN_NOTICE("You start carefully start rewiring \the [src]."))
if(do_after(user, 10 SECONDS, src, DO_REPAIR_CONSTRUCT))
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."))
deactivated = FALSE
activate(user)
return
else
to_chat(user, SPAN_WARNING("There's not enough cable to finish the task."))
@@ -104,7 +152,7 @@
if(I.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."))
deactivated = TRUE
deactivate(user)
anchored = FALSE
deployed = FALSE
update_icon()
@@ -122,8 +170,17 @@
if(deployed)
trigger()
//landmines that do more than explode
/*
##################
Subtypes
##################
*/
/**
* # Fragmentation Landmine
*
* A landmine that throws sharpnels around
*/
/obj/item/landmine/frag
var/num_fragments = 15
var/fragment_damage = 10
@@ -131,11 +188,16 @@
var/explosion_size = 3
var/spread_range = 7
/obj/item/landmine/frag/trigger(mob/living/L)
/obj/item/landmine/frag/trigger(mob/living/triggerer)
spark(src, 3, alldirs)
fragem(src,num_fragments,num_fragments,explosion_size,explosion_size+1,fragment_damage,damage_step,TRUE)
qdel(src)
/**
* # Radiation Landmine
*
* A landmine that irradiates the victim
*/
/obj/item/landmine/radiation
icon_state = "radlandmine"
@@ -147,10 +209,15 @@
H.apply_radiation(50)
qdel(src)
/**
* # Phoron Landmine
*
* A landmine that releases phoron
*/
/obj/item/landmine/phoron
icon_state = "phoronlandmine"
/obj/item/landmine/phoron/trigger(mob/living/L)
/obj/item/landmine/phoron/trigger(mob/living/triggerer)
spark(src, 3, alldirs)
for (var/turf/simulated/floor/target in range(1,src))
if(!target.blocks_air)
@@ -160,6 +227,11 @@
qdel(src)
/**
* # Nitrous Oxide Landmine
*
* A landmine that releases nitrous oxide
*/
/obj/item/landmine/n2o
icon_state = "phoronlandmine"
@@ -171,10 +243,164 @@
qdel(src)
/**
* # EMP Landmine
*
* A landmine that emits an EMP pulse
*/
/obj/item/landmine/emp
icon_state = "emplandmine"
/obj/item/landmine/emp/trigger(mob/living/L)
/obj/item/landmine/emp/trigger(mob/living/triggerer)
spark(src, 3, 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/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_allinrange(src, sound('sound/weapons/empty/empty6.ogg'))
else
late_trigger(locate(engaged_by))
/obj/item/landmine/standstill/Uncrossed(O)
. = ..()
//Oh no...
if(engaged_by && O == locate(engaged_by))
var/mob/living/victim = O
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, 5, 7, world.view)
qdel(src)
/obj/item/landmine/standstill/deactivate(mob/user)
src.engaged_by = null
. = ..()
/obj/item/landmine/standstill/attackby(obj/item/I, 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."
desc_info = "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."
icon = 'icons/obj/item/landmine/claymore.dmi'
icon_state = "m20"
var/datum/wires/landmine/claymore/trigger_wire
var/obj/item/device/assembly/signaler/signaler
/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/I, mob/user)
if(istype(I, /obj/item/device/assembly/signaler))
if(!isnull(signaler))
to_chat(user, SPAN_NOTICE("There is already a signaler inserted in \the [src]."))
return
signaler = I
user.drop_from_inventory(I, src)
trigger_wire.Attach("red", signaler)
else
. = ..()
/obj/item/landmine/claymore/Crossed(AM, ignore_deployment)
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/item/projectile/bullet/pellet/shotgun/pellet = new(get_turf(src))
pellet.fire(Get_Angle(get_turf(src), to_hit))
qdel(src)
#undef SHOTS_TO_LAUNCH
@@ -489,6 +489,14 @@
illustration = "grenade"
starts_with = list(/obj/item/grenade/frag = 5)
/obj/item/storage/box/grenades/napalm
name = "box of napalm grenades"
desc = "A box containing 3 napalm grenades."
icon_state = "secbox"
item_state = "secbox"
illustration = "grenade"
starts_with = list(/obj/item/grenade/napalm = 3)
/obj/item/storage/box/cardox
name = "box of cardox grenades"
desc = "A box containing 5 experimental cardox grenades."
@@ -1238,3 +1246,20 @@
/obj/item/storage/box/led_collars/fill()
..()
make_exact_fit()
/obj/item/storage/box/traps/punji
name = "box of punji traps"
desc = "A box containing 5 punji traps."
starts_with = list(/obj/item/trap/punji = 5)
/obj/item/storage/box/landmines/standstill
name = "box of standstill landmines"
desc = "A box containing 5 standstill landmines."
starts_with = list(/obj/item/landmine/standstill = 5)
/obj/item/storage/box/landmines/claymore
name = "box of claymore landmines"
desc = "A box containing 5 claymore landmines, relative detonators, and a spare one to trigger them all."
starts_with = list(
/obj/item/landmine/claymore = 5,
/obj/item/device/assembly/signaler = 6
)
+149 -3
View File
@@ -4,7 +4,7 @@
throw_speed = 2
throw_range = 1
gender = PLURAL
icon = 'icons/obj/item/traps.dmi'
icon = 'icons/obj/item/traps/traps.dmi'
var/icon_base = "beartrap"
icon_state = "beartrap0"
randpixel = 0
@@ -136,11 +136,28 @@
/obj/item/trap/update_icon()
icon_state = "[icon_base][deployed]"
/*
##################
Subtypes
##################
*/
/**
* # Sharpened trap
*
* This device has an even higher chance of penetrating armor and locking foes in place
*/
/obj/item/trap/sharpened
name = "sharpened mechanical trap"
desc_antag = "This device has an even higher chance of penetrating armor and locking foes in place."
activated_armor_penetration = 100
/**
* # Animal trap
*
* Used to catch small animals like rats, lizards, and chicks
*/
/obj/item/trap/animal
name = "small trap"
desc = "A small mechanical trap that's used to catch small animals like rats, lizards, and chicks."
@@ -506,6 +523,11 @@
/obj/item/trap/animal/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
return TRUE
/**
* # Animal trap (Medium)
*
* Used to catch medium animals like cats, monkeys, nymphs, and wayward maintenance drones
*/
/obj/item/trap/animal/medium
name = "medium trap"
desc = "A medium mechanical trap that is used to catch moderately-sized animals like cats, monkeys, nymphs, and wayward maintenance drones."
@@ -527,6 +549,11 @@
/mob/living/simple_animal/chicken, /mob/living/simple_animal/yithian, /mob/living/carbon/alien/diona, /mob/living/silicon/robot/drone, /mob/living/silicon/pai,
/mob/living/simple_animal/spiderbot, /mob/living/simple_animal/hostile/tree)
/**
* # Animal trap (Large)
*
* Used to catch larger animals, from spiders and dogs to bears and even larger mammals
*/
/obj/item/trap/animal/large
name = "large trap"
desc = "A large mechanical trap that is used to catch larger animals, from spiders and dogs to bears and even larger mammals."
@@ -613,7 +640,7 @@
/obj/item/large_trap_foundation
name = "large trap foundation"
desc = "A metal foundation for large trap, it is missing metals rods to hold the prey."
icon = 'icons/obj/item/traps.dmi'
icon = 'icons/obj/item/traps/traps.dmi'
icon_state = "large_foundation"
throwforce = 4
force = 5
@@ -641,7 +668,11 @@
else
..()
/**
* # Tripwire trap
*
* A trap that makes you fall over
*/
/obj/item/trap/tripwire
name = "tripwire trap"
desc = "A piece of cable coil strung between two metal rods. Low-tech, but reliable."
@@ -689,3 +720,118 @@
if(!L.lying && (L.m_intent == M_RUN) || prob(5))
L.visible_message(SPAN_DANGER("\The [L] trips over \the [src]!"), FONT_LARGE(SPAN_DANGER("You trip over \the [src]!")))
L.Weaken(3)
/**
* # Punji trap
*
* A trap that damages and gives an infection to the victim, can have a message attached
*/
/obj/item/trap/punji
name = "punji trap"
desc = "An horrendous trap."
icon = 'icons/obj/item/traps/punji.dmi'
icon_base = "punji"
icon_state = "punji0"
var/message = null
/obj/item/trap/punji/Crossed(atom/movable/AM)
if(deployed && isliving(AM))
var/mob/living/L = AM
attack_mob(L)
update_icon()
/obj/item/trap/punji/attack_mob(mob/living/L)
//Reveal the trap, if not already visible
hide(FALSE)
//Select a target zone
var/target_zone
if(L.lying)
target_zone = pick(BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_L_HAND, BP_L_ARM, BP_R_HAND, BP_R_ARM)
else
target_zone = pick(BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG)
//Try to apply the damage
var/success = L.apply_damage(60, DAMAGE_BRUTE, target_zone, used_weapon = src, armor_pen = activated_armor_penetration)
//If successfully applied, give the message
if(success)
//Show the leftover message, if any, after a little
addtimer(CALLBACK(src, PROC_REF(reveal_message), L), 3 SECONDS)
//Give a simple message and return if it's not a human
if(!ishuman(L))
L.visible_message(SPAN_DANGER("You step on \the [src]!"))
return
var/mob/living/carbon/human/human = L
var/obj/item/organ/organ = human.get_organ(target_zone)
human.visible_message(SPAN_DANGER("\The [human] steps on \the [src]!"),
SPAN_WARNING(FONT_LARGE(SPAN_DANGER("You step on \the [src], feel your body fall, and something sharp penetrate your [organ.name]!"))),
SPAN_WARNING("<b>You feel your body fall, and something sharp penetrate your [organ.name]!</b>"))
//If it's a human and not an IPC, apply an infection
//We are returning early before this step in case something isn't a human, so this should be fine not to catch borgs/bot/exosuits/whatever
if(!isipc(L))
//If it's a Vaurca, there's a chance the spear wouldn't go in deep enough to apply an infection
//You're still damaged by falling on it though, which happens above, but at least you're spared the infection
//Glory to your carapace
if(isvaurca(L) && prob(50))
return
organ.germ_level += INFECTION_LEVEL_THREE
//Add some fertilizer to poison the target whole, not only the external organ (leg/foot)
L.reagents.add_reagent(/singleton/reagent/toxin/fertilizer, 10)
/obj/item/trap/punji/proc/reveal_message(mob/living/victim)
if(!message)
return
//If the mob moved away and/or no longer sees the trap, do not show the message
if(!(src in oview(world.view, victim)))
return
victim.visible_message(SPAN_ALERT("You notice something written on a plate inside the trap: <br>")+SPAN_BAD(message))
/obj/item/trap/punji/examine(mob/user, distance)
. = ..()
if(src.message && distance < 3)
to_chat(user, SPAN_ALERT("You notice something written on a plate inside the trap: <br>")+SPAN_BAD(message))
/obj/item/trap/punji/verb/hide_under()
set src in oview(1)
set name = "Hide"
set desc = "Hide the trap under the cover."
set category = "Object"
if(use_check_and_message(usr, USE_DISALLOW_SILICONS))
return
to_chat(usr, SPAN_NOTICE("You begin hiding the trap..."))
if(!do_after(usr, 15 SECONDS))
return
hide(TRUE)
to_chat(usr, SPAN_ALERT("You hide \the [src], remember where you left it or suffer the very same warcrime you wanted to inflict!"))
/obj/item/trap/punji/verb/set_message()
set src in oview(1)
set name = "Set Message"
set desc = "Set a message for the victim of the trap."
set category = "Object"
if(src.message)
to_chat(usr, SPAN_NOTICE("There is already a carved message inside the trap, can't make more..."))
return
var/added_message = tgui_input_text(usr, "Leave your message here...", "Punji trap message", multiline = TRUE, encode = FALSE)
if(added_message)
to_chat(usr, SPAN_NOTICE("You begin carving the message inside the trap..."))
if(do_after(usr, 10 SECONDS))
src.message = strip_html_readd_newlines(added_message)