mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 21:18:37 +01:00
## About The Pull Request Fixes #94778 There are a bunch of places where we dismember a limb (or head) and then do something with it assuming that we actually dismembered it, but that isn't actually true. Many of these places then move your not-actually-dismembered head somewhere else. If you have an unremovable limb (such as if you have TRAIT_NODISMEMBER) this means that it actually gets removed anyway because it's physically moved somewhere else. In all of these cases, if we failed to dismember the limb we should just leave it alone. I left anything where after dismembering the limb it immediately deletes it in though because those are generally supposed to be invariably fatal. ## Changelog 🆑 fix: Chainsaws can't behead people with unremovable heads. fix: You can only put your own head on a spear or into a box if it is possible to remove your head. fix: Heretic rifts can only remove your arms if your arms can be removed. fix: Paperwork can only cut off your head if your head can be cut off. fix: Smite being reflected can only blow off your arm if your arm can be removed. /🆑
196 lines
7.6 KiB
Plaintext
196 lines
7.6 KiB
Plaintext
/obj/item/grenade/flashbang
|
|
name = "flashbang"
|
|
icon_state = "flashbang"
|
|
inhand_icon_state = "flashbang"
|
|
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
|
|
possible_fuse_time = list("3", "4", "5")
|
|
//how many tiles away the mob will be affected by the flashbang.
|
|
var/flashbang_range = 7
|
|
//The devision for the sweetspot culations. if set to 1, the sweetspot is ostensibly the flashbang range.
|
|
var/sweetspot_divider = 3
|
|
//The light emitted by this flashbang to indicate the sweetspot.
|
|
var/flashbang_light = LIGHT_COLOR_INTENSE_RED
|
|
|
|
/obj/item/grenade/flashbang/apply_grenade_fantasy_bonuses(quality)
|
|
flashbang_range = modify_fantasy_variable("flashbang_range", flashbang_range, quality)
|
|
|
|
/obj/item/grenade/flashbang/remove_grenade_fantasy_bonuses(quality)
|
|
flashbang_range = reset_fantasy_variable("flashbang_range", flashbang_range)
|
|
|
|
/obj/item/grenade/flashbang/arm_grenade(mob/user, delayoverride, msg = TRUE, volume = 60)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
var/sweetspot_range = clamp(CEILING(flashbang_range/sweetspot_divider, 1), 0, flashbang_range)
|
|
set_light(sweetspot_range, sweetspot_range, flashbang_light)
|
|
|
|
/obj/item/grenade/flashbang/detonate(mob/living/lanced_by)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
update_mob()
|
|
var/turf/flashbang_turf = get_turf(src)
|
|
if(!flashbang_turf)
|
|
return
|
|
|
|
//Check that there's enough pressure on the detonation turf for the 'bang' part of the flashbang to work.
|
|
var/datum/gas_mixture/environment = flashbang_turf.return_air()
|
|
var/pressure = environment?.return_pressure()
|
|
var/soundbang = pressure >= SOUND_MINIMUM_PRESSURE
|
|
|
|
do_sparks(rand(5, 9), FALSE, src)
|
|
playsound(flashbang_turf, 'sound/items/weapons/flashbang.ogg', 100, TRUE, 8, 0.9)
|
|
new /obj/effect/dummy/lighting_obj (flashbang_turf, flashbang_range + 2, 4, COLOR_WHITE, 2)
|
|
for(var/mob/living/living_mob in get_hearers_in_view(flashbang_range, flashbang_turf))
|
|
bang(get_turf(living_mob), living_mob, soundbang)
|
|
qdel(src)
|
|
|
|
/obj/item/grenade/flashbang/proc/bang(turf/turf, mob/living/living_mob, soundbang = TRUE)
|
|
if(living_mob.stat == DEAD) //They're dead!
|
|
return
|
|
living_mob.show_message(span_warning("BANG"), MSG_AUDIBLE)
|
|
var/distance = get_dist(get_turf(src), turf)
|
|
var/sweetspot_range = clamp(CEILING(flashbang_range/sweetspot_divider, 1), 0, flashbang_range)
|
|
|
|
//Flash
|
|
var/attempt_flash = living_mob.flash_act(affect_silicon = 1)
|
|
if(attempt_flash == FLASH_COMPLETED)
|
|
if(distance <= sweetspot_range || issilicon(living_mob))
|
|
living_mob.Paralyze(max(20/max(1, distance), 5))
|
|
living_mob.Knockdown(max(200/max(1, distance), 60))
|
|
else
|
|
living_mob.adjust_dizzy_up_to(max(200/max(1, distance), 5), 20 SECONDS)
|
|
living_mob.dropItemToGround(living_mob.get_active_held_item())
|
|
living_mob.dropItemToGround(living_mob.get_inactive_held_item())
|
|
|
|
//Bang
|
|
if(!soundbang && distance)
|
|
return
|
|
|
|
if(!distance)
|
|
living_mob.soundbang_act(SOUNDBANG_OVERWHELMING, 20 SECONDS, 10, 15)
|
|
return
|
|
|
|
if(distance <= 1) // Adds more stun as to not prime n' pull (#45381)
|
|
living_mob.soundbang_act(SOUNDBANG_STRONG, 3 SECONDS, 5)
|
|
return
|
|
|
|
if(distance <= sweetspot_range)
|
|
living_mob.soundbang_act(SOUNDBANG_NORMAL, max(20 SECONDS / max(1, distance), 60), rand(0, 5))
|
|
return
|
|
|
|
if(!living_mob.soundbang_act(SOUNDBANG_NORMAL, 0, rand(0, 2)))
|
|
return
|
|
|
|
living_mob.adjust_staggered_up_to(max(200/max(1, distance), 5), 10 SECONDS)
|
|
living_mob.dropItemToGround(living_mob.get_active_held_item())
|
|
living_mob.dropItemToGround(living_mob.get_inactive_held_item())
|
|
|
|
/obj/item/grenade/stingbang
|
|
name = "stingbang"
|
|
icon_state = "timeg_locked"
|
|
base_icon_state = "timeg"
|
|
inhand_icon_state = "flashbang"
|
|
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
|
|
var/flashbang_range = 1 //how many tiles away the mob will be stunned.
|
|
shrapnel_type = /obj/projectile/bullet/pellet/stingball
|
|
shrapnel_radius = 5
|
|
custom_premium_price = PAYCHECK_COMMAND * 3.5 // mostly gotten through cargo, but throw in one for the sec vendor ;)
|
|
|
|
/obj/item/grenade/stingbang/mega
|
|
name = "mega stingbang"
|
|
icon_state = "timeg_mega_locked"
|
|
base_icon_state = "timeg_mega"
|
|
shrapnel_type = /obj/projectile/bullet/pellet/stingball/mega
|
|
shrapnel_radius = 12
|
|
|
|
/obj/item/grenade/stingbang/detonate(mob/living/lanced_by)
|
|
if(dud_flags)
|
|
active = FALSE
|
|
update_appearance()
|
|
return FALSE
|
|
|
|
if(iscarbon(loc))
|
|
var/mob/living/carbon/user = loc
|
|
var/obj/item/bodypart/bodypart = user.get_holding_bodypart_of_item(src)
|
|
if(bodypart)
|
|
forceMove(get_turf(user))
|
|
var/did_dismember = bodypart.dismember()
|
|
user.visible_message("<b>[span_danger("[src] goes off in [user]'s hand[did_dismember ? ", blowing [user.p_their()] [bodypart.plaintext_zone] to bloody shreds" : ""]!")]</b>", span_userdanger("[src] goes off in your hand[did_dismember ? ", blowing your [bodypart.plaintext_zone] to bloody shreds" : ""]!"))
|
|
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
|
|
update_mob()
|
|
var/flashbang_turf = get_turf(src)
|
|
if(!flashbang_turf)
|
|
return
|
|
do_sparks(rand(5, 9), FALSE, src)
|
|
playsound(flashbang_turf, 'sound/items/weapons/flashbang.ogg', 50, TRUE, 8, 0.9)
|
|
new /obj/effect/dummy/lighting_obj (flashbang_turf, flashbang_range + 2, 2, COLOR_WHITE, 1)
|
|
for(var/mob/living/living_mob in get_hearers_in_view(flashbang_range, flashbang_turf))
|
|
pop(get_turf(living_mob), living_mob)
|
|
qdel(src)
|
|
|
|
/obj/item/grenade/stingbang/proc/pop(turf/turf, mob/living/living_mob)
|
|
if(living_mob.stat == DEAD) //They're dead!
|
|
return
|
|
living_mob.show_message(span_warning("POP"), MSG_AUDIBLE)
|
|
var/distance = get_dist(get_turf(src), turf)
|
|
//Flash
|
|
if(living_mob.flash_act(affect_silicon = 1))
|
|
living_mob.Paralyze(max(10/max(1, distance), 5))
|
|
living_mob.Knockdown(max(100/max(1, distance), 60))
|
|
|
|
//Bang
|
|
if(!distance)
|
|
living_mob.Paralyze(2 SECONDS)
|
|
living_mob.Knockdown(20 SECONDS)
|
|
living_mob.soundbang_act(SOUNDBANG_NORMAL, 200, 10, 15)
|
|
if(living_mob.apply_damages(brute = 10, burn = 10))
|
|
to_chat(living_mob, span_userdanger("The blast from \the [src] bruises and burns you!"))
|
|
|
|
// only checking if they're on top of the tile, cause being one tile over will be its own punishment
|
|
|
|
// Grenade that releases more shrapnel the more times you use it in hand between priming and detonation (sorta like the 9bang from MW3), for admin goofs
|
|
/obj/item/grenade/primer
|
|
name = "rotfrag grenade"
|
|
desc = "A grenade that generates more shrapnel the more you rotate it in your hand after pulling the pin. This one releases shrapnel shards."
|
|
icon_state = "timeg_locked"
|
|
base_icon_state = "timeg"
|
|
inhand_icon_state = "flashbang"
|
|
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
|
|
var/rots_per_mag = 3 /// how many times we need to "rotate" the charge in hand per extra tile of magnitude
|
|
shrapnel_type = /obj/projectile/bullet/shrapnel
|
|
var/rots = 1 /// how many times we've "rotated" the charge
|
|
|
|
/obj/item/grenade/primer/attack_self(mob/user)
|
|
. = ..()
|
|
if(active)
|
|
user.playsound_local(user, 'sound/misc/box_deploy.ogg', 50, TRUE)
|
|
rots++
|
|
user.changeNext_move(CLICK_CD_RAPID)
|
|
|
|
/obj/item/grenade/primer/detonate(mob/living/lanced_by)
|
|
shrapnel_radius = round(rots / rots_per_mag)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
qdel(src)
|
|
|
|
/obj/item/grenade/primer/stingbang
|
|
name = "rotsting"
|
|
desc = "A grenade that generates more shrapnel the more you rotate it in your hand after pulling the pin. This one releases stingballs."
|
|
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
|
|
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
|
|
rots_per_mag = 2
|
|
shrapnel_type = /obj/projectile/bullet/pellet/stingball
|