mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-11 18:22:14 +00:00
Refactors embedding to use datums instead of storing data in bespoke elements (#84599)
## About The Pull Request This refactors embedding elements to make them use singleton datums (similarly to armor) instead being bespoke and creating a new element every time armor values are supposed to be adjusted. Default values have been removed from defines due to now being declared in base class itself. Additionally fixes vending machines and tackling gloves setting generated shards (which they instantly embed into their victim) embed properties to null after running the embedding code, despite said shards having non-null embedding values by default, making them not be able to embed into anyone else, also potentially breaking the pain/jostling code if they somehow get updated. ## Why It's Good For The Game Current embedding system is an unnecessarily complicated mess as bespoke elements are hard to work with, and creating a new element every time you change values is hacky at best. This change should make it easier to read and work with. ## Changelog 🆑 fix: Fixed glass shards generated from falling vending machines or tackling windows not being able to embed into anyone. refactor: Refactored embedding code to use datums instead of bespoke elements and ugly associated lists. /🆑
This commit is contained in:
@@ -180,38 +180,11 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list(
|
||||
#define UNARMED_MISS_CHANCE_MAX 80
|
||||
|
||||
//Combat object defines
|
||||
|
||||
//Embedded objects
|
||||
///Chance for embedded objects to cause pain (damage user)
|
||||
#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
|
||||
#define EMBED_CHANCE 45
|
||||
///Coefficient of multiplication for the damage the item does while embedded (this*item.w_class)
|
||||
#define EMBEDDED_PAIN_MULTIPLIER 2
|
||||
///Coefficient of multiplication for the damage the item does when it first embeds (this*item.w_class)
|
||||
#define EMBEDDED_IMPACT_PAIN_MULTIPLIER 4
|
||||
/// The minimum value of an item's throw_speed for it to embed (Unless it has embedded_ignore_throwspeed_threshold set to 1)
|
||||
#define EMBED_THROWSPEED_THRESHOLD 4
|
||||
///Coefficient of multiplication for the damage the item does when it falls out or is removed without a surgery (this*item.w_class)
|
||||
#define EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER 6
|
||||
///A Time in ticks, total removal time = (this*item.w_class)
|
||||
#define EMBEDDED_UNSAFE_REMOVAL_TIME 30
|
||||
///Chance for embedded objects to cause pain every time they move (jostle)
|
||||
#define EMBEDDED_JOSTLE_CHANCE 5
|
||||
///Coefficient of multiplication for the damage the item does while
|
||||
#define EMBEDDED_JOSTLE_PAIN_MULTIPLIER 1
|
||||
///This percentage of all pain will be dealt as stam damage rather than brute (0-1)
|
||||
#define EMBEDDED_PAIN_STAM_PCT 0.0
|
||||
///For thrown weapons, every extra speed it's thrown at above its normal throwspeed will add this to the embed chance
|
||||
/// For thrown embedding weapons, every extra speed it's thrown at above its normal throwspeed will add this to the embed chance
|
||||
#define EMBED_CHANCE_SPEED_BONUS 10
|
||||
|
||||
#define EMBED_HARMLESS list("pain_mult" = 0, "jostle_pain_mult" = 0, "ignore_throwspeed_threshold" = TRUE)
|
||||
#define EMBED_HARMLESS_SUPERIOR list("pain_mult" = 0, "jostle_pain_mult" = 0, "ignore_throwspeed_threshold" = TRUE, "embed_chance" = 100, "fall_chance" = 0.1)
|
||||
#define EMBED_POINTY list("ignore_throwspeed_threshold" = TRUE)
|
||||
#define EMBED_POINTY_SUPERIOR list("embed_chance" = 100, "ignore_throwspeed_threshold" = TRUE)
|
||||
|
||||
//Gun weapon weight
|
||||
#define WEAPON_LIGHT 1
|
||||
#define WEAPON_MEDIUM 2
|
||||
|
||||
@@ -142,11 +142,8 @@
|
||||
projectile.wound_bonus += var_modifiers["wound_bonus"]
|
||||
projectile.bare_wound_bonus += var_modifiers["bare_wound_bonus"]
|
||||
projectile.demolition_mod += var_modifiers["demolition_mod"]
|
||||
if(islist(var_modifiers["embedding"]))
|
||||
var/list/embed_params = var_modifiers["embedding"]
|
||||
for(var/embed_param in embed_params - "ignore_throwspeed_threshold")
|
||||
LAZYADDASSOC(projectile.embedding, embed_param, embed_params[embed_param])
|
||||
projectile.updateEmbedding()
|
||||
if(var_modifiers["embedding"])
|
||||
projectile.set_embed(var_modifiers["embedding"])
|
||||
|
||||
/datum/component/dart_insert/proc/remove_var_modifiers(obj/projectile/projectile)
|
||||
projectile.damage -= var_modifiers["damage"]
|
||||
@@ -155,9 +152,6 @@
|
||||
projectile.wound_bonus -= var_modifiers["wound_bonus"]
|
||||
projectile.bare_wound_bonus -= var_modifiers["bare_wound_bonus"]
|
||||
projectile.demolition_mod -= var_modifiers["demolition_mod"]
|
||||
if(islist(var_modifiers["embedding"]))
|
||||
var/list/embed_params = var_modifiers["embedding"]
|
||||
for(var/embed_param in embed_params - "ignore_throwspeed_threshold")
|
||||
LAZYADDASSOC(projectile.embedding, embed_param, -embed_params[embed_param])
|
||||
projectile.updateEmbedding()
|
||||
if(var_modifiers["embedding"])
|
||||
projectile.set_embed(initial(projectile.embed_type))
|
||||
var_modifiers.Cut()
|
||||
|
||||
@@ -27,63 +27,28 @@
|
||||
dupe_mode = COMPONENT_DUPE_ALLOWED
|
||||
var/obj/item/bodypart/limb
|
||||
var/obj/item/weapon
|
||||
|
||||
// all of this stuff is explained in _DEFINES/combat.dm
|
||||
var/embed_chance // not like we really need it once we're already stuck in but hey
|
||||
var/fall_chance
|
||||
var/pain_chance
|
||||
var/pain_mult
|
||||
var/impact_pain_mult
|
||||
var/remove_pain_mult
|
||||
var/rip_time
|
||||
var/ignore_throwspeed_threshold
|
||||
var/jostle_chance
|
||||
var/jostle_pain_mult
|
||||
var/pain_stam_pct
|
||||
|
||||
///if both our pain multiplier and jostle pain multiplier are 0, we're harmless and can omit most of the damage related stuff
|
||||
var/harmful
|
||||
|
||||
/datum/component/embedded/Initialize(obj/item/I,
|
||||
/datum/component/embedded/Initialize(obj/item/weapon,
|
||||
datum/thrownthing/throwingdatum,
|
||||
obj/item/bodypart/part,
|
||||
embed_chance = EMBED_CHANCE,
|
||||
fall_chance = EMBEDDED_ITEM_FALLOUT,
|
||||
pain_chance = EMBEDDED_PAIN_CHANCE,
|
||||
pain_mult = EMBEDDED_PAIN_MULTIPLIER,
|
||||
remove_pain_mult = EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER,
|
||||
impact_pain_mult = EMBEDDED_IMPACT_PAIN_MULTIPLIER,
|
||||
rip_time = EMBEDDED_UNSAFE_REMOVAL_TIME,
|
||||
ignore_throwspeed_threshold = FALSE,
|
||||
jostle_chance = EMBEDDED_JOSTLE_CHANCE,
|
||||
jostle_pain_mult = EMBEDDED_JOSTLE_PAIN_MULTIPLIER,
|
||||
pain_stam_pct = EMBEDDED_PAIN_STAM_PCT)
|
||||
obj/item/bodypart/part)
|
||||
|
||||
if(!iscarbon(parent) || !isitem(I))
|
||||
if(!iscarbon(parent) || !isitem(weapon))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.weapon = weapon
|
||||
|
||||
if(part)
|
||||
limb = part
|
||||
src.embed_chance = embed_chance
|
||||
src.fall_chance = fall_chance
|
||||
src.pain_chance = pain_chance
|
||||
src.pain_mult = pain_mult
|
||||
src.remove_pain_mult = remove_pain_mult
|
||||
src.rip_time = rip_time
|
||||
src.impact_pain_mult = impact_pain_mult
|
||||
src.ignore_throwspeed_threshold = ignore_throwspeed_threshold
|
||||
src.jostle_chance = jostle_chance
|
||||
src.jostle_pain_mult = jostle_pain_mult
|
||||
src.pain_stam_pct = pain_stam_pct
|
||||
src.weapon = I
|
||||
|
||||
if(!weapon.isEmbedHarmless())
|
||||
if(!weapon.is_embed_harmless())
|
||||
harmful = TRUE
|
||||
|
||||
weapon.embedded(parent, part)
|
||||
START_PROCESSING(SSdcs, src)
|
||||
var/mob/living/carbon/victim = parent
|
||||
|
||||
var/datum/embed_data/embed_data = weapon.get_embed()
|
||||
limb._embed_object(weapon) // on the inside... on the inside...
|
||||
weapon.forceMove(victim)
|
||||
RegisterSignals(weapon, list(COMSIG_MOVABLE_MOVED, COMSIG_QDELETING), PROC_REF(weaponDeleted))
|
||||
@@ -95,13 +60,13 @@
|
||||
playsound(victim,'sound/weapons/bladeslice.ogg', 40)
|
||||
if (limb.can_bleed())
|
||||
weapon.add_mob_blood(victim)//it embedded itself in you, of course it's bloody!
|
||||
damage += weapon.w_class * impact_pain_mult
|
||||
damage += weapon.w_class * embed_data.impact_pain_mult
|
||||
victim.add_mood_event("embedded", /datum/mood_event/embedded)
|
||||
|
||||
if(damage > 0)
|
||||
var/armor = victim.run_armor_check(limb.body_zone, MELEE, "Your armor has protected your [limb.plaintext_zone].", "Your armor has softened a hit to your [limb.plaintext_zone].",I.armour_penetration, weak_against_armour = I.weak_against_armour)
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, blocked=armor, wound_bonus = I.wound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness())
|
||||
victim.adjustStaminaLoss(pain_stam_pct * damage)
|
||||
var/armor = victim.run_armor_check(limb.body_zone, MELEE, "Your armor has protected your [limb.plaintext_zone].", "Your armor has softened a hit to your [limb.plaintext_zone].", weapon.armour_penetration, weak_against_armour = weapon.weak_against_armour)
|
||||
limb.receive_damage(brute = (1 - embed_data.pain_stam_pct) * damage, blocked = armor, wound_bonus = weapon.wound_bonus, bare_wound_bonus = weapon.bare_wound_bonus, sharpness = weapon.get_sharpness())
|
||||
victim.adjustStaminaLoss(embed_data.pain_stam_pct * damage)
|
||||
|
||||
/datum/component/embedded/Destroy()
|
||||
var/mob/living/carbon/victim = parent
|
||||
@@ -135,20 +100,21 @@
|
||||
if(victim.stat == DEAD)
|
||||
return
|
||||
|
||||
var/damage = weapon.w_class * pain_mult
|
||||
var/pain_chance_current = SPT_PROB_RATE(pain_chance / 100, seconds_per_tick) * 100
|
||||
if(pain_stam_pct && HAS_TRAIT_FROM(victim, TRAIT_INCAPACITATED, STAMINA)) //if it's a less-lethal embed, give them a break if they're already stamcritted
|
||||
var/datum/embed_data/embed_data = weapon.get_embed()
|
||||
var/damage = weapon.w_class * embed_data.pain_mult
|
||||
var/pain_chance_current = SPT_PROB_RATE(embed_data.pain_chance / 100, seconds_per_tick) * 100
|
||||
if(embed_data.pain_stam_pct && HAS_TRAIT_FROM(victim, TRAIT_INCAPACITATED, STAMINA)) //if it's a less-lethal embed, give them a break if they're already stamcritted
|
||||
pain_chance_current *= 0.2
|
||||
damage *= 0.5
|
||||
else if(victim.body_position == LYING_DOWN)
|
||||
pain_chance_current *= 0.2
|
||||
|
||||
if(harmful && prob(pain_chance_current))
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, wound_bonus = CANT_WOUND)
|
||||
victim.adjustStaminaLoss(pain_stam_pct * damage)
|
||||
limb.receive_damage(brute = (1 - embed_data.pain_stam_pct) * damage, wound_bonus = CANT_WOUND)
|
||||
victim.adjustStaminaLoss(embed_data.pain_stam_pct * damage)
|
||||
to_chat(victim, span_userdanger("[weapon] embedded in your [limb.plaintext_zone] hurts!"))
|
||||
|
||||
var/fall_chance_current = SPT_PROB_RATE(fall_chance / 100, seconds_per_tick) * 100
|
||||
var/fall_chance_current = SPT_PROB_RATE(embed_data.fall_chance / 100, seconds_per_tick) * 100
|
||||
if(victim.body_position == LYING_DOWN)
|
||||
fall_chance_current *= 0.2
|
||||
|
||||
@@ -165,25 +131,27 @@
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/mob/living/carbon/victim = parent
|
||||
var/chance = jostle_chance
|
||||
var/datum/embed_data/embed_data = weapon.get_embed()
|
||||
var/chance = embed_data.jostle_chance
|
||||
if(victim.move_intent == MOVE_INTENT_WALK || victim.body_position == LYING_DOWN)
|
||||
chance *= 0.5
|
||||
|
||||
if(harmful && prob(chance))
|
||||
var/damage = weapon.w_class * jostle_pain_mult
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, wound_bonus = CANT_WOUND)
|
||||
victim.adjustStaminaLoss(pain_stam_pct * damage)
|
||||
var/damage = weapon.w_class * embed_data.jostle_pain_mult
|
||||
limb.receive_damage(brute = (1 - embed_data.pain_stam_pct) * damage, wound_bonus = CANT_WOUND)
|
||||
victim.adjustStaminaLoss(embed_data.pain_stam_pct * damage)
|
||||
to_chat(victim, span_userdanger("[weapon] embedded in your [limb.plaintext_zone] jostles and stings!"))
|
||||
|
||||
|
||||
/// Called when then item randomly falls out of a carbon. This handles the damage and descriptors, then calls safe_remove()
|
||||
/datum/component/embedded/proc/fallOut()
|
||||
var/mob/living/carbon/victim = parent
|
||||
var/datum/embed_data/embed_data = weapon.get_embed()
|
||||
|
||||
if(harmful)
|
||||
var/damage = weapon.w_class * remove_pain_mult
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, wound_bonus = CANT_WOUND)
|
||||
victim.adjustStaminaLoss(pain_stam_pct * damage)
|
||||
var/damage = weapon.w_class * embed_data.remove_pain_mult
|
||||
limb.receive_damage(brute= (1 - embed_data.pain_stam_pct) * damage, wound_bonus = CANT_WOUND)
|
||||
victim.adjustStaminaLoss(embed_data.pain_stam_pct * damage)
|
||||
victim.visible_message(span_danger("[weapon] falls [harmful ? "out" : "off"] of [victim.name]'s [limb.plaintext_zone]!"), span_userdanger("[weapon] falls [harmful ? "out" : "off"] of your [limb.plaintext_zone]!"))
|
||||
safeRemove()
|
||||
|
||||
@@ -195,7 +163,8 @@
|
||||
if(I != weapon || src.limb != limb)
|
||||
return
|
||||
var/mob/living/carbon/victim = parent
|
||||
var/time_taken = rip_time * weapon.w_class
|
||||
var/datum/embed_data/embed_data = weapon.get_embed()
|
||||
var/time_taken = embed_data.rip_time * weapon.w_class
|
||||
INVOKE_ASYNC(src, PROC_REF(complete_rip_out), victim, I, limb, time_taken)
|
||||
|
||||
/// everything async that ripOut used to do
|
||||
@@ -214,9 +183,10 @@
|
||||
|
||||
/// Proc that actually does the damage associated with ripping something out of yourself. Call this before safeRemove.
|
||||
/datum/component/embedded/proc/damaging_removal(mob/living/carbon/victim, obj/item/removed, obj/item/bodypart/limb, ouch_multiplier = 1)
|
||||
var/damage = weapon.w_class * remove_pain_mult * ouch_multiplier
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, sharpness=SHARP_EDGED) //It hurts to rip it out, get surgery you dingus. unlike the others, this CAN wound + increase slash bloodflow
|
||||
victim.adjustStaminaLoss(pain_stam_pct * damage)
|
||||
var/datum/embed_data/embed_data = weapon.get_embed()
|
||||
var/damage = weapon.w_class * embed_data.remove_pain_mult * ouch_multiplier
|
||||
limb.receive_damage(brute= (1 - embed_data.pain_stam_pct) * damage, sharpness = SHARP_EDGED) //It hurts to rip it out, get surgery you dingus. unlike the others, this CAN wound + increase slash bloodflow
|
||||
victim.adjustStaminaLoss(embed_data.pain_stam_pct * damage)
|
||||
victim.emote("scream")
|
||||
|
||||
/// This proc handles the final step and actual removal of an embedded/stuck item from a carbon, whether or not it was actually removed safely.
|
||||
@@ -271,12 +241,13 @@
|
||||
/// The actual action for pulling out an embedded object with a hemostat
|
||||
/datum/component/embedded/proc/tweezePluck(obj/item/possible_tweezers, mob/user)
|
||||
var/mob/living/carbon/victim = parent
|
||||
var/datum/embed_data/embed_data = weapon.get_embed()
|
||||
var/self_pluck = (user == victim)
|
||||
// quality of the tool we're using
|
||||
var/tweezer_speed = possible_tweezers.toolspeed
|
||||
// is this an actual piece of medical equipment
|
||||
var/tweezer_safe = (possible_tweezers.tool_behaviour == TOOL_HEMOSTAT)
|
||||
var/pluck_time = rip_time * (weapon.w_class * 0.3) * (self_pluck ? 1.5 : 1) * tweezer_speed * (tweezer_safe ? 1 : 1.5)
|
||||
var/pluck_time = embed_data.rip_time * (weapon.w_class * 0.3) * (self_pluck ? 1.5 : 1) * tweezer_speed * (tweezer_safe ? 1 : 1.5)
|
||||
|
||||
if(self_pluck)
|
||||
user.visible_message(span_danger("[user] begins plucking [weapon] from [user.p_their()] [limb.plaintext_zone] with [possible_tweezers]..."), span_notice("You start plucking [weapon] from your [limb.plaintext_zone] with [possible_tweezers]... (It will take [DisplayTimeText(pluck_time)])"),\
|
||||
@@ -313,10 +284,12 @@
|
||||
if(!harmful)
|
||||
victim.visible_message(span_danger("[marked_item] vanishes from [victim.name]'s [limb.plaintext_zone]!"), span_userdanger("[weapon] vanishes from [limb.plaintext_zone]!"))
|
||||
return
|
||||
var/damage = weapon.w_class * remove_pain_mult
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage * 1.5, sharpness=SHARP_EDGED) // Performs exit wounds and flings the user to the caster if nearby
|
||||
|
||||
var/datum/embed_data/embed_data = weapon.get_embed()
|
||||
var/damage = weapon.w_class * embed_data.remove_pain_mult
|
||||
limb.receive_damage(brute = (1 - embed_data.pain_stam_pct) * damage * 1.5, sharpness = SHARP_EDGED) // Performs exit wounds and flings the user to the caster if nearby
|
||||
victim.cause_wound_of_type_and_severity(WOUND_PIERCE, limb, WOUND_SEVERITY_MODERATE)
|
||||
victim.adjustStaminaLoss(pain_stam_pct * damage)
|
||||
victim.adjustStaminaLoss(embed_data.pain_stam_pct * damage)
|
||||
playsound(get_turf(victim), 'sound/effects/wounds/blood2.ogg', 50, TRUE)
|
||||
|
||||
var/dist = get_dist(caster, victim) //Check if the caster is close enough to yank them in
|
||||
|
||||
@@ -596,11 +596,9 @@
|
||||
if(W.type in list(/obj/structure/window, /obj/structure/window/fulltile, /obj/structure/window/unanchored, /obj/structure/window/fulltile/unanchored)) // boring unreinforced windows
|
||||
for(var/i in 1 to speed)
|
||||
var/obj/item/shard/shard = new /obj/item/shard(get_turf(user))
|
||||
shard.embedding = list(embed_chance = 100, ignore_throwspeed_threshold = TRUE, impact_pain_mult=3, pain_chance=5)
|
||||
shard.updateEmbedding()
|
||||
shard.set_embed(/datum/embed_data/glass_candy)
|
||||
user.hitby(shard, skipcatch = TRUE, hitpush = FALSE)
|
||||
shard.embedding = null
|
||||
shard.updateEmbedding()
|
||||
shard.set_embed(initial(shard.embed_type))
|
||||
W.atom_destruction()
|
||||
user.adjustStaminaLoss(10 * speed)
|
||||
user.Paralyze(3 SECONDS)
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
if(reusable)
|
||||
if(!ispath(proj.shrapnel_type))
|
||||
proj.shrapnel_type = shell.type
|
||||
proj.updateEmbedding()
|
||||
proj.AddElement(/datum/element/projectile_drop, shell.type)
|
||||
|
||||
/datum/element/caseless/proc/on_fired_casing(obj/item/ammo_casing/shell, atom/target, mob/living/user, fired_from, randomspread, spread, zone_override, params, distro, obj/projectile/proj)
|
||||
|
||||
@@ -10,64 +10,33 @@
|
||||
*/
|
||||
|
||||
/datum/element/embed
|
||||
element_flags = ELEMENT_BESPOKE
|
||||
argument_hash_start_idx = 2
|
||||
var/initialized = FALSE /// whether we can skip assigning all the vars (since these are bespoke elements, we don't have to reset the vars every time we attach to something, we already know what we are!)
|
||||
|
||||
// all of this stuff is explained in _DEFINES/combat.dm
|
||||
var/embed_chance
|
||||
var/fall_chance
|
||||
var/pain_chance
|
||||
var/pain_mult
|
||||
var/remove_pain_mult
|
||||
var/impact_pain_mult
|
||||
var/rip_time
|
||||
var/ignore_throwspeed_threshold
|
||||
var/jostle_chance
|
||||
var/jostle_pain_mult
|
||||
var/pain_stam_pct
|
||||
var/payload_type
|
||||
|
||||
/datum/element/embed/Attach(datum/target, embed_chance, fall_chance, pain_chance, pain_mult, remove_pain_mult, impact_pain_mult, rip_time, ignore_throwspeed_threshold, jostle_chance, jostle_pain_mult, pain_stam_pct, projectile_payload=/obj/item/shard)
|
||||
/datum/element/embed/Attach(datum/target)
|
||||
. = ..()
|
||||
|
||||
if(!isitem(target) && !isprojectile(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
RegisterSignal(target, COMSIG_ELEMENT_ATTACH, PROC_REF(severancePackage))
|
||||
if(isitem(target))
|
||||
RegisterSignal(target, COMSIG_MOVABLE_IMPACT_ZONE, PROC_REF(checkEmbed))
|
||||
RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(examined))
|
||||
RegisterSignal(target, COMSIG_EMBED_TRY_FORCE, PROC_REF(tryForceEmbed))
|
||||
RegisterSignal(target, COMSIG_ITEM_DISABLE_EMBED, PROC_REF(detachFromWeapon))
|
||||
else
|
||||
payload_type = projectile_payload
|
||||
RegisterSignal(target, COMSIG_PROJECTILE_SELF_ON_HIT, PROC_REF(checkEmbedProjectile))
|
||||
RegisterSignal(target, COMSIG_ELEMENT_ATTACH, PROC_REF(sever_element))
|
||||
if(isprojectile(target))
|
||||
RegisterSignal(target, COMSIG_PROJECTILE_SELF_ON_HIT, PROC_REF(check_embed_projectile))
|
||||
return
|
||||
|
||||
if(!initialized)
|
||||
src.embed_chance = embed_chance
|
||||
src.fall_chance = fall_chance
|
||||
src.pain_chance = pain_chance
|
||||
src.pain_mult = pain_mult
|
||||
src.remove_pain_mult = remove_pain_mult
|
||||
src.rip_time = rip_time
|
||||
src.impact_pain_mult = impact_pain_mult
|
||||
src.ignore_throwspeed_threshold = ignore_throwspeed_threshold
|
||||
src.jostle_chance = jostle_chance
|
||||
src.jostle_pain_mult = jostle_pain_mult
|
||||
src.pain_stam_pct = pain_stam_pct
|
||||
initialized = TRUE
|
||||
RegisterSignal(target, COMSIG_MOVABLE_IMPACT_ZONE, PROC_REF(check_embed))
|
||||
RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(examined))
|
||||
RegisterSignal(target, COMSIG_EMBED_TRY_FORCE, PROC_REF(try_force_embed))
|
||||
RegisterSignal(target, COMSIG_ITEM_DISABLE_EMBED, PROC_REF(detach_from_weapon))
|
||||
|
||||
/datum/element/embed/Detach(obj/target)
|
||||
. = ..()
|
||||
if(isitem(target))
|
||||
UnregisterSignal(target, list(COMSIG_MOVABLE_IMPACT_ZONE, COMSIG_ELEMENT_ATTACH, COMSIG_MOVABLE_IMPACT, COMSIG_ATOM_EXAMINE, COMSIG_EMBED_TRY_FORCE, COMSIG_ITEM_DISABLE_EMBED))
|
||||
else
|
||||
if(isprojectile(target))
|
||||
UnregisterSignal(target, list(COMSIG_PROJECTILE_SELF_ON_HIT, COMSIG_ELEMENT_ATTACH))
|
||||
return
|
||||
|
||||
UnregisterSignal(target, list(COMSIG_MOVABLE_IMPACT_ZONE, COMSIG_ELEMENT_ATTACH, COMSIG_MOVABLE_IMPACT, COMSIG_ATOM_EXAMINE, COMSIG_EMBED_TRY_FORCE, COMSIG_ITEM_DISABLE_EMBED))
|
||||
|
||||
/// Checking to see if we're gonna embed into a human
|
||||
/datum/element/embed/proc/checkEmbed(obj/item/weapon, mob/living/carbon/victim, hit_zone, blocked, datum/thrownthing/throwingdatum, forced=FALSE)
|
||||
/datum/element/embed/proc/check_embed(obj/item/weapon, mob/living/carbon/victim, hit_zone, blocked, datum/thrownthing/throwingdatum, forced=FALSE)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(forced)
|
||||
@@ -82,7 +51,7 @@
|
||||
|
||||
var/flying_speed = throwingdatum?.speed || weapon.throw_speed
|
||||
|
||||
if(flying_speed < EMBED_THROWSPEED_THRESHOLD && !ignore_throwspeed_threshold)
|
||||
if(flying_speed < EMBED_THROWSPEED_THRESHOLD && !weapon.get_embed().ignore_throwspeed_threshold)
|
||||
return FALSE
|
||||
|
||||
if(!roll_embed_chance(weapon, victim, hit_zone, throwingdatum))
|
||||
@@ -97,27 +66,17 @@
|
||||
victim.AddComponent(/datum/component/embedded,\
|
||||
weapon,\
|
||||
throwingdatum,\
|
||||
part = limb,\
|
||||
embed_chance = embed_chance,\
|
||||
fall_chance = fall_chance,\
|
||||
pain_chance = pain_chance,\
|
||||
pain_mult = pain_mult,\
|
||||
remove_pain_mult = remove_pain_mult,\
|
||||
rip_time = rip_time,\
|
||||
ignore_throwspeed_threshold = ignore_throwspeed_threshold,\
|
||||
jostle_chance = jostle_chance,\
|
||||
jostle_pain_mult = jostle_pain_mult,\
|
||||
pain_stam_pct = pain_stam_pct)
|
||||
part = limb)
|
||||
|
||||
///A different embed element has been attached, so we'll detach and let them handle things
|
||||
/datum/element/embed/proc/severancePackage(obj/weapon, datum/element/E)
|
||||
/datum/element/embed/proc/sever_element(obj/weapon, datum/element/E)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(istype(E, /datum/element/embed))
|
||||
Detach(weapon)
|
||||
|
||||
///If we don't want to be embeddable anymore (deactivating an e-dagger for instance)
|
||||
/datum/element/embed/proc/detachFromWeapon(obj/weapon)
|
||||
/datum/element/embed/proc/detach_from_weapon(obj/weapon)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
Detach(weapon)
|
||||
@@ -126,26 +85,26 @@
|
||||
/datum/element/embed/proc/examined(obj/item/I, mob/user, list/examine_list)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(I.isEmbedHarmless())
|
||||
if(I.is_embed_harmless())
|
||||
examine_list += "[I] feels sticky, and could probably get stuck to someone if thrown properly!"
|
||||
else
|
||||
examine_list += "[I] has a fine point, and could probably embed in someone if thrown properly!"
|
||||
|
||||
/**
|
||||
* checkEmbedProjectile() is what we get when a projectile with a defined shrapnel_type impacts a target.
|
||||
* check_embed_projectile() is what we get when a projectile with a defined shrapnel_type impacts a target.
|
||||
*
|
||||
* If we hit a valid target, we create the shrapnel_type object and then forcefully try to embed it on its
|
||||
* behalf. DO NOT EVER add an embed element to the payload and let it do the rest.
|
||||
* That's awful, and it'll limit us to drop-deletable shrapnels in the worry of stuff like
|
||||
* arrows and harpoons being embeddable even when not let loose by their weapons.
|
||||
*/
|
||||
/datum/element/embed/proc/checkEmbedProjectile(obj/projectile/source, atom/movable/firer, atom/hit, angle, hit_zone)
|
||||
/datum/element/embed/proc/check_embed_projectile(obj/projectile/source, atom/movable/firer, atom/hit, angle, hit_zone, blocked)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!source.can_embed_into(hit))
|
||||
if(!source.can_embed_into(hit) || blocked)
|
||||
Detach(source)
|
||||
return // we don't care
|
||||
|
||||
var/payload_type = source.shrapnel_type
|
||||
var/obj/item/payload = new payload_type(get_turf(hit))
|
||||
if(istype(payload, /obj/item/shrapnel/bullet))
|
||||
payload.name = source.name
|
||||
@@ -155,12 +114,12 @@
|
||||
if(!limb)
|
||||
limb = C.get_bodypart()
|
||||
|
||||
if(!tryForceEmbed(payload, limb))
|
||||
if(!try_force_embed(payload, limb))
|
||||
payload.failedEmbed()
|
||||
Detach(source)
|
||||
|
||||
/**
|
||||
* tryForceEmbed() is called here when we fire COMSIG_EMBED_TRY_FORCE from [/obj/item/proc/tryEmbed]. Mostly, this means we're a piece of shrapnel from a projectile that just impacted something, and we're trying to embed in it.
|
||||
* try_force_embed() is called here when we fire COMSIG_EMBED_TRY_FORCE from [/obj/item/proc/tryEmbed]. Mostly, this means we're a piece of shrapnel from a projectile that just impacted something, and we're trying to embed in it.
|
||||
*
|
||||
* The reason for this extra mucking about is avoiding having to do an extra hitby(), and annoying the target by impacting them once with the projectile, then again with the shrapnel, and possibly
|
||||
* AGAIN if we actually embed. This way, we save on at least one message.
|
||||
@@ -171,7 +130,7 @@
|
||||
* * hit_zone- if our target is a carbon, try to hit them in this zone, if we don't have one, pick a random one. If our target is a bodypart, we already know where we're hitting.
|
||||
* * forced- if we want this to succeed 100%
|
||||
*/
|
||||
/datum/element/embed/proc/tryForceEmbed(obj/item/embedding_item, atom/target, hit_zone, forced=FALSE)
|
||||
/datum/element/embed/proc/try_force_embed(obj/item/embedding_item, atom/target, hit_zone, forced=FALSE)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/obj/item/bodypart/limb
|
||||
@@ -190,16 +149,16 @@
|
||||
if(!forced && !roll_embed_chance(embedding_item, victim, hit_zone))
|
||||
return
|
||||
|
||||
return checkEmbed(embedding_item, victim, hit_zone, forced=TRUE) // Don't repeat the embed roll, we already did it
|
||||
return check_embed(embedding_item, victim, hit_zone, forced=TRUE) // Don't repeat the embed roll, we already did it
|
||||
|
||||
/// Calculates the actual chance to embed based on armour penetration and throwing speed, then returns true if we pass that probability check
|
||||
/datum/element/embed/proc/roll_embed_chance(obj/item/embedding_item, mob/living/victim, hit_zone, datum/thrownthing/throwingdatum)
|
||||
var/actual_chance = embed_chance
|
||||
var/actual_chance = embedding_item.get_embed().embed_chance
|
||||
|
||||
if(throwingdatum?.speed > embedding_item.throw_speed)
|
||||
actual_chance += (throwingdatum.speed - embedding_item.throw_speed) * EMBED_CHANCE_SPEED_BONUS
|
||||
|
||||
if(embedding_item.isEmbedHarmless()) // all the armor in the world won't save you from a kick me sign
|
||||
if(embedding_item.is_embed_harmless()) // all the armor in the world won't save you from a kick me sign
|
||||
return prob(actual_chance)
|
||||
|
||||
var/armor = max(victim.run_armor_check(hit_zone, BULLET, silent=TRUE), victim.run_armor_check(hit_zone, BOMB, silent=TRUE)) * 0.5 // we'll be nice and take the better of bullet and bomb armor, halved
|
||||
|
||||
54
code/datums/embed_data.dm
Normal file
54
code/datums/embed_data.dm
Normal file
@@ -0,0 +1,54 @@
|
||||
/// Assosciative list of type -> embed data.
|
||||
GLOBAL_LIST_INIT(embed_by_type, generate_embed_type_cache())
|
||||
|
||||
/proc/generate_embed_type_cache()
|
||||
var/list/embed_cache = list()
|
||||
for(var/datum/embed_data/embed_type as anything in subtypesof(/datum/embed_data))
|
||||
var/datum/embed_data/embed = new embed_type
|
||||
embed_cache[embed_type] = embed
|
||||
return embed_cache
|
||||
|
||||
/proc/get_embed_by_type(embed_type)
|
||||
var/datum/embed_data/embed = GLOB.embed_by_type[embed_type]
|
||||
if(embed)
|
||||
return embed
|
||||
CRASH("Attempted to get an embed type that did not exist! '[embed_type]'")
|
||||
|
||||
/datum/embed_data
|
||||
/// Chance for an object to embed into somebody when thrown
|
||||
var/embed_chance = 45
|
||||
/// Chance for embedded object to fall out (causing pain but removing the object)
|
||||
var/fall_chance = 5
|
||||
/// Chance for embedded objects to cause pain (damage user)
|
||||
var/pain_chance = 15
|
||||
/// Coefficient of multiplication for the damage the item does while embedded (this*item.w_class)
|
||||
var/pain_mult = 2
|
||||
/// Coefficient of multiplication for the damage the item does when it first embeds (this*item.w_class)
|
||||
var/impact_pain_mult = 4
|
||||
/// Coefficient of multiplication for the damage the item does when it falls out or is removed without a surgery (this*item.w_class)
|
||||
var/remove_pain_mult = 6
|
||||
/// Time in ticks, total removal time = (this*item.w_class)
|
||||
var/rip_time = 30
|
||||
/// If this should ignore throw speed threshold of 4
|
||||
var/ignore_throwspeed_threshold = FALSE
|
||||
/// Chance for embedded objects to cause pain every time they move (jostle)
|
||||
var/jostle_chance = 5
|
||||
/// Coefficient of multiplication for the damage the item does while
|
||||
var/jostle_pain_mult = 1
|
||||
/// This percentage of all pain will be dealt as stam damage rather than brute (0-1)
|
||||
var/pain_stam_pct = 0
|
||||
|
||||
/datum/embed_data/proc/generate_with_values(embed_chance, fall_chance, pain_chance, pain_mult, impact_pain_mult, remove_pain_mult, rip_time, ignore_throwspeed_threshold, jostle_chance, jostle_pain_mult, pain_stam_pct)
|
||||
var/datum/embed_data/data = new()
|
||||
|
||||
data.embed_chance = !isnull(embed_chance) ? embed_chance : src.embed_chance
|
||||
data.fall_chance = !isnull(fall_chance) ? fall_chance : src.fall_chance
|
||||
data.pain_chance = !isnull(pain_chance) ? pain_chance : src.pain_chance
|
||||
data.pain_mult = !isnull(pain_mult) ? pain_mult : src.pain_mult
|
||||
data.impact_pain_mult = !isnull(impact_pain_mult) ? impact_pain_mult : src.impact_pain_mult
|
||||
data.remove_pain_mult = !isnull(remove_pain_mult) ? remove_pain_mult : src.remove_pain_mult
|
||||
data.rip_time = !isnull(rip_time) ? rip_time : src.rip_time
|
||||
data.ignore_throwspeed_threshold = !isnull(ignore_throwspeed_threshold) ? ignore_throwspeed_threshold : src.ignore_throwspeed_threshold
|
||||
data.jostle_chance = !isnull(jostle_chance) ? jostle_chance : src.jostle_chance
|
||||
data.jostle_pain_mult = !isnull(jostle_pain_mult) ? jostle_pain_mult : src.jostle_pain_mult
|
||||
data.pain_stam_pct = !isnull(pain_stam_pct) ? pain_stam_pct : src.pain_stam_pct
|
||||
@@ -48,13 +48,7 @@
|
||||
force = 2
|
||||
throwforce = 25
|
||||
throw_speed = 4
|
||||
embedding = list(
|
||||
"impact_pain_mult" = 0,
|
||||
"embedded_pain_multiplier" = 15,
|
||||
"embed_chance" = 100,
|
||||
"embedded_fall_chance" = 0,
|
||||
"embedded_ignore_throwspeed_threshold" = TRUE,
|
||||
)
|
||||
embed_type = /datum/embed_data/tongue_spike
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
sharpness = SHARP_POINTY
|
||||
custom_materials = list(/datum/material/biomass = SMALL_MATERIAL_AMOUNT * 5)
|
||||
@@ -63,6 +57,13 @@
|
||||
/// if we missed our target
|
||||
var/missed = TRUE
|
||||
|
||||
/datum/embed_data/tongue_spike
|
||||
impact_pain_mult = 0
|
||||
pain_mult = 15
|
||||
embed_chance = 100
|
||||
fall_chance = 0
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
|
||||
/obj/item/hardened_spike/Initialize(mapload, mob/living/carbon/source)
|
||||
. = ..()
|
||||
src.fired_by_ref = WEAKREF(source)
|
||||
@@ -110,17 +111,14 @@
|
||||
desc = "Hardened biomass, shaped into... something."
|
||||
icon_state = "tonguespikechem"
|
||||
throwforce = 2
|
||||
embedding = list(
|
||||
"impact_pain_mult" = 0,
|
||||
"embedded_pain_multiplier" = 0,
|
||||
"embed_chance" = 100,
|
||||
"embedded_fall_chance" = 0,
|
||||
"embedded_pain_chance" = 0,
|
||||
"embedded_ignore_throwspeed_threshold" = TRUE, //never hurts once it's in you
|
||||
)
|
||||
embed_type = /datum/embed_data/tongue_spike/chem
|
||||
/// Whether the tongue's already embedded in a target once before
|
||||
var/embedded_once_alread = FALSE
|
||||
|
||||
/datum/embed_data/tongue_spike/chem
|
||||
pain_mult = 0
|
||||
pain_chance = 0
|
||||
|
||||
/obj/item/hardened_spike/chem/embedded(mob/living/carbon/human/embedded_mob)
|
||||
. = ..()
|
||||
if(embedded_once_alread)
|
||||
|
||||
@@ -164,7 +164,9 @@
|
||||
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
|
||||
|
||||
/// Does it embed and if yes, what kind of embed
|
||||
var/list/embedding
|
||||
var/embed_type
|
||||
/// Stores embedding data
|
||||
var/datum/embed_data/embed_data
|
||||
|
||||
///for flags such as [GLASSESCOVERSEYES]
|
||||
var/flags_cover = 0
|
||||
@@ -263,8 +265,8 @@
|
||||
add_weapon_description()
|
||||
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_ITEM, src)
|
||||
if(LAZYLEN(embedding))
|
||||
updateEmbedding()
|
||||
if(get_embed())
|
||||
AddElement(/datum/element/embed)
|
||||
|
||||
setup_reskinning()
|
||||
|
||||
@@ -1246,9 +1248,11 @@
|
||||
return owner.dropItemToGround(src)
|
||||
|
||||
///Does the current embedding var meet the criteria for being harmless? Namely, does it have a pain multiplier and jostle pain mult of 0? If so, return true.
|
||||
/obj/item/proc/isEmbedHarmless()
|
||||
if(embedding)
|
||||
return !isnull(embedding["pain_mult"]) && !isnull(embedding["jostle_pain_mult"]) && embedding["pain_mult"] == 0 && embedding["jostle_pain_mult"] == 0
|
||||
/obj/item/proc/is_embed_harmless()
|
||||
if (!get_embed())
|
||||
return FALSE
|
||||
|
||||
return !isnull(embed_data.pain_mult) && !isnull(embed_data.jostle_pain_mult) && embed_data.pain_mult == 0 && embed_data.jostle_pain_mult == 0
|
||||
|
||||
///In case we want to do something special (like self delete) upon failing to embed in something.
|
||||
/obj/item/proc/failedEmbed()
|
||||
@@ -1281,11 +1285,13 @@
|
||||
/obj/item/proc/tryEmbed(atom/target, forced=FALSE)
|
||||
if(!isbodypart(target) && !iscarbon(target))
|
||||
return NONE
|
||||
if(!forced && !LAZYLEN(embedding))
|
||||
|
||||
if(!forced && !get_embed())
|
||||
return NONE
|
||||
|
||||
if(SEND_SIGNAL(src, COMSIG_EMBED_TRY_FORCE, target = target, forced = forced))
|
||||
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.
|
||||
@@ -1293,29 +1299,6 @@
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_DISABLE_EMBED)
|
||||
return
|
||||
|
||||
///For when you want to add/update the embedding on an item. Uses the vars in [/obj/item/var/embedding], and defaults to config values for values that aren't set. Will automatically detach previous embed elements on this item.
|
||||
/obj/item/proc/updateEmbedding()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_EMBEDDING_UPDATE)
|
||||
if(!LAZYLEN(embedding))
|
||||
disableEmbedding()
|
||||
return
|
||||
|
||||
AddElement(/datum/element/embed,\
|
||||
embed_chance = (!isnull(embedding["embed_chance"]) ? embedding["embed_chance"] : EMBED_CHANCE),\
|
||||
fall_chance = (!isnull(embedding["fall_chance"]) ? embedding["fall_chance"] : EMBEDDED_ITEM_FALLOUT),\
|
||||
pain_chance = (!isnull(embedding["pain_chance"]) ? embedding["pain_chance"] : EMBEDDED_PAIN_CHANCE),\
|
||||
pain_mult = (!isnull(embedding["pain_mult"]) ? embedding["pain_mult"] : EMBEDDED_PAIN_MULTIPLIER),\
|
||||
remove_pain_mult = (!isnull(embedding["remove_pain_mult"]) ? embedding["remove_pain_mult"] : EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER),\
|
||||
rip_time = (!isnull(embedding["rip_time"]) ? embedding["rip_time"] : EMBEDDED_UNSAFE_REMOVAL_TIME),\
|
||||
ignore_throwspeed_threshold = (!isnull(embedding["ignore_throwspeed_threshold"]) ? embedding["ignore_throwspeed_threshold"] : FALSE),\
|
||||
impact_pain_mult = (!isnull(embedding["impact_pain_mult"]) ? embedding["impact_pain_mult"] : EMBEDDED_IMPACT_PAIN_MULTIPLIER),\
|
||||
jostle_chance = (!isnull(embedding["jostle_chance"]) ? embedding["jostle_chance"] : EMBEDDED_JOSTLE_CHANCE),\
|
||||
jostle_pain_mult = (!isnull(embedding["jostle_pain_mult"]) ? embedding["jostle_pain_mult"] : EMBEDDED_JOSTLE_PAIN_MULTIPLIER),\
|
||||
pain_stam_pct = (!isnull(embedding["pain_stam_pct"]) ? embedding["pain_stam_pct"] : EMBEDDED_PAIN_STAM_PCT))
|
||||
return TRUE
|
||||
|
||||
/// How many different types of mats will be counted in a bite?
|
||||
#define MAX_MATS_PER_BITE 2
|
||||
|
||||
@@ -1733,6 +1716,18 @@
|
||||
SEND_SIGNAL(loc, COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED, src, old_w_class, new_w_class)
|
||||
return TRUE
|
||||
|
||||
/// Fetches embedding data
|
||||
/obj/item/proc/get_embed()
|
||||
RETURN_TYPE(/datum/embed_data)
|
||||
return embed_type ? (embed_data ||= get_embed_by_type(embed_type)) : null
|
||||
|
||||
/obj/item/proc/set_embed(datum/embed_data/embed)
|
||||
if(embed_data == embed)
|
||||
return
|
||||
if(!GLOB.embed_by_type[embed_data?.type])
|
||||
qdel(embed_data)
|
||||
embed_data = ispath(embed) ? get_embed_by_type(armor) : embed
|
||||
SEND_SIGNAL(src, COMSIG_ITEM_EMBEDDING_UPDATE)
|
||||
|
||||
/**
|
||||
* Returns the atom(either itself or an internal module) that will interact/attack the target on behalf of us
|
||||
|
||||
@@ -145,9 +145,8 @@
|
||||
var/obj/item/thrown_weapon = bomb_target
|
||||
thrown_weapon.throw_speed = max(1, (thrown_weapon.throw_speed - 3))
|
||||
thrown_weapon.throw_range = max(1, (thrown_weapon.throw_range - 3))
|
||||
if(thrown_weapon.embedding)
|
||||
thrown_weapon.embedding["embed_chance"] = 0
|
||||
thrown_weapon.updateEmbedding()
|
||||
if(thrown_weapon.get_embed())
|
||||
thrown_weapon.set_embed(thrown_weapon.get_embed().generate_with_values(embed_chance = 0))
|
||||
else if(isliving(bomb_target))
|
||||
plastic_overlay.layer = FLOAT_LAYER
|
||||
|
||||
|
||||
@@ -124,13 +124,19 @@
|
||||
icon_state = "buckknife"
|
||||
worn_icon_state = "buckknife"
|
||||
desc = "A military combat utility survival knife."
|
||||
embedding = list("pain_mult" = 4, "embed_chance" = 65, "fall_chance" = 10, "ignore_throwspeed_threshold" = TRUE)
|
||||
embed_type = /datum/embed_data/combat_knife
|
||||
force = 20
|
||||
throwforce = 20
|
||||
attack_verb_continuous = list("slashes", "stabs", "slices", "tears", "lacerates", "rips", "cuts")
|
||||
attack_verb_simple = list("slash", "stab", "slice", "tear", "lacerate", "rip", "cut")
|
||||
slot_flags = ITEM_SLOT_MASK
|
||||
|
||||
/datum/embed_data/combat_knife
|
||||
pain_mult = 4
|
||||
embed_chance = 65
|
||||
fall_chance = 10
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
|
||||
/obj/item/knife/combat/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/knockoff, 90, list(BODY_ZONE_PRECISE_MOUTH), slot_flags) //90% to knock off when wearing a mask
|
||||
@@ -155,7 +161,7 @@
|
||||
icon = 'icons/obj/weapons/stabby.dmi'
|
||||
icon_state = "survivalknife"
|
||||
worn_icon_state = "survivalknife"
|
||||
embedding = list("pain_mult" = 4, "embed_chance" = 35, "fall_chance" = 10)
|
||||
embed_type = /datum/embed_data/combat_knife/weak
|
||||
desc = "A hunting grade survival knife."
|
||||
force = 15
|
||||
throwforce = 15
|
||||
@@ -169,13 +175,16 @@
|
||||
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
||||
desc = "A sharpened bone. The bare minimum in survival."
|
||||
embedding = list("pain_mult" = 4, "embed_chance" = 35, "fall_chance" = 10)
|
||||
embed_type = /datum/embed_data/combat_knife/weak
|
||||
obj_flags = parent_type::obj_flags & ~CONDUCTS_ELECTRICITY
|
||||
slot_flags = NONE
|
||||
force = 15
|
||||
throwforce = 15
|
||||
custom_materials = null
|
||||
|
||||
/datum/embed_data/combat_knife/weak
|
||||
embed_chance = 35
|
||||
|
||||
/obj/item/knife/combat/cyborg
|
||||
name = "cyborg knife"
|
||||
icon = 'icons/obj/items_cyborg.dmi'
|
||||
|
||||
@@ -113,13 +113,9 @@
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(active)
|
||||
if(embedding)
|
||||
updateEmbedding()
|
||||
heat = active_heat
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
if(embedding)
|
||||
disableEmbedding()
|
||||
heat = initial(heat)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
@@ -173,6 +169,10 @@
|
||||
return (BRUTELOSS|FIRELOSS)
|
||||
|
||||
/// Energy swords.
|
||||
/datum/embed_data/esword
|
||||
embed_chance = 75
|
||||
impact_pain_mult = 10
|
||||
|
||||
/obj/item/melee/energy/sword
|
||||
name = "energy sword"
|
||||
desc = "May the force be within you."
|
||||
@@ -189,7 +189,7 @@
|
||||
armour_penetration = 35
|
||||
block_chance = 50
|
||||
block_sound = 'sound/weapons/block_blade.ogg'
|
||||
embedding = list("embed_chance" = 75, "impact_pain_mult" = 10)
|
||||
embed_type = /datum/embed_data/esword
|
||||
|
||||
/obj/item/melee/energy/sword/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
|
||||
if(!HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE))
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
icon_state = "gumball"
|
||||
damage = 0
|
||||
speed = 0.5
|
||||
embedding = null
|
||||
embed_type = null
|
||||
|
||||
/obj/projectile/bullet/gumball/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -219,29 +219,30 @@
|
||||
icon_state = "lollipop_1"
|
||||
damage = 0
|
||||
speed = 0.5
|
||||
embedding = null
|
||||
embed_type = null
|
||||
var/head_color
|
||||
|
||||
/obj/projectile/bullet/lollipop/harmful
|
||||
embedding = list(
|
||||
embed_chance = 35,
|
||||
fall_chance = 2,
|
||||
jostle_chance = 0,
|
||||
ignore_throwspeed_threshold = TRUE,
|
||||
pain_stam_pct = 0.5,
|
||||
pain_mult = 3,
|
||||
rip_time = 10,
|
||||
)
|
||||
embed_type = /datum/embed_data/lollipop
|
||||
damage = 10
|
||||
shrapnel_type = /obj/item/food/lollipop/cyborg
|
||||
embed_falloff_tile = 0
|
||||
|
||||
/datum/embed_data/lollipop
|
||||
embed_chance = 35
|
||||
fall_chance = 2
|
||||
jostle_chance = 0
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
pain_stam_pct = 0.5
|
||||
pain_mult = 3
|
||||
rip_time = 10
|
||||
|
||||
/obj/projectile/bullet/lollipop/Initialize(mapload)
|
||||
. = ..()
|
||||
var/mutable_appearance/head = mutable_appearance('icons/obj/weapons/guns/projectiles.dmi', "lollipop_2")
|
||||
head.color = head_color = rgb(rand(0, 255), rand(0, 255), rand(0, 255))
|
||||
add_overlay(head)
|
||||
if(!embedding)
|
||||
if(!embed_type)
|
||||
AddElement(/datum/element/projectile_drop, /obj/item/food/lollipop/cyborg)
|
||||
RegisterSignals(src, list(COMSIG_PROJECTILE_ON_SPAWN_DROP, COMSIG_PROJECTILE_ON_SPAWN_EMBEDDED), PROC_REF(handle_drop))
|
||||
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
name = "bullet"
|
||||
icon = 'icons/obj/weapons/guns/ammo.dmi'
|
||||
icon_state = "s-casing"
|
||||
embedding = null // embedding vars are taken from the projectile itself
|
||||
|
||||
embed_type = null
|
||||
|
||||
/obj/projectile/bullet/shrapnel
|
||||
name = "flying shrapnel shard"
|
||||
@@ -34,7 +33,12 @@
|
||||
ignore_range_hit_prone_targets = TRUE
|
||||
sharpness = SHARP_EDGED
|
||||
wound_bonus = 30
|
||||
embedding = list(embed_chance=70, ignore_throwspeed_threshold=TRUE, fall_chance=1)
|
||||
embed_type = /datum/embed_data/shrapnel
|
||||
|
||||
/datum/embed_data/shrapnel
|
||||
embed_chance = 70
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
fall_chance = 1
|
||||
|
||||
/obj/projectile/bullet/shrapnel/short_range
|
||||
range = 5
|
||||
@@ -70,7 +74,17 @@
|
||||
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)
|
||||
embed_type = /datum/embed_data/stingball
|
||||
|
||||
/datum/embed_data/stingball
|
||||
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/on_ricochet(atom/A)
|
||||
hit_prone_targets = TRUE // ducking will save you from the first wave, but not the rebounds
|
||||
@@ -92,10 +106,20 @@
|
||||
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)
|
||||
embed_type = /datum/embed_data/capmine
|
||||
wound_falloff_tile = 0
|
||||
embed_falloff_tile = 0
|
||||
|
||||
/datum/embed_data/capmine
|
||||
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
|
||||
|
||||
/obj/item/shrapnel/capmine
|
||||
name = "\improper AP shrapnel shard"
|
||||
custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 0.5)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
throwforce = 20
|
||||
throw_speed = 4
|
||||
demolition_mod = 0.75
|
||||
embedding = list("impact_pain_mult" = 2, "remove_pain_mult" = 4, "jostle_chance" = 2.5)
|
||||
embed_type = /datum/embed_data/spear
|
||||
armour_penetration = 10
|
||||
custom_materials = list(/datum/material/iron = HALF_SHEET_MATERIAL_AMOUNT, /datum/material/glass= HALF_SHEET_MATERIAL_AMOUNT * 2)
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
@@ -32,6 +32,11 @@
|
||||
/// How much damage to do wielded
|
||||
var/force_wielded = 18
|
||||
|
||||
/datum/embed_data/spear
|
||||
impact_pain_mult = 2
|
||||
remove_pain_mult = 4
|
||||
jostle_chance = 2.5
|
||||
|
||||
/datum/armor/item_spear
|
||||
fire = 50
|
||||
acid = 30
|
||||
|
||||
@@ -33,13 +33,16 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
|
||||
attack_verb_continuous = list("hits", "bludgeons", "whacks")
|
||||
attack_verb_simple = list("hit", "bludgeon", "whack")
|
||||
hitsound = 'sound/weapons/gun/general/grenade_launch.ogg'
|
||||
embedding = list(embed_chance = 50)
|
||||
embed_type = /datum/embed_data/rods
|
||||
novariants = TRUE
|
||||
matter_amount = 2
|
||||
cost = HALF_SHEET_MATERIAL_AMOUNT
|
||||
source = /datum/robot_energy_storage/material/iron
|
||||
merge_type = /obj/item/stack/rods
|
||||
|
||||
/datum/embed_data/rods
|
||||
embed_chance = 50
|
||||
|
||||
/obj/item/stack/rods/suicide_act(mob/living/carbon/user)
|
||||
user.visible_message(span_suicide("[user] begins to stuff \the [src] down [user.p_their()] throat! It looks like [user.p_theyre()] trying to commit suicide!"))//it looks like theyre ur mum
|
||||
return BRUTELOSS
|
||||
|
||||
@@ -293,7 +293,16 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
|
||||
var/shiv_type = /obj/item/knife/shiv
|
||||
var/craft_time = 3.5 SECONDS
|
||||
var/obj/item/stack/sheet/weld_material = /obj/item/stack/sheet/glass
|
||||
embedding = list("embed_chance" = 65)
|
||||
embed_type = /datum/embed_data/shard
|
||||
|
||||
/datum/embed_data/shard
|
||||
embed_chance = 65
|
||||
|
||||
/datum/embed_data/glass_candy
|
||||
embed_chance = 100
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
impact_pain_mult = 1
|
||||
pain_chance = 5
|
||||
|
||||
/datum/armor/item_shard
|
||||
melee = 100
|
||||
|
||||
@@ -14,12 +14,17 @@
|
||||
grind_results = list(/datum/reagent/cellulose = 5)
|
||||
splint_factor = 0.65
|
||||
merge_type = /obj/item/stack/sticky_tape
|
||||
var/list/conferred_embed = EMBED_HARMLESS
|
||||
var/conferred_embed = /datum/embed_data/sticky_tape
|
||||
///The tape type you get when ripping off a piece of tape.
|
||||
var/obj/tape_gag = /obj/item/clothing/mask/muzzle/tape
|
||||
greyscale_config = /datum/greyscale_config/tape
|
||||
greyscale_colors = "#B2B2B2#BD6A62"
|
||||
|
||||
/datum/embed_data/sticky_tape
|
||||
pain_mult = 0
|
||||
jostle_pain_mult = 0
|
||||
ignore_throwspeed_threshold = 0
|
||||
|
||||
/obj/item/stack/sticky_tape/attack_hand(mob/user, list/modifiers)
|
||||
if(user.get_inactive_held_item() == src)
|
||||
if(is_zero_amount(delete_if_zero = TRUE))
|
||||
@@ -43,7 +48,7 @@
|
||||
if(!isitem(target))
|
||||
return NONE
|
||||
|
||||
if(target.embedding && target.embedding == conferred_embed)
|
||||
if(target.get_embed()?.type == conferred_embed)
|
||||
to_chat(user, span_warning("[target] is already coated in [src]!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
@@ -60,12 +65,11 @@
|
||||
user.put_in_hands(O)
|
||||
return ITEM_INTERACT_SUCCESS
|
||||
|
||||
if(target.embedding && target.embedding == conferred_embed)
|
||||
if(target.get_embed() && target.get_embed().type == conferred_embed)
|
||||
to_chat(user, span_warning("[target] is already coated in [src]!"))
|
||||
return ITEM_INTERACT_BLOCKING
|
||||
|
||||
target.embedding = conferred_embed
|
||||
target.updateEmbedding()
|
||||
target.set_embed(conferred_embed)
|
||||
to_chat(user, span_notice("You finish wrapping [target] with [src]."))
|
||||
target.name = "[prefix] [target.name]"
|
||||
|
||||
@@ -80,34 +84,44 @@
|
||||
singular_name = "super sticky tape"
|
||||
desc = "Quite possibly the most mischevious substance in the galaxy. Use with extreme lack of caution."
|
||||
prefix = "super sticky"
|
||||
conferred_embed = EMBED_HARMLESS_SUPERIOR
|
||||
conferred_embed = /datum/embed_data/sticky_tape/super
|
||||
splint_factor = 0.4
|
||||
merge_type = /obj/item/stack/sticky_tape/super
|
||||
greyscale_colors = "#4D4D4D#75433F"
|
||||
tape_gag = /obj/item/clothing/mask/muzzle/tape/super
|
||||
|
||||
/datum/embed_data/sticky_tape/super
|
||||
embed_chance = 100
|
||||
fall_chance = 0.1
|
||||
|
||||
/obj/item/stack/sticky_tape/pointy
|
||||
name = "pointy tape"
|
||||
singular_name = "pointy tape"
|
||||
desc = "Used for sticking to things for sticking said things inside people."
|
||||
icon_state = "tape_spikes"
|
||||
prefix = "pointy"
|
||||
conferred_embed = EMBED_POINTY
|
||||
conferred_embed = /datum/embed_data/pointy_tape
|
||||
merge_type = /obj/item/stack/sticky_tape/pointy
|
||||
greyscale_config = /datum/greyscale_config/tape/spikes
|
||||
greyscale_colors = "#E64539#808080#AD2F45"
|
||||
tape_gag = /obj/item/clothing/mask/muzzle/tape/pointy
|
||||
|
||||
/datum/embed_data/pointy_tape
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
|
||||
/obj/item/stack/sticky_tape/pointy/super
|
||||
name = "super pointy tape"
|
||||
singular_name = "super pointy tape"
|
||||
desc = "You didn't know tape could look so sinister. Welcome to Space Station 13."
|
||||
prefix = "super pointy"
|
||||
conferred_embed = EMBED_POINTY_SUPERIOR
|
||||
conferred_embed = /datum/embed_data/pointy_tape/super
|
||||
merge_type = /obj/item/stack/sticky_tape/pointy/super
|
||||
greyscale_colors = "#8C0A00#4F4F4F#300008"
|
||||
tape_gag = /obj/item/clothing/mask/muzzle/tape/pointy/super
|
||||
|
||||
/datum/embed_data/pointy_tape/super
|
||||
embed_chance = 100
|
||||
|
||||
/obj/item/stack/sticky_tape/surgical
|
||||
name = "surgical tape"
|
||||
singular_name = "surgical tape"
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
throwforce = 0
|
||||
throw_speed = 1
|
||||
embedding = EMBED_HARMLESS
|
||||
custom_materials = list(/datum/material/iron= HALF_SHEET_MATERIAL_AMOUNT)
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_verb_continuous = list("pokes", "jabs", "pins the tail on")
|
||||
@@ -15,6 +14,12 @@
|
||||
sharpness = SHARP_POINTY
|
||||
max_integrity = 200
|
||||
layer = CORGI_ASS_PIN_LAYER
|
||||
embed_type = /datum/embed_data/corgi_pin
|
||||
|
||||
/datum/embed_data/corgi_pin
|
||||
pain_chance = 0
|
||||
jostle_pain_mult = 0
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
|
||||
/obj/item/poster/tail_board
|
||||
name = "party game poster"
|
||||
|
||||
@@ -387,7 +387,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
force = 2
|
||||
throwforce = 10 //10 + 2 (WEIGHT_CLASS_SMALL) * 4 (EMBEDDED_IMPACT_PAIN_MULTIPLIER) = 18 damage on hit due to guaranteed embedding
|
||||
throw_speed = 4
|
||||
embedding = list("pain_mult" = 4, "embed_chance" = 100, "fall_chance" = 0)
|
||||
embed_type = /datum/embed_data/throwing_star
|
||||
armour_penetration = 40
|
||||
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
@@ -395,11 +395,22 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
custom_materials = list(/datum/material/iron= SMALL_MATERIAL_AMOUNT * 5, /datum/material/glass= SMALL_MATERIAL_AMOUNT * 5)
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
/datum/embed_data/throwing_star
|
||||
pain_mult = 4
|
||||
embed_chance = 100
|
||||
fall_chance = 0
|
||||
|
||||
/obj/item/throwing_star/stamina
|
||||
name = "shock throwing star"
|
||||
desc = "An aerodynamic disc designed to cause excruciating pain when stuck inside fleeing targets, hopefully without causing fatal harm."
|
||||
throwforce = 5
|
||||
embedding = list("pain_chance" = 5, "embed_chance" = 100, "fall_chance" = 0, "jostle_chance" = 10, "pain_stam_pct" = 0.8, "jostle_pain_mult" = 3)
|
||||
embed_type = /datum/embed_data/throwing_star/stamina
|
||||
|
||||
/datum/embed_data/throwing_star/stamina
|
||||
pain_mult = 5
|
||||
jostle_chance = 10
|
||||
pain_stam_pct = 0.8
|
||||
jostle_pain_mult = 3
|
||||
|
||||
/obj/item/throwing_star/toy
|
||||
name = "toy throwing star"
|
||||
@@ -407,7 +418,11 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
sharpness = NONE
|
||||
force = 0
|
||||
throwforce = 0
|
||||
embedding = list("pain_mult" = 0, "jostle_pain_mult" = 0, "embed_chance" = 100, "fall_chance" = 0)
|
||||
embed_type = /datum/embed_data/throwing_star/toy
|
||||
|
||||
/datum/embed_data/throwing_star/toy
|
||||
pain_mult = 0
|
||||
jostle_pain_mult = 0
|
||||
|
||||
/obj/item/switchblade
|
||||
name = "switchblade"
|
||||
@@ -1082,7 +1097,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
throwforce = 25
|
||||
throw_speed = 4
|
||||
attack_speed = CLICK_CD_HYPER_RAPID
|
||||
embedding = list("embed_chance" = 100)
|
||||
embed_type = /datum/embed_data/hfr_blade
|
||||
block_chance = 25
|
||||
block_sound = 'sound/weapons/parry.ogg'
|
||||
sharpness = SHARP_EDGED
|
||||
@@ -1097,6 +1112,9 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
/// The previous target we attacked
|
||||
var/datum/weakref/previous_target
|
||||
|
||||
/datum/embed_data/hfr_blade
|
||||
embed_chance = 100
|
||||
|
||||
/obj/item/highfrequencyblade/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/two_handed, \
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
force = 0
|
||||
throwforce = 0
|
||||
hitsound = null
|
||||
embedding = null
|
||||
embed_type = null
|
||||
light_color = COLOR_YELLOW
|
||||
sword_color_icon = "bananium"
|
||||
active_heat = 0
|
||||
|
||||
@@ -15,15 +15,7 @@
|
||||
attack_verb_continuous = list("attacks", "slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "rends")
|
||||
attack_verb_simple = list("attack", "slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "rend")
|
||||
actions_types = list(/datum/action/item_action/rune_shatter)
|
||||
embedding = list(
|
||||
ignore_throwspeed_threshold = TRUE,
|
||||
embed_chance = 75,
|
||||
jostle_chance = 2,
|
||||
jostle_pain_mult = 5,
|
||||
pain_stam_pct = 0.4,
|
||||
pain_mult = 3,
|
||||
rip_time = 15,
|
||||
)
|
||||
embed_type = /datum/embed_data/rune_carver
|
||||
|
||||
/// Whether we're currently drawing a rune
|
||||
var/drawing = FALSE
|
||||
@@ -34,6 +26,15 @@
|
||||
/// Turfs that you cannot draw carvings on
|
||||
var/static/list/blacklisted_turfs = typecacheof(list(/turf/open/space, /turf/open/openspace, /turf/open/lava))
|
||||
|
||||
/datum/embed_data/rune_carver
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
embed_chance = 75
|
||||
jostle_chance = 2
|
||||
jostle_pain_mult = 5
|
||||
pain_stam_pct = 0.4
|
||||
pain_mult = 3
|
||||
rip_time = 15
|
||||
|
||||
/obj/item/melee/rune_carver/examine(mob/user)
|
||||
. = ..()
|
||||
if(!IS_HERETIC_OR_MONSTER(user) && !isobserver(user))
|
||||
|
||||
@@ -43,9 +43,12 @@ GLOBAL_DATUM(global_funny_embedding, /datum/global_funny_embedding)
|
||||
* Makes every item in the world embed when thrown, but also hooks into global signals for new items created to also bless them with embed-ability(??).
|
||||
*/
|
||||
/datum/global_funny_embedding
|
||||
var/embed_type = EMBED_POINTY
|
||||
var/embed_type = /datum/embed_data/global_funny
|
||||
var/prefix = "error"
|
||||
|
||||
/datum/embed_data/global_funny
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
|
||||
/datum/global_funny_embedding/New()
|
||||
. = ..()
|
||||
//second operation takes MUCH longer, so lets set up signals first.
|
||||
@@ -61,11 +64,11 @@ GLOBAL_DATUM(global_funny_embedding, /datum/global_funny_embedding)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
// this proc says it's for initializing components, but we're initializing elements too because it's you and me against the world >:)
|
||||
if(LAZYLEN(created_item.embedding))
|
||||
return //already embeds to some degree, so whatever 🐀
|
||||
created_item.embedding = embed_type
|
||||
if(created_item.get_embed())
|
||||
return //already embeds to some degree, so whatever // No rat allowed
|
||||
|
||||
created_item.name = "[prefix] [created_item.name]"
|
||||
created_item.updateEmbedding()
|
||||
created_item.set_embed(embed_type)
|
||||
|
||||
/**
|
||||
* ### handle_current_items
|
||||
@@ -77,17 +80,20 @@ GLOBAL_DATUM(global_funny_embedding, /datum/global_funny_embedding)
|
||||
CHECK_TICK
|
||||
if(!(embed_item.flags_1 & INITIALIZED_1))
|
||||
continue
|
||||
if(!embed_item.embedding)
|
||||
embed_item.embedding = embed_type
|
||||
embed_item.updateEmbedding()
|
||||
if(embed_item.get_embed())
|
||||
continue
|
||||
embed_item.set_embed(embed_type)
|
||||
embed_item.name = "[prefix] [embed_item.name]"
|
||||
|
||||
///everything will be... POINTY!!!!
|
||||
/datum/global_funny_embedding/pointy
|
||||
embed_type = EMBED_POINTY
|
||||
prefix = "pointy"
|
||||
|
||||
///everything will be... sticky? sure, why not
|
||||
/datum/global_funny_embedding/sticky
|
||||
embed_type = EMBED_HARMLESS
|
||||
embed_type = /datum/embed_data/global_funny/sticky
|
||||
prefix = "sticky"
|
||||
|
||||
/datum/embed_data/global_funny/sticky
|
||||
pain_mult = 0
|
||||
jostle_pain_mult = 0
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
throw_speed = 2
|
||||
block_chance = 0
|
||||
throwforce = 0
|
||||
embedding = null
|
||||
embed_type = null
|
||||
sword_color_icon = null
|
||||
|
||||
active_throwforce = 0
|
||||
|
||||
@@ -478,13 +478,18 @@
|
||||
throwforce = 15
|
||||
throw_speed = 4
|
||||
throw_range = 7
|
||||
embedding = list("pain_mult" = 4, "embed_chance" = 35, "fall_chance" = 10)
|
||||
embed_type = /datum/embed_data/hatchet
|
||||
custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT*7.5)
|
||||
attack_verb_continuous = list("chops", "tears", "lacerates", "cuts")
|
||||
attack_verb_simple = list("chop", "tear", "lacerate", "cut")
|
||||
hitsound = 'sound/weapons/bladeslice.ogg'
|
||||
sharpness = SHARP_EDGED
|
||||
|
||||
/datum/embed_data/hatchet
|
||||
pain_mult = 4
|
||||
embed_chance = 35
|
||||
fall_chance = 10
|
||||
|
||||
/obj/item/hatchet/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/butchering, \
|
||||
|
||||
@@ -859,12 +859,15 @@
|
||||
return
|
||||
|
||||
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
|
||||
if(our_seed.get_gene(/datum/plant_gene/trait/stinging))
|
||||
our_plant.embedding = EMBED_POINTY
|
||||
else
|
||||
our_plant.embedding = EMBED_HARMLESS
|
||||
our_plant.updateEmbedding()
|
||||
our_plant.throwforce = (our_seed.potency/20)
|
||||
if (!our_plant.get_embed())
|
||||
return
|
||||
|
||||
if(our_seed.get_gene(/datum/plant_gene/trait/stinging))
|
||||
our_plant.set_embed(our_plant.get_embed().generate_with_values(ignore_throwspeed_threshold = TRUE))
|
||||
return
|
||||
|
||||
our_plant.set_embed(our_plant.get_embed().generate_with_values(ignore_throwspeed_threshold = TRUE, pain_mult = 0, jostle_pain_mult = 0))
|
||||
|
||||
/**
|
||||
* This trait automatically heats up the plant's chemical contents when harvested.
|
||||
|
||||
@@ -415,7 +415,7 @@
|
||||
// this way, we only visibly try to examine ourselves if we have something embedded, otherwise we'll still hug ourselves :)
|
||||
visible_message(span_notice("[src] examines [p_them()]self."), \
|
||||
span_notice("You check yourself for shrapnel."))
|
||||
if(I.isEmbedHarmless())
|
||||
if(I.is_embed_harmless())
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] stuck to your [LB.name]!</a>")
|
||||
else
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] embedded in your [LB.name]!</a>")
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
var/list/msg = list("<span class='warning'>")
|
||||
for(var/obj/item/bodypart/bodypart as anything in bodyparts)
|
||||
for(var/obj/item/embedded_item as anything in bodypart.embedded_objects)
|
||||
if(embedded_item.isEmbedHarmless())
|
||||
if(embedded_item.is_embed_harmless())
|
||||
msg += "<B>[t_He] [t_has] [icon2html(embedded_item, user)] \a [embedded_item] stuck to [t_his] [bodypart.name]!</B>\n"
|
||||
else
|
||||
msg += "<B>[t_He] [t_has] [icon2html(embedded_item, user)] \a [embedded_item] embedded in [t_his] [bodypart.name]!</B>\n"
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
disabled += body_part
|
||||
missing -= body_part.body_zone
|
||||
for(var/obj/item/I in body_part.embedded_objects)
|
||||
if(I.isEmbedHarmless())
|
||||
if(I.is_embed_harmless())
|
||||
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] [icon2html(I, user)] \a [I] embedded in [t_his] [body_part.name]!</B>\n"
|
||||
|
||||
@@ -375,7 +375,7 @@
|
||||
name = "mending globule"
|
||||
icon_state = "glob_projectile"
|
||||
shrapnel_type = /obj/item/mending_globule
|
||||
embedding = list("embed_chance" = 100, ignore_throwspeed_threshold = TRUE, "pain_mult" = 0, "jostle_pain_mult" = 0, "fall_chance" = 0.5)
|
||||
embed_type = /datum/embed_data/mending_globule
|
||||
damage = 0
|
||||
|
||||
///This item is what is embedded into the mob, and actually handles healing of mending globules
|
||||
@@ -384,10 +384,17 @@
|
||||
desc = "It somehow heals those who touch it."
|
||||
icon = 'icons/obj/science/vatgrowing.dmi'
|
||||
icon_state = "globule"
|
||||
embedding = list("embed_chance" = 100, ignore_throwspeed_threshold = TRUE, "pain_mult" = 0, "jostle_pain_mult" = 0, "fall_chance" = 0.5)
|
||||
embed_type = /datum/embed_data/mending_globule
|
||||
var/obj/item/bodypart/bodypart
|
||||
var/heals_left = 35
|
||||
|
||||
/datum/embed_data/mending_globule
|
||||
embed_chance = 100
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
pain_mult = 0
|
||||
jostle_pain_mult = 0
|
||||
fall_chance = 0.5
|
||||
|
||||
/obj/item/mending_globule/Destroy()
|
||||
. = ..()
|
||||
bodypart = null
|
||||
|
||||
@@ -559,7 +559,7 @@
|
||||
light_range = 1
|
||||
light_power = 1
|
||||
light_color = COLOR_LIGHT_ORANGE
|
||||
embedding = null
|
||||
embed_type = null
|
||||
|
||||
/obj/projectile/bullet/mining_bomb/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
var/degrees = 0
|
||||
var/font = PEN_FONT
|
||||
var/requires_gravity = TRUE // can you use this to write in zero-g
|
||||
embedding = list(embed_chance = 50)
|
||||
embed_type = /datum/embed_data/pen
|
||||
sharpness = SHARP_POINTY
|
||||
var/dart_insert_icon = 'icons/obj/weapons/guns/toy.dmi'
|
||||
var/dart_insert_casing_icon_state = "overlay_pen"
|
||||
@@ -37,6 +37,9 @@
|
||||
/// If this pen can be clicked in order to retract it
|
||||
var/can_click = TRUE
|
||||
|
||||
/datum/embed_data/pen
|
||||
embed_chance = 50
|
||||
|
||||
/obj/item/pen/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/dart_insert, \
|
||||
@@ -86,7 +89,7 @@
|
||||
return list(
|
||||
"damage" = max(5, throwforce),
|
||||
"speed" = max(0, throw_speed - 3),
|
||||
"embedding" = embedding,
|
||||
"embedding" = get_embed(),
|
||||
"armour_penetration" = armour_penetration,
|
||||
"wound_bonus" = wound_bonus,
|
||||
"bare_wound_bonus" = bare_wound_bonus,
|
||||
@@ -191,7 +194,7 @@
|
||||
"Black and Silver" = "pen-fountain-b",
|
||||
"Command Blue" = "pen-fountain-cb"
|
||||
)
|
||||
embedding = list("embed_chance" = 75)
|
||||
embed_type = /datum/embed_data/pen/captain
|
||||
dart_insert_casing_icon_state = "overlay_fountainpen_gold"
|
||||
dart_insert_projectile_icon_state = "overlay_fountainpen_gold_proj"
|
||||
var/list/overlay_reskin = list(
|
||||
@@ -202,6 +205,9 @@
|
||||
"Command Blue" = "overlay_fountainpen_gold"
|
||||
)
|
||||
|
||||
/datum/embed_data/pen/captain
|
||||
embed_chance = 50
|
||||
|
||||
/obj/item/pen/fountain/captain/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/butchering, \
|
||||
@@ -414,7 +420,7 @@
|
||||
inhand_icon_state = hidden_icon
|
||||
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
||||
embedding = list(embed_chance = 100) // Rule of cool
|
||||
set_embed(/datum/embed_data/edagger_active)
|
||||
else
|
||||
name = initial(name)
|
||||
desc = initial(desc)
|
||||
@@ -422,15 +428,17 @@
|
||||
inhand_icon_state = initial(inhand_icon_state)
|
||||
lefthand_file = initial(lefthand_file)
|
||||
righthand_file = initial(righthand_file)
|
||||
embedding = list(embed_chance = EMBED_CHANCE)
|
||||
set_embed(embed_type)
|
||||
|
||||
updateEmbedding()
|
||||
if(user)
|
||||
balloon_alert(user, "[hidden_name] [active ? "active" : "concealed"]")
|
||||
playsound(src, active ? 'sound/weapons/saberon.ogg' : 'sound/weapons/saberoff.ogg', 5, TRUE)
|
||||
set_light_on(active)
|
||||
return COMPONENT_NO_DEFAULT_MESSAGE
|
||||
|
||||
/datum/embed_data/edagger_active
|
||||
embed_chance = 100
|
||||
|
||||
/obj/item/pen/edagger/proc/on_scan(datum/source, mob/user, list/extra_data)
|
||||
SIGNAL_HANDLER
|
||||
LAZYADD(extra_data[DETSCAN_CATEGORY_ILLEGAL], "Hard-light generator detected.")
|
||||
|
||||
@@ -33,16 +33,17 @@
|
||||
speed = 1
|
||||
range = 25
|
||||
shrapnel_type = null
|
||||
embedding = list(
|
||||
embed_chance = 90,
|
||||
fall_chance = 2,
|
||||
jostle_chance = 2,
|
||||
ignore_throwspeed_threshold = TRUE,
|
||||
pain_stam_pct = 0.5,
|
||||
pain_mult = 3,
|
||||
jostle_pain_mult = 3,
|
||||
embed_type = /datum/embed_data/arrow
|
||||
|
||||
/datum/embed_data/arrow
|
||||
embed_chance = 90
|
||||
fall_chance = 2
|
||||
jostle_chance = 2
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
pain_stam_pct = 0.5
|
||||
pain_mult = 3
|
||||
jostle_pain_mult = 3
|
||||
rip_time = 1 SECONDS
|
||||
)
|
||||
|
||||
/// holy arrows
|
||||
/obj/item/ammo_casing/arrow/holy
|
||||
@@ -99,7 +100,7 @@
|
||||
desc = "THE UNMATCHED POWER OF THE SUN"
|
||||
icon_state = "holy_arrow_projectile"
|
||||
damage = 20
|
||||
embedding = null
|
||||
embed_type = null
|
||||
|
||||
/obj/projectile/bullet/arrow/blazing/on_hit(atom/target, blocked, pierce_hit)
|
||||
. = ..()
|
||||
|
||||
@@ -191,7 +191,9 @@
|
||||
///If defined, on hit we create an item of this type then call hitby() on the hit target with this, mainly used for embedding items (bullets) in targets
|
||||
var/shrapnel_type
|
||||
///If we have a shrapnel_type defined, these embedding stats will be passed to the spawned shrapnel type, which will roll for embedding on the target
|
||||
var/list/embedding
|
||||
var/embed_type
|
||||
///Saves embedding data
|
||||
var/datum/embed_data/embed_data
|
||||
///If TRUE, hit mobs, even if they are lying on the floor and are not our target within MAX_RANGE_HIT_PRONE_TARGETS tiles
|
||||
var/hit_prone_targets = FALSE
|
||||
///if TRUE, ignores the range of MAX_RANGE_HIT_PRONE_TARGETS tiles of hit_prone_targets
|
||||
@@ -218,8 +220,8 @@
|
||||
/obj/projectile/Initialize(mapload)
|
||||
. = ..()
|
||||
decayedRange = range
|
||||
if(embedding)
|
||||
updateEmbedding()
|
||||
if(get_embed())
|
||||
AddElement(/datum/element/embed)
|
||||
AddElement(/datum/element/connect_loc, projectile_connections)
|
||||
|
||||
/obj/projectile/proc/Range()
|
||||
@@ -227,8 +229,8 @@
|
||||
if(wound_bonus != CANT_WOUND)
|
||||
wound_bonus += wound_falloff_tile
|
||||
bare_wound_bonus = max(0, bare_wound_bonus + wound_falloff_tile)
|
||||
if(embedding)
|
||||
embedding["embed_chance"] += embed_falloff_tile
|
||||
if(get_embed())
|
||||
set_embed(embed_data.generate_with_values(embed_data.embed_chance + embed_falloff_tile)) // Should be rewritten in projecitle refactor
|
||||
if(damage_falloff_tile && damage >= 0)
|
||||
damage += damage_falloff_tile
|
||||
if(stamina_falloff_tile && stamina >= 0)
|
||||
@@ -1130,26 +1132,6 @@
|
||||
/obj/projectile/experience_pressure_difference()
|
||||
return
|
||||
|
||||
///Like [/obj/item/proc/updateEmbedding] but for projectiles instead, call this when you want to add embedding or update the stats on the embedding element
|
||||
/obj/projectile/proc/updateEmbedding()
|
||||
if(!shrapnel_type || !LAZYLEN(embedding))
|
||||
return
|
||||
|
||||
AddElement(/datum/element/embed,\
|
||||
embed_chance = (!isnull(embedding["embed_chance"]) ? embedding["embed_chance"] : EMBED_CHANCE),\
|
||||
fall_chance = (!isnull(embedding["fall_chance"]) ? embedding["fall_chance"] : EMBEDDED_ITEM_FALLOUT),\
|
||||
pain_chance = (!isnull(embedding["pain_chance"]) ? embedding["pain_chance"] : EMBEDDED_PAIN_CHANCE),\
|
||||
pain_mult = (!isnull(embedding["pain_mult"]) ? embedding["pain_mult"] : EMBEDDED_PAIN_MULTIPLIER),\
|
||||
remove_pain_mult = (!isnull(embedding["remove_pain_mult"]) ? embedding["remove_pain_mult"] : EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER),\
|
||||
rip_time = (!isnull(embedding["rip_time"]) ? embedding["rip_time"] : EMBEDDED_UNSAFE_REMOVAL_TIME),\
|
||||
ignore_throwspeed_threshold = (!isnull(embedding["ignore_throwspeed_threshold"]) ? embedding["ignore_throwspeed_threshold"] : FALSE),\
|
||||
impact_pain_mult = (!isnull(embedding["impact_pain_mult"]) ? embedding["impact_pain_mult"] : EMBEDDED_IMPACT_PAIN_MULTIPLIER),\
|
||||
jostle_chance = (!isnull(embedding["jostle_chance"]) ? embedding["jostle_chance"] : EMBEDDED_JOSTLE_CHANCE),\
|
||||
jostle_pain_mult = (!isnull(embedding["jostle_pain_mult"]) ? embedding["jostle_pain_mult"] : EMBEDDED_JOSTLE_PAIN_MULTIPLIER),\
|
||||
pain_stam_pct = (!isnull(embedding["pain_stam_pct"]) ? embedding["pain_stam_pct"] : EMBEDDED_PAIN_STAM_PCT),\
|
||||
projectile_payload = shrapnel_type)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Is this projectile considered "hostile"?
|
||||
*
|
||||
@@ -1169,7 +1151,7 @@
|
||||
|
||||
///Checks if the projectile can embed into someone
|
||||
/obj/projectile/proc/can_embed_into(atom/hit)
|
||||
return embedding && shrapnel_type && iscarbon(hit) && !HAS_TRAIT(hit, TRAIT_PIERCEIMMUNE)
|
||||
return get_embed() && shrapnel_type && iscarbon(hit) && !HAS_TRAIT(hit, TRAIT_PIERCEIMMUNE)
|
||||
|
||||
/// Reflects the projectile off of something
|
||||
/obj/projectile/proc/reflect(atom/hit_atom)
|
||||
@@ -1212,3 +1194,16 @@
|
||||
bullet.preparePixelProjectile(target, src)
|
||||
bullet.fire()
|
||||
return bullet
|
||||
|
||||
/// Fetches embedding data
|
||||
/obj/projectile/proc/get_embed()
|
||||
return embed_type ? (embed_data ||= get_embed_by_type(embed_type)) : null
|
||||
|
||||
/obj/projectile/proc/set_embed(datum/embed_data/embed)
|
||||
if(embed_data == embed)
|
||||
return
|
||||
// GLOB.embed_by_type stores shared "default" embedding values of datums
|
||||
// Dynamically generated embeds use the base class and thus are not present in there, and should be qdeleted upon being discarded
|
||||
if(!isnull(embed_data) && !GLOB.embed_by_type[embed_data.type])
|
||||
qdel(embed_data)
|
||||
embed_data = ispath(embed) ? get_embed_by_type(armor) : embed
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
sharpness = SHARP_POINTY
|
||||
impact_effect_type = /obj/effect/temp_visual/impact_effect
|
||||
shrapnel_type = /obj/item/shrapnel/bullet
|
||||
embedding = list(embed_chance=20, fall_chance=2, jostle_chance=0, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.5, pain_mult=3, rip_time=10)
|
||||
embed_type = /datum/embed_data/bullet
|
||||
wound_bonus = 0
|
||||
wound_falloff_tile = -5
|
||||
embed_falloff_tile = -3
|
||||
@@ -16,3 +16,12 @@
|
||||
/obj/projectile/bullet/smite
|
||||
name = "divine retribution"
|
||||
damage = 10
|
||||
|
||||
/datum/embed_data/bullet
|
||||
embed_chance=20
|
||||
fall_chance=2
|
||||
jostle_chance=0
|
||||
ignore_throwspeed_threshold=TRUE
|
||||
pain_stam_pct=0.5
|
||||
pain_mult=3
|
||||
rip_time=10
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
pass_flags = PASSTABLE | PASSMOB
|
||||
sharpness = NONE
|
||||
shrapnel_type = null
|
||||
embedding = null
|
||||
embed_type = null
|
||||
impact_effect_type = null
|
||||
suppressed = SUPPRESSED_VERY
|
||||
damage_type = BURN
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
dismemberment = 0
|
||||
paralyze = 5 SECONDS
|
||||
stutter = 20 SECONDS
|
||||
embedding = null
|
||||
embed_type = null
|
||||
hitsound = 'sound/effects/meteorimpact.ogg'
|
||||
hitsound_wall = 'sound/weapons/sonic_jackhammer.ogg'
|
||||
/// If our cannonball hits something, it reduces the damage by this value.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "dart"
|
||||
icon_state = "cbbolt"
|
||||
damage = 6
|
||||
embedding = null
|
||||
embed_type = null
|
||||
shrapnel_type = null
|
||||
var/inject_flags = null
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var/obj/item/dnainjector/injector
|
||||
damage = 5
|
||||
hitsound_wall = SFX_SHATTER
|
||||
embedding = null
|
||||
embed_type = null
|
||||
shrapnel_type = null
|
||||
|
||||
/obj/projectile/bullet/dnainjector/on_hit(atom/target, blocked = 0, pierce_hit)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
base_icon_state = "foamdart"
|
||||
range = 10
|
||||
shrapnel_type = null
|
||||
embedding = null
|
||||
embed_type = null
|
||||
var/modified = FALSE
|
||||
var/obj/item/pen/pen = null
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
desc = "USE A WEEL GUN"
|
||||
icon_state= "bolter"
|
||||
damage = 60
|
||||
embedding = null
|
||||
embed_type = null
|
||||
shrapnel_type = null
|
||||
|
||||
/obj/projectile/bullet/a40mm/on_hit(atom/target, blocked = 0, pierce_hit)
|
||||
|
||||
@@ -4,11 +4,21 @@
|
||||
name = "junk bullet"
|
||||
icon_state = "trashball"
|
||||
damage = 30
|
||||
embedding = list(embed_chance=15, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10)
|
||||
embed_type = /datum/embed_data/bullet_junk
|
||||
var/bane_mob_biotypes = MOB_ROBOTIC
|
||||
var/bane_multiplier = 1.5
|
||||
var/bane_added_damage = 0
|
||||
|
||||
/datum/embed_data/bullet_junk
|
||||
embed_chance=15
|
||||
fall_chance=3
|
||||
jostle_chance=4
|
||||
ignore_throwspeed_threshold=TRUE
|
||||
pain_stam_pct=0.4
|
||||
pain_mult=5
|
||||
jostle_pain_mult=6
|
||||
rip_time=10
|
||||
|
||||
/obj/projectile/bullet/junk/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/bane, mob_biotypes = bane_mob_biotypes, target_type = /mob/living, damage_multiplier = bane_multiplier, added_damage = bane_added_damage, requires_combat_mode = FALSE)
|
||||
@@ -28,7 +38,7 @@
|
||||
name = "bundle of live electrical parts"
|
||||
icon_state = "tesla_projectile"
|
||||
damage = 15
|
||||
embedding = null
|
||||
embed_type = null
|
||||
shrapnel_type = null
|
||||
bane_multiplier = 3
|
||||
|
||||
@@ -49,10 +59,20 @@
|
||||
name = "junk ripper bullet"
|
||||
icon_state = "redtrac"
|
||||
damage = 10
|
||||
embedding = list(embed_chance=100, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10)
|
||||
embed_type = /datum/embed_data/bullet_junk_ripper
|
||||
wound_bonus = 10
|
||||
bare_wound_bonus = 30
|
||||
|
||||
/datum/embed_data/bullet_junk_ripper
|
||||
embed_chance=100
|
||||
fall_chance=3
|
||||
jostle_chance=4
|
||||
ignore_throwspeed_threshold=TRUE
|
||||
pain_stam_pct=0.4
|
||||
pain_mult=5
|
||||
jostle_pain_mult=6
|
||||
rip_time=10
|
||||
|
||||
/obj/projectile/bullet/junk/reaper
|
||||
name = "junk reaper bullet"
|
||||
tracer_type = /obj/effect/projectile/tracer/sniper
|
||||
|
||||
@@ -3,13 +3,23 @@
|
||||
/obj/projectile/bullet/c9mm
|
||||
name = "9mm bullet"
|
||||
damage = 30
|
||||
embedding = list(embed_chance=15, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10)
|
||||
embed_type = /datum/embed_data/bullet_c9mm
|
||||
|
||||
/datum/embed_data/bullet_c9mm
|
||||
embed_chance=15
|
||||
fall_chance=3
|
||||
jostle_chance=4
|
||||
ignore_throwspeed_threshold=TRUE
|
||||
pain_stam_pct=0.4
|
||||
pain_mult=5
|
||||
jostle_pain_mult=6
|
||||
rip_time=10
|
||||
|
||||
/obj/projectile/bullet/c9mm/ap
|
||||
name = "9mm armor-piercing bullet"
|
||||
damage = 27
|
||||
armour_penetration = 40
|
||||
embedding = null
|
||||
embed_type = null
|
||||
shrapnel_type = null
|
||||
|
||||
/obj/projectile/bullet/c9mm/hp
|
||||
|
||||
@@ -21,9 +21,19 @@
|
||||
ricochet_auto_aim_range = 3
|
||||
wound_bonus = -20
|
||||
bare_wound_bonus = 10
|
||||
embedding = list(embed_chance=25, fall_chance=2, jostle_chance=2, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=3, jostle_pain_mult=5, rip_time=1 SECONDS)
|
||||
embed_type = /datum/embed_data/bullet_c38
|
||||
embed_falloff_tile = -4
|
||||
|
||||
/datum/embed_data/bullet_c38
|
||||
embed_chance=25
|
||||
fall_chance=2
|
||||
jostle_chance=2
|
||||
ignore_throwspeed_threshold=TRUE
|
||||
pain_stam_pct=0.4
|
||||
pain_mult=3
|
||||
jostle_pain_mult=5
|
||||
rip_time=1 SECONDS
|
||||
|
||||
/obj/projectile/bullet/c38/match
|
||||
name = ".38 Match bullet"
|
||||
ricochets_max = 4
|
||||
@@ -45,7 +55,7 @@
|
||||
ricochet_decay_damage = 0.8
|
||||
shrapnel_type = null
|
||||
sharpness = NONE
|
||||
embedding = null
|
||||
embed_type = null
|
||||
|
||||
// premium .38 ammo from cargo, weak against armor, lower base damage, but excellent at embedding and causing slice wounds at close range
|
||||
/obj/projectile/bullet/c38/dumdum
|
||||
@@ -56,10 +66,20 @@
|
||||
sharpness = SHARP_EDGED
|
||||
wound_bonus = 20
|
||||
bare_wound_bonus = 20
|
||||
embedding = list(embed_chance=75, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=1 SECONDS)
|
||||
embed_type = /datum/embed_data/bullet_c38_dumdum
|
||||
wound_falloff_tile = -5
|
||||
embed_falloff_tile = -15
|
||||
|
||||
/datum/embed_data/bullet_c38_dumdum
|
||||
embed_chance=75
|
||||
fall_chance=3
|
||||
jostle_chance=4
|
||||
ignore_throwspeed_threshold=TRUE
|
||||
pain_stam_pct=0.4
|
||||
pain_mult=5
|
||||
jostle_pain_mult=6
|
||||
rip_time=1 SECONDS
|
||||
|
||||
/obj/projectile/bullet/c38/trac
|
||||
name = ".38 TRAC bullet"
|
||||
damage = 10
|
||||
|
||||
@@ -48,10 +48,20 @@
|
||||
armour_penetration = 50
|
||||
wound_bonus = -20
|
||||
bare_wound_bonus = 80
|
||||
embedding = list(embed_chance=100, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10)
|
||||
embed_type = /datum/embed_data/harpoon
|
||||
wound_falloff_tile = -5
|
||||
shrapnel_type = null
|
||||
|
||||
/datum/embed_data/harpoon
|
||||
embed_chance=100
|
||||
fall_chance=3
|
||||
jostle_chance=4
|
||||
ignore_throwspeed_threshold=TRUE
|
||||
pain_stam_pct=0.4
|
||||
pain_mult=5
|
||||
jostle_pain_mult=6
|
||||
rip_time=10
|
||||
|
||||
// Rebar (Rebar Crossbow)
|
||||
/obj/projectile/bullet/rebar
|
||||
name = "rebar"
|
||||
@@ -62,11 +72,21 @@
|
||||
armour_penetration = 10
|
||||
wound_bonus = -20
|
||||
bare_wound_bonus = 20
|
||||
embedding = list("embed_chance" = 60, "fall_chance" = 2, "jostle_chance" = 2, "ignore_throwspeed_threshold" = TRUE, "pain_stam_pct" = 0.4, "pain_mult" = 4, "jostle_pain_mult" = 2, "rip_time" = 10)
|
||||
embed_type = /datum/embed_data/rebar
|
||||
embed_falloff_tile = -5
|
||||
wound_falloff_tile = -2
|
||||
shrapnel_type = /obj/item/ammo_casing/rebar
|
||||
|
||||
/datum/embed_data/rebar
|
||||
embed_chance = 60
|
||||
fall_chance = 2
|
||||
jostle_chance = 2
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
pain_stam_pct = 0.4
|
||||
pain_mult = 4
|
||||
jostle_pain_mult = 2
|
||||
rip_time = 10
|
||||
|
||||
/obj/projectile/bullet/rebar/proc/handle_drop(datum/source, obj/item/ammo_casing/rebar/newcasing)
|
||||
|
||||
/obj/projectile/bullet/rebar/syndie
|
||||
@@ -78,10 +98,20 @@
|
||||
armour_penetration = 20 //A bit better versus armor. Gets past anti laser armor or a vest, but doesnt wound proc on sec armor.
|
||||
wound_bonus = 10
|
||||
bare_wound_bonus = 20
|
||||
embedding = list("embed_chance" = 80, "fall_chance" = 1, "jostle_chance" = 3, "ignore_throwspeed_threshold" = TRUE, "pain_stam_pct" = 0.4, "pain_mult" = 3, "jostle_pain_mult" = 2, "rip_time" = 14)
|
||||
embed_falloff_tile = -3
|
||||
embed_type = /datum/embed_data/rebar_syndie
|
||||
shrapnel_type = /obj/item/ammo_casing/rebar/syndie
|
||||
|
||||
/datum/embed_data/rebar_syndie
|
||||
embed_chance = 80
|
||||
fall_chance = 1
|
||||
jostle_chance = 3
|
||||
ignore_throwspeed_threshold
|
||||
pain_stam_pct = 0.4
|
||||
pain_mult = 3
|
||||
jostle_pain_mult = 2
|
||||
rip_time = 14
|
||||
|
||||
/obj/projectile/bullet/rebar/zaukerite
|
||||
name = "zaukerite shard"
|
||||
icon_state = "rebar_zaukerite"
|
||||
@@ -93,10 +123,20 @@
|
||||
armour_penetration = 20 // not nearly as good, as its not as sharp.
|
||||
wound_bonus = 10
|
||||
bare_wound_bonus = 40
|
||||
embedding = list("embed_chance" =100, "fall_chance" = 0, "jostle_chance" = 5, "ignore_throwspeed_threshold" = TRUE, "pain_stam_pct" = 0.8, "pain_mult" = 6, "jostle_pain_mult" = 2, "rip_time" = 30)
|
||||
embed_type = /datum/embed_data/rebar_zaukerite
|
||||
embed_falloff_tile = 0 // very spiky.
|
||||
shrapnel_type = /obj/item/ammo_casing/rebar/zaukerite
|
||||
|
||||
/datum/embed_data/rebar_zaukerite
|
||||
embed_chance = 100
|
||||
fall_chance = 0
|
||||
jostle_chance = 5
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
pain_stam_pct = 0.8
|
||||
pain_mult = 6
|
||||
jostle_pain_mult = 2
|
||||
rip_time = 30
|
||||
|
||||
/obj/projectile/bullet/rebar/hydrogen
|
||||
name = "metallic hydrogen bolt"
|
||||
icon_state = "rebar_hydrogen"
|
||||
@@ -108,10 +148,20 @@
|
||||
projectile_piercing = PASSMOB //felt this might have been a nice compromise for the lower damage for the difficulty of getting it
|
||||
wound_bonus = -15
|
||||
bare_wound_bonus = 10
|
||||
embedding = list("embed_chance" = 50, "fall_chance" = 2, "jostle_chance" = 3, "ignore_throwspeed_threshold" = TRUE, "pain_stam_pct" = 0.6, "pain_mult" = 4, "jostle_pain_mult" = 2, "rip_time" =18)
|
||||
embed_type = /datum/embed_data/rebar_hydrogen
|
||||
embed_falloff_tile = -3
|
||||
shrapnel_type = /obj/item/ammo_casing/rebar/hydrogen
|
||||
|
||||
/datum/embed_data/rebar_hydrogen
|
||||
embed_chance = 50
|
||||
fall_chance = 2
|
||||
jostle_chance = 3
|
||||
ignore_throwspeed_threshold = TRUE
|
||||
pain_stam_pct = 0.6
|
||||
pain_mult = 4
|
||||
jostle_pain_mult = 2
|
||||
rip_time =18
|
||||
|
||||
/obj/projectile/bullet/rebar/healium
|
||||
name = "healium bolt"
|
||||
icon_state = "rebar_healium"
|
||||
@@ -122,7 +172,7 @@
|
||||
armour_penetration = 100
|
||||
wound_bonus = -100
|
||||
bare_wound_bonus = -100
|
||||
embedding = list(embed_chance = 0)
|
||||
embed_type = null
|
||||
embed_falloff_tile = -3
|
||||
shrapnel_type = /obj/item/ammo_casing/rebar/healium
|
||||
|
||||
@@ -139,7 +189,6 @@
|
||||
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
|
||||
/obj/projectile/bullet/rebar/supermatter
|
||||
name = "supermatter bolt"
|
||||
icon_state = "rebar_supermatter"
|
||||
@@ -147,6 +196,7 @@
|
||||
speed = 0.4
|
||||
dismemberment = 0
|
||||
damage_type = TOX
|
||||
embed_type = null
|
||||
armour_penetration = 100
|
||||
shrapnel_type = /obj/item/ammo_casing/rebar/supermatter
|
||||
|
||||
@@ -164,7 +214,6 @@
|
||||
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
|
||||
/obj/projectile/bullet/rebar/supermatter/proc/dust_feedback(atom/target)
|
||||
playsound(get_turf(src), 'sound/effects/supermatter.ogg', 10, TRUE)
|
||||
visible_message(span_danger("[target] is hit by [src], turning [target.p_them()] to dust in a brilliant flash of light!"))
|
||||
@@ -174,7 +223,7 @@
|
||||
damage = 1 // It's a damn toy.
|
||||
range = 10
|
||||
shrapnel_type = null
|
||||
embedding = null
|
||||
embed_type = null
|
||||
name = "paper ball"
|
||||
desc = "doink!"
|
||||
damage_type = BRUTE
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
stamina = 55
|
||||
wound_bonus = 20
|
||||
sharpness = NONE
|
||||
embedding = null
|
||||
embed_type = null
|
||||
|
||||
/obj/projectile/bullet/shotgun_beanbag/a40mm
|
||||
name = "rubber slug"
|
||||
@@ -55,7 +55,7 @@
|
||||
range = 7
|
||||
icon_state = "spark"
|
||||
color = COLOR_YELLOW
|
||||
embedding = null
|
||||
embed_type = null
|
||||
|
||||
/obj/projectile/bullet/shotgun_frag12
|
||||
name ="frag12 slug"
|
||||
@@ -84,7 +84,7 @@
|
||||
damage = 3
|
||||
stamina = 11
|
||||
sharpness = NONE
|
||||
embedding = null
|
||||
embed_type = null
|
||||
speed = 1.2
|
||||
stamina_falloff_tile = -0.25
|
||||
ricochets_max = 4
|
||||
@@ -106,7 +106,7 @@
|
||||
name = "incapacitating pellet"
|
||||
damage = 1
|
||||
stamina = 6
|
||||
embedding = null
|
||||
embed_type = null
|
||||
|
||||
// Mech Scattershot
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
name = "4.6x30mm armor-piercing bullet"
|
||||
damage = 15
|
||||
armour_penetration = 40
|
||||
embedding = null
|
||||
embed_type = null
|
||||
|
||||
/obj/projectile/bullet/incendiary/c46x30mm
|
||||
name = "4.6x30mm incendiary bullet"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
icon = 'icons/obj/service/hydroponics/harvest.dmi'
|
||||
icon_state = "banana"
|
||||
range = 200
|
||||
embedding = null
|
||||
embed_type = null
|
||||
shrapnel_type = null
|
||||
|
||||
/obj/projectile/bullet/honker/Initialize(mapload)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name ="explosive bolt"
|
||||
icon_state= "bolter"
|
||||
damage = 50
|
||||
embedding = null
|
||||
embed_type = null
|
||||
shrapnel_type = null
|
||||
|
||||
/obj/projectile/bullet/gyro/on_hit(atom/target, blocked = 0, pierce_hit)
|
||||
@@ -17,7 +17,7 @@
|
||||
icon_state= "missile"
|
||||
damage = 50
|
||||
sharpness = NONE
|
||||
embedding = null
|
||||
embed_type = null
|
||||
shrapnel_type = null
|
||||
ricochets_max = 0
|
||||
/// Whether we do extra damage when hitting a mech or silicon
|
||||
|
||||
@@ -252,7 +252,7 @@
|
||||
ricochet_auto_aim_angle = 10
|
||||
ricochet_auto_aim_range = 3
|
||||
wound_bonus = -10
|
||||
embedding = null
|
||||
embed_type = null
|
||||
|
||||
/obj/projectile/bullet/c38/holy/on_hit(atom/target, blocked, pierce_hit)
|
||||
. = ..()
|
||||
|
||||
@@ -351,7 +351,7 @@
|
||||
check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [LOWER_TEXT(wound.name)]!!!")]"
|
||||
|
||||
for(var/obj/item/embedded_thing in embedded_objects)
|
||||
var/stuck_word = embedded_thing.isEmbedHarmless() ? "stuck" : "embedded"
|
||||
var/stuck_word = embedded_thing.is_embed_harmless() ? "stuck" : "embedded"
|
||||
check_list += "\t <a href='?src=[REF(examiner)];embedded_object=[REF(embedded_thing)];embedded_limb=[REF(src)]' class='warning'>There is \a [embedded_thing] [stuck_word] in your [name]!</a>"
|
||||
|
||||
/obj/item/bodypart/blob_act()
|
||||
@@ -1096,15 +1096,15 @@
|
||||
if(embed in embedded_objects) // go away
|
||||
return
|
||||
// We don't need to do anything with projectile embedding, because it will never reach this point
|
||||
RegisterSignal(embed, COMSIG_ITEM_EMBEDDING_UPDATE, PROC_REF(embedded_object_changed))
|
||||
embedded_objects += embed
|
||||
RegisterSignal(embed, COMSIG_ITEM_EMBEDDING_UPDATE, PROC_REF(embedded_object_changed))
|
||||
refresh_bleed_rate()
|
||||
|
||||
/// INTERNAL PROC, DO NOT USE
|
||||
/// Cleans up any attachment we have to the embedded object, removes it from our list
|
||||
/obj/item/bodypart/proc/_unembed_object(obj/item/unembed)
|
||||
UnregisterSignal(unembed, COMSIG_ITEM_EMBEDDING_UPDATE)
|
||||
embedded_objects -= unembed
|
||||
UnregisterSignal(unembed, COMSIG_ITEM_EMBEDDING_UPDATE)
|
||||
refresh_bleed_rate()
|
||||
|
||||
/obj/item/bodypart/proc/embedded_object_changed(obj/item/embedded_source)
|
||||
@@ -1157,7 +1157,7 @@
|
||||
cached_bleed_rate += 0.5
|
||||
|
||||
for(var/obj/item/embeddies in embedded_objects)
|
||||
if(!embeddies.isEmbedHarmless())
|
||||
if(!embeddies.is_embed_harmless())
|
||||
cached_bleed_rate += 0.25
|
||||
|
||||
for(var/datum/wound/iter_wound as anything in wounds)
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
/mob/living/carbon/proc/has_embedded_objects(include_harmless=FALSE)
|
||||
for(var/obj/item/bodypart/bodypart as anything in bodyparts)
|
||||
for(var/obj/item/embedded in bodypart.embedded_objects)
|
||||
if(!include_harmless && embedded.isEmbedHarmless())
|
||||
if(!include_harmless && embedded.is_embed_harmless())
|
||||
continue
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -33,10 +33,15 @@
|
||||
attack_verb_continuous = list("stubs", "pokes")
|
||||
attack_verb_simple = list("stub", "poke")
|
||||
sharpness = SHARP_EDGED
|
||||
embedding = list("pain_mult" = 1, "embed_chance" = 30, "fall_chance" = 70)
|
||||
embed_type = /datum/embed_data/janicart_key
|
||||
wound_bonus = -1
|
||||
bare_wound_bonus = 2
|
||||
|
||||
/datum/embed_data/janicart_key
|
||||
pain_mult = 1
|
||||
embed_chance = 30
|
||||
fall_chance = 70
|
||||
|
||||
/obj/item/key/janitor/suicide_act(mob/living/carbon/user)
|
||||
switch(user.mind?.get_skill_level(/datum/skill/cleaning))
|
||||
if(SKILL_LEVEL_NONE to SKILL_LEVEL_NOVICE) //Their mind is too weak to ascend as a janny
|
||||
|
||||
@@ -1074,11 +1074,9 @@ GLOBAL_LIST_EMPTY(vending_machines_to_restock)
|
||||
var/mob/living/carbon/carbon_target = atom_target
|
||||
for(var/i in 1 to num_shards)
|
||||
var/obj/item/shard/shard = new /obj/item/shard(get_turf(carbon_target))
|
||||
shard.embedding = list(embed_chance = 100, ignore_throwspeed_threshold = TRUE, impact_pain_mult = 1, pain_chance = 5)
|
||||
shard.updateEmbedding()
|
||||
shard.set_embed(/datum/embed_data/glass_candy)
|
||||
carbon_target.hitby(shard, skipcatch = TRUE, hitpush = FALSE)
|
||||
shard.embedding = list()
|
||||
shard.updateEmbedding()
|
||||
shard.set_embed(initial(shard.embed_type))
|
||||
return TRUE
|
||||
if (VENDOR_CRUSH_CRIT_PIN) // pin them beneath the machine until someone untilts it
|
||||
if (!isliving(atom_target))
|
||||
|
||||
@@ -776,6 +776,7 @@
|
||||
#include "code\datums\dog_fashion.dm"
|
||||
#include "code\datums\ductnet.dm"
|
||||
#include "code\datums\eigenstate.dm"
|
||||
#include "code\datums\embed_data.dm"
|
||||
#include "code\datums\emotes.dm"
|
||||
#include "code\datums\ert.dm"
|
||||
#include "code\datums\hailer_phrase.dm"
|
||||
|
||||
Reference in New Issue
Block a user