mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 08:37:43 +01:00
Fixes projectile impacts + messages, embedding, adds deployable landmines (#53436)
* icon and alert anim * hmm * projectile and embed fixes * cap mine * clean up, fix some issues with projectile embeds * light * doc * icon * awkward * icon again
This commit is contained in:
@@ -162,7 +162,7 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
|
||||
#define EMBEDDED_PAIN_CHANCE 15
|
||||
///Chance for embedded object to fall out (causing pain but removing the object)
|
||||
#define EMBEDDED_ITEM_FALLOUT 5
|
||||
///Chance for an object to embed into somebody when thrown (if it's sharp)
|
||||
///Chance for an object to embed into somebody when thrown
|
||||
#define EMBED_CHANCE 45
|
||||
///Coefficient of multiplication for the damage the item does while embedded (this*item.w_class)
|
||||
#define EMBEDDED_PAIN_MULTIPLIER 2
|
||||
|
||||
@@ -607,10 +607,8 @@
|
||||
|
||||
// /obj/projectile signals (sent to the firer)
|
||||
|
||||
///from base of /obj/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle, hit_limb)
|
||||
///from base of /obj/projectile/proc/on_hit(), like COMSIG_PROJECTILE_ON_HIT but on the projectile itself and with the hit limb (if any): (atom/movable/firer, atom/target, Angle, hit_limb)
|
||||
#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit"
|
||||
#define COMPONENT_PROJECTILE_SELF_ON_HIT_EMBED_SUCCESS (1<<0)
|
||||
#define COMPONENT_PROJECTILE_SELF_ON_HIT_SELF_DELETE (1<<1)
|
||||
///from base of /obj/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle)
|
||||
#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit"
|
||||
///from base of /obj/projectile/proc/fire(): (obj/projectile, atom/original_target)
|
||||
@@ -621,8 +619,9 @@
|
||||
#define COMSIG_PROJECTILE_PREHIT "com_proj_prehit"
|
||||
///sent to targets during the process_hit proc of projectiles
|
||||
#define COMSIG_PROJECTILE_RANGE_OUT "projectile_range_out"
|
||||
///sent when trying to force an embed (mainly for projectiles, only used in the embed element)
|
||||
///from [/obj/item/proc/tryEmbed] sent when trying to force an embed (mainly for projectiles and eating glass)
|
||||
#define COMSIG_EMBED_TRY_FORCE "item_try_embed"
|
||||
#define COMPONENT_EMBED_SUCCESS (1<<1)
|
||||
|
||||
///sent to targets during the process_hit proc of projectiles
|
||||
#define COMSIG_PELLET_CLOUD_INIT "pellet_cloud_init"
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
if(target.stat == CONSCIOUS && is_nuclear_operative(shooter) && !is_nuclear_operative(target) && (locate(/obj/item/disk/nuclear) in target.get_contents()) && shooter.client)
|
||||
shooter.client.give_award(/datum/award/achievement/misc/rocket_holdup, shooter)
|
||||
|
||||
target.do_alert_animation(target)
|
||||
target.do_alert_animation()
|
||||
target.playsound_local(target.loc, 'sound/machines/chime.ogg', 50, TRUE)
|
||||
SEND_SIGNAL(target, COMSIG_ADD_MOOD_EVENT, "gunpoint", /datum/mood_event/gunpoint)
|
||||
|
||||
|
||||
@@ -132,15 +132,26 @@
|
||||
/**
|
||||
* create_blast_pellets() is for when we have a central point we want to shred the surroundings of with a ring of shrapnel, namely frag grenades and landmines.
|
||||
*
|
||||
* Note that grenades have extra handling for someone throwing themselves/being thrown on top of it, while landmines do not (obviously, it's a landmine!). See [/datum/component/pellet_cloud/proc/handle_martyrs]
|
||||
* Note that grenades have extra handling for someone throwing themselves/being thrown on top of it, see [/datum/component/pellet_cloud/proc/handle_martyrs]
|
||||
* Landmines just have a small check for [/obj/effect/mine/shrapnel/var/shred_triggerer], and spawn extra shrapnel for them if so
|
||||
*
|
||||
* Arguments:
|
||||
* * O- Our parent, the thing making the shrapnel obviously (grenade or landmine)
|
||||
* * punishable_triggerer- For grenade lances or people who step on the landmines (if we shred the triggerer), we spawn extra shrapnel for them in addition to the normal spread
|
||||
*/
|
||||
/datum/component/pellet_cloud/proc/create_blast_pellets(obj/O, mob/living/lanced_by)
|
||||
/datum/component/pellet_cloud/proc/create_blast_pellets(obj/O, mob/living/punishable_triggerer)
|
||||
SIGNAL_HANDLER_DOES_SLEEP
|
||||
|
||||
var/atom/A = parent
|
||||
|
||||
if(isgrenade(parent)) // handle_martyrs can reduce the radius and thus the number of pellets we produce if someone dives on top of a frag grenade
|
||||
handle_martyrs(lanced_by) // note that we can modify radius in this proc
|
||||
handle_martyrs(punishable_triggerer) // note that we can modify radius in this proc
|
||||
else if(islandmine(parent))
|
||||
var/obj/effect/mine/shrapnel/triggered_mine = parent
|
||||
if(triggered_mine.shred_triggerer && istype(punishable_triggerer)) // free shrapnel for the idiot who stepped on it if we're a mine that shreds the triggerer
|
||||
pellet_delta += radius // so they don't count against the later total
|
||||
for(var/i in 1 to radius)
|
||||
pew(punishable_triggerer, TRUE)
|
||||
|
||||
if(radius < 1)
|
||||
return
|
||||
@@ -161,18 +172,18 @@
|
||||
*
|
||||
* Note we track anyone who's alive and client'd when they get shredded in var/list/purple_hearts, for achievement checking later
|
||||
*/
|
||||
/datum/component/pellet_cloud/proc/handle_martyrs(mob/living/lanced_by)
|
||||
/datum/component/pellet_cloud/proc/handle_martyrs(mob/living/punishable_triggerer)
|
||||
var/magnitude_absorbed
|
||||
var/list/martyrs = list()
|
||||
|
||||
var/self_harm_radius_mult = 3
|
||||
|
||||
if(lanced_by && prob(60))
|
||||
to_chat(lanced_by, "<span class='userdanger'>Your plan to whack someone with a grenade on a stick backfires on you, literally!</span>")
|
||||
if(punishable_triggerer && prob(60))
|
||||
to_chat(punishable_triggerer, "<span class='userdanger'>Your plan to whack someone with a grenade on a stick backfires on you, literally!</span>")
|
||||
self_harm_radius_mult = 1 // we'll still give the guy who got hit some extra shredding, but not 3*radius
|
||||
pellet_delta += radius
|
||||
for(var/i in 1 to radius)
|
||||
pew(lanced_by) // thought you could be tricky and lance someone with no ill effects!!
|
||||
pew(punishable_triggerer) // thought you could be tricky and lance someone with no ill effects!!
|
||||
|
||||
for(var/mob/living/body in get_turf(parent))
|
||||
if(body == shooter)
|
||||
@@ -247,11 +258,11 @@
|
||||
finalize()
|
||||
|
||||
/// Minor convenience function for creating each shrapnel piece with circle explosions, mostly stolen from the MIRV component
|
||||
/datum/component/pellet_cloud/proc/pew(atom/target, spread=0)
|
||||
/datum/component/pellet_cloud/proc/pew(atom/target, landmine_victim)
|
||||
var/obj/projectile/P = new projectile_type(get_turf(parent))
|
||||
|
||||
//Shooting Code:
|
||||
P.spread = spread
|
||||
P.spread = 0
|
||||
P.original = target
|
||||
P.fired_from = parent
|
||||
P.firer = parent // don't hit ourself that would be really annoying
|
||||
@@ -262,6 +273,8 @@
|
||||
RegisterSignal(P, list(COMSIG_PROJECTILE_RANGE_OUT, COMSIG_PARENT_QDELETING), .proc/pellet_range)
|
||||
pellets += P
|
||||
P.fire()
|
||||
if(landmine_victim)
|
||||
P.process_hit(get_turf(target), target)
|
||||
|
||||
///All of our pellets are accounted for, time to go target by target and tell them how many things they got hit by.
|
||||
/datum/component/pellet_cloud/proc/finalize()
|
||||
@@ -274,8 +287,8 @@
|
||||
var/obj/item/bodypart/hit_part
|
||||
if(isbodypart(target))
|
||||
hit_part = target
|
||||
target = hit_part.owner
|
||||
if(wound_info_by_part[hit_part])
|
||||
target = hit_part.owner
|
||||
var/damage_dealt = wound_info_by_part[hit_part][CLOUD_POSITION_DAMAGE]
|
||||
var/w_bonus = wound_info_by_part[hit_part][CLOUD_POSITION_W_BONUS]
|
||||
var/bw_bonus = wound_info_by_part[hit_part][CLOUD_POSITION_BW_BONUS]
|
||||
|
||||
@@ -153,7 +153,7 @@
|
||||
if(!limb)
|
||||
limb = C.get_bodypart()
|
||||
|
||||
. = payload.tryEmbed(limb)
|
||||
payload.tryEmbed(limb) // at this point we've created our shrapnel baby and set them up to embed in the target, we can now die in peace as they handle their embed try on their own
|
||||
Detach(P)
|
||||
|
||||
/**
|
||||
@@ -187,5 +187,4 @@
|
||||
hit_zone = limb.body_zone
|
||||
C = limb.owner
|
||||
|
||||
checkEmbed(I, C, hit_zone, forced=TRUE)
|
||||
return TRUE
|
||||
return checkEmbed(I, C, hit_zone, forced=TRUE)
|
||||
|
||||
@@ -7,12 +7,36 @@
|
||||
icon_state = "uglymine"
|
||||
/// We manually check to see if we've been triggered in case multiple atoms cross us in the time between the mine being triggered and it actually deleting, to avoid a race condition with multiple detonations
|
||||
var/triggered = FALSE
|
||||
/// Can be set to FALSE if we want a short 'coming online' delay, then set to TRUE. Can still be set off by damage
|
||||
var/armed = TRUE
|
||||
/// If set, we default armed to FALSE and set it to TRUE after this long from initializing
|
||||
var/arm_delay
|
||||
|
||||
/obj/effect/mine/Initialize()
|
||||
. = ..()
|
||||
if(arm_delay)
|
||||
armed = FALSE
|
||||
icon_state = "uglymine-inactive"
|
||||
addtimer(CALLBACK(src, .proc/now_armed), arm_delay)
|
||||
|
||||
/obj/effect/mine/examine(mob/user)
|
||||
. = ..()
|
||||
if(!armed)
|
||||
. += "\t<span class='information'>It appears to be inactive...</span>"
|
||||
|
||||
/// The effect of the mine
|
||||
/obj/effect/mine/proc/mineEffect(mob/victim)
|
||||
to_chat(victim, "<span class='danger'>*click*</span>")
|
||||
|
||||
/// If the landmine was previously inactive, this beeps and displays a message marking it active
|
||||
/obj/effect/mine/proc/now_armed()
|
||||
armed = TRUE
|
||||
icon_state = "uglymine"
|
||||
playsound(src, 'sound/machines/nuke/angry_beep.ogg', 40, FALSE, -2)
|
||||
visible_message("<span class='danger'>\The [src] beeps softly, indicating it is now active.<span>", vision_distance = COMBAT_MESSAGE_RANGE)
|
||||
|
||||
/obj/effect/mine/Crossed(atom/movable/AM)
|
||||
if(triggered || !isturf(loc))
|
||||
if(triggered || !isturf(loc) || !armed)
|
||||
return
|
||||
. = ..()
|
||||
|
||||
@@ -25,16 +49,22 @@
|
||||
. = ..()
|
||||
triggermine()
|
||||
|
||||
/obj/effect/mine/proc/triggermine(mob/victim)
|
||||
if(triggered)
|
||||
/// When something sets off a mine
|
||||
/obj/effect/mine/proc/triggermine(atom/movable/triggerer)
|
||||
if(triggered) //too busy detonating to detonate again
|
||||
return
|
||||
visible_message("<span class='danger'>[victim] sets off [icon2html(src, viewers(src))] [src]!</span>")
|
||||
if(triggerer)
|
||||
visible_message("<span class='danger'>[triggerer] sets off [icon2html(src, viewers(src))] [src]!</span>")
|
||||
else
|
||||
visible_message("<span class='danger'>[icon2html(src, viewers(src))] [src] detonates!</span>")
|
||||
|
||||
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
mineEffect(victim)
|
||||
if(ismob(triggerer))
|
||||
mineEffect(triggerer)
|
||||
triggered = TRUE
|
||||
SEND_SIGNAL(src, COMSIG_MINE_TRIGGERED)
|
||||
SEND_SIGNAL(src, COMSIG_MINE_TRIGGERED, triggerer)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/mine/explosive
|
||||
@@ -51,18 +81,6 @@
|
||||
name = "stun mine"
|
||||
var/stun_time = 80
|
||||
|
||||
/obj/effect/mine/shrapnel
|
||||
name = "shrapnel mine"
|
||||
var/shrapnel_type = /obj/projectile/bullet/shrapnel
|
||||
var/shrapnel_magnitude = 3
|
||||
|
||||
/obj/effect/mine/shrapnel/mineEffect(mob/victim)
|
||||
AddComponent(/datum/component/pellet_cloud, projectile_type=shrapnel_type, magnitude=shrapnel_magnitude)
|
||||
|
||||
/obj/effect/mine/shrapnel/sting
|
||||
name = "stinger mine"
|
||||
shrapnel_type = /obj/projectile/bullet/pellet/stingball
|
||||
|
||||
/obj/effect/mine/stun/mineEffect(mob/living/victim)
|
||||
if(isliving(victim))
|
||||
victim.Paralyze(stun_time)
|
||||
@@ -197,3 +215,72 @@
|
||||
sleep(duration)
|
||||
victim.remove_movespeed_modifier(/datum/movespeed_modifier/yellow_orb)
|
||||
to_chat(victim, "<span class='notice'>You slow down.</span>")
|
||||
|
||||
|
||||
/// These mines spawn pellet_clouds around them when triggered
|
||||
/obj/effect/mine/shrapnel
|
||||
name = "shrapnel mine"
|
||||
/// The type of projectiles we're shooting out of this
|
||||
var/shrapnel_type = /obj/projectile/bullet/shrapnel
|
||||
/// Broadly, how many pellets we're spawning, the total is n! - (n-1)! pellets, so don't set it too high. For reference, 15 is probably pushing it at MAX
|
||||
var/shrapnel_magnitude = 3
|
||||
/// If TRUE, we spawn extra pellets to eviscerate the person who stepped on it, otherwise it just spawns a ring of pellets around the tile we're on (making setting it off an offensive move)
|
||||
var/shred_triggerer = FALSE
|
||||
|
||||
/obj/effect/mine/shrapnel/mineEffect(mob/victim)
|
||||
return
|
||||
|
||||
/obj/effect/mine/shrapnel/triggermine(atom/movable/AM)
|
||||
AddComponent(/datum/component/pellet_cloud, projectile_type=shrapnel_type, magnitude=shrapnel_magnitude)
|
||||
return ..()
|
||||
|
||||
/obj/effect/mine/shrapnel/sting
|
||||
name = "stinger mine"
|
||||
shrapnel_type = /obj/projectile/bullet/pellet/stingball
|
||||
|
||||
/obj/effect/mine/shrapnel/capspawn
|
||||
name = "\improper AP mine"
|
||||
desc = "A defensive landmine filled with 'AP shrapnel', good for defending cramped spaces without breaching hulls. The AP stands for 'Asset Protection', though it's still plenty nasty against any fool who sets it off."
|
||||
shrapnel_type = /obj/projectile/bullet/pellet/capmine
|
||||
shrapnel_magnitude = 4
|
||||
shred_triggerer = TRUE
|
||||
arm_delay = 3 SECONDS
|
||||
light_range = 1.6
|
||||
light_power = 2
|
||||
light_color = COLOR_VIVID_RED
|
||||
|
||||
/obj/effect/mine/shrapnel/capspawn/now_armed()
|
||||
. = ..()
|
||||
set_light_on(TRUE)
|
||||
|
||||
/obj/item/minespawner
|
||||
name = "landmine deployment device"
|
||||
desc = "When activated, will deploy an Asset Protection landmine after 3 seconds passes, perfect for high ranking NT officers looking to cover their assets from afar."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "beacon"
|
||||
|
||||
var/mine_type = /obj/effect/mine/shrapnel/capspawn
|
||||
var/active = FALSE
|
||||
|
||||
/obj/item/minespawner/attack_self(mob/user)
|
||||
. = ..()
|
||||
if(active)
|
||||
return
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/user_human = user
|
||||
user_human.throw_mode_on()
|
||||
|
||||
playsound(src, 'sound/weapons/armbomb.ogg', 70, TRUE)
|
||||
to_chat(user, "<span class='warning'>You arm \the [src], causing it to shake! It will deploy in 3 seconds.</span>")
|
||||
active = TRUE
|
||||
addtimer(CALLBACK(src, .proc/deploy_mine), 3 SECONDS)
|
||||
|
||||
/// Deploys the mine and deletes itself
|
||||
/obj/item/minespawner/proc/deploy_mine()
|
||||
do_alert_animation()
|
||||
playsound(loc, 'sound/machines/chime.ogg', 30, FALSE, -3)
|
||||
var/obj/effect/mine/new_mine = new mine_type(get_turf(src))
|
||||
visible_message("<span class='danger'>\The [src] releases a puff of smoke, revealing \a [new_mine]!</span>")
|
||||
var/obj/effect/particle_effect/smoke/poof = new (get_turf(src))
|
||||
poof.lifetime = 3
|
||||
qdel(src)
|
||||
|
||||
+10
-15
@@ -939,13 +939,10 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
if(embedding)
|
||||
return !isnull(embedding["pain_mult"]) && !isnull(embedding["jostle_pain_mult"]) && embedding["pain_mult"] == 0 && embedding["jostle_pain_mult"] == 0
|
||||
|
||||
///In case we want to do something special (like self delete) upon failing to embed in something. Returns a bitflag.
|
||||
///In case we want to do something special (like self delete) upon failing to embed in something.
|
||||
/obj/item/proc/failedEmbed()
|
||||
if(item_flags & DROPDEL)
|
||||
qdel(src)
|
||||
return COMPONENT_PROJECTILE_SELF_ON_HIT_SELF_DELETE
|
||||
return NONE
|
||||
|
||||
|
||||
///Called by the carbon throw_item() proc. Returns null if the item negates the throw, or a reference to the thing to suffer the throw else.
|
||||
/obj/item/proc/on_thrown(mob/living/carbon/user, atom/target)
|
||||
@@ -962,7 +959,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
*
|
||||
* Really, this is used mostly with projectiles with shrapnel payloads, from [/datum/element/embed/proc/checkEmbedProjectile], and called on said shrapnel. Mostly acts as an intermediate between different embed elements.
|
||||
*
|
||||
* Returns bitflags informing whether the item was able to embed itself, deleted itself in the process, or nothing happened.
|
||||
* Returns TRUE if it embedded successfully, nothing otherwise
|
||||
*
|
||||
* Arguments:
|
||||
* * target- Either a body part or a carbon. What are we hitting?
|
||||
@@ -975,9 +972,8 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
return NONE
|
||||
|
||||
if(SEND_SIGNAL(src, COMSIG_EMBED_TRY_FORCE, target, forced, silent))
|
||||
return COMPONENT_PROJECTILE_SELF_ON_HIT_EMBED_SUCCESS
|
||||
return failedEmbed()
|
||||
|
||||
return COMPONENT_EMBED_SUCCESS
|
||||
failedEmbed()
|
||||
|
||||
///For when you want to disable an item's embedding capabilities (like transforming weapons and such), this proc will detach any active embed elements from it.
|
||||
/obj/item/proc/disableEmbedding()
|
||||
@@ -1036,13 +1032,12 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
|
||||
|
||||
M.apply_damage(max(15, force), BRUTE, BODY_ZONE_HEAD, wound_bonus = 10, sharpness = TRUE)
|
||||
M.losebreath += 2
|
||||
switch(tryEmbed(M.get_bodypart(BODY_ZONE_CHEST), TRUE, TRUE)) //and if it embeds in their chest, cause a lot of pain
|
||||
if(COMPONENT_PROJECTILE_SELF_ON_HIT_SELF_DELETE)
|
||||
return
|
||||
if(COMPONENT_PROJECTILE_SELF_ON_HIT_EMBED_SUCCESS)
|
||||
M.apply_damage(max(25, force*1.5), BRUTE, BODY_ZONE_CHEST, wound_bonus = 7, sharpness = TRUE)
|
||||
M.losebreath += 6
|
||||
discover_after = FALSE
|
||||
if(tryEmbed(M.get_bodypart(BODY_ZONE_CHEST), TRUE, TRUE)) //and if it embeds successfully in their chest, cause a lot of pain
|
||||
M.apply_damage(max(25, force*1.5), BRUTE, BODY_ZONE_CHEST, wound_bonus = 7, sharpness = TRUE)
|
||||
M.losebreath += 6
|
||||
discover_after = FALSE
|
||||
if(QDELETED(src)) // in case trying to embed it caused its deletion (say, if it's DROPDEL)
|
||||
return
|
||||
|
||||
if(S?.tastes?.len) //is that blood in my mouth?
|
||||
S.tastes += "iron"
|
||||
|
||||
@@ -57,14 +57,6 @@
|
||||
shrapnel_type = /obj/projectile/bullet/pellet/stingball/mega
|
||||
shrapnel_radius = 12
|
||||
|
||||
/obj/item/grenade/stingbang/breaker
|
||||
name = "breakbang"
|
||||
shrapnel_type = /obj/projectile/bullet/pellet/stingball/breaker
|
||||
|
||||
/obj/item/grenade/stingbang/shred
|
||||
name = "shredbang"
|
||||
shrapnel_type = /obj/projectile/bullet/pellet/stingball/shred
|
||||
|
||||
/obj/item/grenade/stingbang/prime(mob/living/lanced_by)
|
||||
if(iscarbon(loc))
|
||||
var/mob/living/carbon/C = loc
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/obj/item/shrapnel // frag grenades
|
||||
name = "shrapnel shard"
|
||||
embedding = list(embed_chance=70, ignore_throwspeed_threshold=TRUE, fall_chance=4)
|
||||
custom_materials = list(/datum/material/iron=50)
|
||||
armour_penetration = -20
|
||||
icon = 'icons/obj/shards.dmi'
|
||||
@@ -11,7 +10,6 @@
|
||||
|
||||
/obj/item/shrapnel/stingball // stingbang grenades
|
||||
name = "stingball"
|
||||
embedding = list(embed_chance=90, fall_chance=3, jostle_chance=7, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.7, pain_mult=5, jostle_pain_mult=6, rip_time=15)
|
||||
icon_state = "tiny"
|
||||
sharpness = SHARP_NONE
|
||||
|
||||
@@ -21,11 +19,12 @@
|
||||
icon_state = "s-casing"
|
||||
embedding = null // embedding vars are taken from the projectile itself
|
||||
|
||||
|
||||
/obj/projectile/bullet/shrapnel
|
||||
name = "flying shrapnel shard"
|
||||
damage = 14
|
||||
range = 20
|
||||
armour_penetration = -30
|
||||
armour_penetration = -20
|
||||
dismemberment = 5
|
||||
ricochets_max = 2
|
||||
ricochet_chance = 70
|
||||
@@ -33,7 +32,8 @@
|
||||
ricochet_incidence_leeway = 60
|
||||
hit_stunned_targets = TRUE
|
||||
sharpness = SHARP_EDGED
|
||||
wound_bonus = 40
|
||||
wound_bonus = 30
|
||||
embedding = list(embed_chance=70, ignore_throwspeed_threshold=TRUE, fall_chance=1)
|
||||
|
||||
/obj/projectile/bullet/shrapnel/mega
|
||||
name = "flying shrapnel hunk"
|
||||
@@ -55,24 +55,37 @@
|
||||
ricochet_auto_aim_angle = 10
|
||||
ricochet_auto_aim_range = 2
|
||||
ricochet_incidence_leeway = 0
|
||||
embed_falloff_tile = -2
|
||||
shrapnel_type = /obj/item/shrapnel/stingball
|
||||
embedding = list(embed_chance=55, fall_chance=2, jostle_chance=7, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.7, pain_mult=3, jostle_pain_mult=3, rip_time=15)
|
||||
|
||||
/obj/projectile/bullet/pellet/stingball/mega
|
||||
name = "megastingball pellet"
|
||||
ricochets_max = 6
|
||||
ricochet_chance = 110
|
||||
|
||||
/obj/projectile/bullet/pellet/stingball/breaker
|
||||
name = "breakbang pellet"
|
||||
damage = 10
|
||||
wound_bonus = 40
|
||||
sharpness = SHARP_NONE
|
||||
|
||||
/obj/projectile/bullet/pellet/stingball/shred
|
||||
name = "shredbang pellet"
|
||||
damage = 10
|
||||
wound_bonus = 30
|
||||
sharpness = SHARP_EDGED
|
||||
|
||||
/obj/projectile/bullet/pellet/stingball/on_ricochet(atom/A)
|
||||
hit_stunned_targets = TRUE // ducking will save you from the first wave, but not the rebounds
|
||||
|
||||
|
||||
|
||||
/obj/projectile/bullet/pellet/capmine
|
||||
name = "\improper AP shrapnel shard"
|
||||
range = 7
|
||||
damage = 8
|
||||
stamina = 8
|
||||
sharpness = SHARP_EDGED
|
||||
wound_bonus = 5
|
||||
bare_wound_bonus = 5
|
||||
ricochets_max = 2
|
||||
ricochet_chance = 140
|
||||
shrapnel_type = /obj/item/shrapnel/capmine
|
||||
embedding = list(embed_chance=90, fall_chance=3, jostle_chance=7, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.7, pain_mult=5, jostle_pain_mult=6, rip_time=15)
|
||||
wound_falloff_tile = 0
|
||||
embed_falloff_tile = 0
|
||||
|
||||
/obj/item/shrapnel/capmine
|
||||
name = "\improper AP shrapnel shard"
|
||||
custom_materials = list(/datum/material/iron=50)
|
||||
armour_penetration = -30
|
||||
|
||||
|
||||
@@ -52,12 +52,13 @@
|
||||
if(!L.stat)
|
||||
if(!L.incapacitated(ignore_restraints = 1))
|
||||
L.face_atom(src)
|
||||
L.do_alert_animation(L)
|
||||
L.do_alert_animation()
|
||||
playsound(loc, 'sound/machines/chime.ogg', 50, FALSE, -5)
|
||||
|
||||
/mob/living/proc/do_alert_animation(atom/A)
|
||||
var/image/I = image('icons/obj/closet.dmi', A, "cardboard_special", A.layer+1)
|
||||
flick_overlay_view(I, A, 8)
|
||||
/// Does the MGS ! animation
|
||||
/atom/proc/do_alert_animation()
|
||||
var/image/I = image('icons/obj/closet.dmi', src, "cardboard_special", layer+1)
|
||||
flick_overlay_view(I, src, 8)
|
||||
I.alpha = 0
|
||||
animate(I, pixel_z = 32, alpha = 255, time = 5, easing = ELASTIC_EASING)
|
||||
|
||||
|
||||
@@ -42,9 +42,9 @@
|
||||
missing -= BP.body_zone
|
||||
for(var/obj/item/I in BP.embedded_objects)
|
||||
if(I.isEmbedHarmless())
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!</B>\n"
|
||||
msg += "<B>[t_He] [t_has] [icon2html(I, user)] \a [I] stuck to [t_his] [BP.name]!</B>\n"
|
||||
else
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!</B>\n"
|
||||
msg += "<B>[t_He] [t_has] [icon2html(I, user)] \a [I] embedded in [t_his] [BP.name]!</B>\n"
|
||||
for(var/i in BP.wounds)
|
||||
var/datum/wound/W = i
|
||||
msg += "[W.get_examine_description(user)]\n"
|
||||
|
||||
@@ -144,9 +144,9 @@
|
||||
missing -= body_part.body_zone
|
||||
for(var/obj/item/I in body_part.embedded_objects)
|
||||
if(I.isEmbedHarmless())
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [body_part.name]!</B>\n"
|
||||
msg += "<B>[t_He] [t_has] [icon2html(I, user)] \a [I] stuck to [t_his] [body_part.name]!</B>\n"
|
||||
else
|
||||
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [body_part.name]!</B>\n"
|
||||
msg += "<B>[t_He] [t_has] [icon2html(I, user)] \a [I] embedded in [t_his] [body_part.name]!</B>\n"
|
||||
|
||||
for(var/i in body_part.wounds)
|
||||
var/datum/wound/iter_wound = i
|
||||
|
||||
@@ -373,7 +373,7 @@
|
||||
..(gibbed)
|
||||
|
||||
/mob/living/simple_animal/hostile/proc/summon_backup(distance, exact_faction_match)
|
||||
do_alert_animation(src)
|
||||
do_alert_animation()
|
||||
playsound(loc, 'sound/machines/chime.ogg', 50, TRUE, -1)
|
||||
for(var/mob/living/simple_animal/hostile/M in oview(distance, targets_from))
|
||||
if(faction_check_mob(M, TRUE))
|
||||
|
||||
@@ -186,8 +186,10 @@
|
||||
if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
hit_limb = L.check_limb_hit(def_zone)
|
||||
if(SEND_SIGNAL(src, COMSIG_PROJECTILE_SELF_ON_HIT, firer, target, Angle, hit_limb) & COMPONENT_PROJECTILE_SELF_ON_HIT_SELF_DELETE)
|
||||
return BULLET_ACT_HIT
|
||||
SEND_SIGNAL(src, COMSIG_PROJECTILE_SELF_ON_HIT, firer, target, Angle, hit_limb)
|
||||
|
||||
if(QDELETED(src)) // in case one of the above signals deleted the projectile for whatever reason
|
||||
return
|
||||
var/turf/target_loca = get_turf(target)
|
||||
|
||||
var/hitx
|
||||
@@ -628,10 +630,8 @@
|
||||
else
|
||||
var/mob/living/L = target
|
||||
if(!direct_target)
|
||||
var/checking = NONE
|
||||
if(!hit_stunned_targets)
|
||||
checking = MOBILITY_USE | MOBILITY_STAND | MOBILITY_MOVE
|
||||
if(!(L.mobility_flags & checking) || L.stat == DEAD) // If target not able to use items, move and stand - or if they're just dead, pass over.
|
||||
var/checking = MOBILITY_USE | MOBILITY_STAND | MOBILITY_MOVE
|
||||
if((!hit_stunned_targets && !(L.mobility_flags & checking)) || L.stat == DEAD) // If target not able to use items, move and stand - or if they're just dead, pass over.
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 107 KiB |
Reference in New Issue
Block a user