From f4e244fb4922ef5b08d09e46b6ee4a926d59cd43 Mon Sep 17 00:00:00 2001
From: SkyratBot <59378654+SkyratBot@users.noreply.github.com>
Date: Mon, 8 Jul 2024 11:20:05 +0200
Subject: [PATCH] [MIRROR] Refactors embedding to use datums instead of storing
data in bespoke elements (#28699)
* 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
:cl:
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.
/:cl:
* Refactors embedding to use datums instead of storing data in bespoke elements
* modular fixes
* fix c14
* paint -> pain ugggh
---------
Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
Co-authored-by: SpaceLoveSs13 <68121607+SpaceLoveSs13@users.noreply.github.com>
---
code/__DEFINES/combat.dm | 31 +----
code/datums/components/dart_insert.dm | 14 +--
code/datums/components/embedded.dm | 107 +++++++-----------
code/datums/components/tackle.dm | 6 +-
code/datums/elements/caseless.dm | 1 -
code/datums/elements/embed.dm | 97 +++++-----------
code/datums/embed_data.dm | 54 +++++++++
code/datums/mutations/tongue_spike.dm | 28 +++--
code/game/objects/items.dm | 57 +++++-----
code/game/objects/items/grenades/plastic.dm | 5 +-
code/game/objects/items/knives.dm | 15 ++-
code/game/objects/items/melee/energy.dm | 10 +-
code/game/objects/items/robot/items/food.dm | 25 ++--
code/game/objects/items/shrapnel.dm | 34 +++++-
code/game/objects/items/spear.dm | 7 +-
code/game/objects/items/stacks/rods.dm | 5 +-
.../game/objects/items/stacks/sheets/glass.dm | 11 +-
code/game/objects/items/stacks/tape.dm | 30 +++--
code/game/objects/items/tail_pin.dm | 7 +-
code/game/objects/items/weaponry.dm | 26 ++++-
.../antagonists/clown_ops/clown_weapons.dm | 2 +-
.../heretic/structures/carving_knife.dm | 19 ++--
code/modules/events/wizard/embeddies.dm | 28 +++--
code/modules/holodeck/items.dm | 2 +-
code/modules/hydroponics/hydroitemdefines.dm | 7 +-
code/modules/hydroponics/plant_genes.dm | 13 ++-
.../mob/living/carbon/carbon_defense.dm | 2 +-
code/modules/mob/living/carbon/examine.dm | 2 +-
.../mob/living/carbon/human/examine.dm | 2 +-
.../mob/living/simple_animal/hostile/ooze.dm | 11 +-
code/modules/mod/modules/modules_supply.dm | 2 +-
code/modules/paperwork/pen.dm | 20 +++-
.../guns/ballistic/bows/bow_arrows.dm | 41 +++----
code/modules/projectiles/projectile.dm | 47 ++++----
.../modules/projectiles/projectile/bullets.dm | 11 +-
.../projectile/bullets/_incendiary.dm | 2 +-
.../projectile/bullets/cannonball.dm | 2 +-
.../projectile/bullets/dart_syringe.dm | 2 +-
.../projectile/bullets/dnainjector.dm | 2 +-
.../projectile/bullets/foam_dart.dm | 2 +-
.../projectiles/projectile/bullets/grenade.dm | 2 +-
.../projectiles/projectile/bullets/junk.dm | 26 ++++-
.../projectiles/projectile/bullets/pistol.dm | 14 ++-
.../projectile/bullets/revolver.dm | 26 ++++-
.../projectiles/projectile/bullets/rifle.dm | 67 +++++++++--
.../projectiles/projectile/bullets/shotgun.dm | 8 +-
.../projectiles/projectile/bullets/smg.dm | 2 +-
.../projectiles/projectile/bullets/special.dm | 2 +-
.../projectiles/projectile/special/rocket.dm | 4 +-
code/modules/religion/burdened/psyker.dm | 2 +-
code/modules/surgery/bodyparts/_bodyparts.dm | 8 +-
code/modules/surgery/bodyparts/helpers.dm | 2 +-
code/modules/vehicles/vehicle_key.dm | 7 +-
code/modules/vending/_vending.dm | 6 +-
.../modules/cellguns/code/medigun_cells.dm | 11 +-
.../modules/clock_cult/code/items/weaponry.dm | 5 +-
.../modules/exp_corps/code/tomahawk.dm | 7 +-
.../horrorform/code/true_changeling.dm | 12 +-
modular_skyrat/modules/marines/code/gear.dm | 2 +-
.../carwo_defense_systems/ammo/pistol.dm | 22 ++--
.../carwo_defense_systems/ammo/rifle.dm | 20 ++--
.../trappiste_fabriek/ammo.dm | 2 +-
.../xhihao_light_arms/ammo.dm | 2 +-
.../code/modular_projectiles.dm | 8 +-
.../modular_weapons/code/pepperball_gun.dm | 2 +-
.../modules/moretraitoritems/code/weapons.dm | 12 +-
.../reagent_forging/code/forge_weapons.dm | 19 +++-
.../modules/sec_haul/code/guns/bullets.dm | 28 ++++-
.../modules/shotgunrebalance/code/shotgun.dm | 12 +-
.../code/ammo/reusable/arrow.dm | 21 ++--
tgstation.dme | 1 +
71 files changed, 701 insertions(+), 450 deletions(-)
create mode 100644 code/datums/embed_data.dm
diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index 6fc955782ce..dc605fd4955 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -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)
+/// 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
diff --git a/code/datums/components/dart_insert.dm b/code/datums/components/dart_insert.dm
index 19eea67ab3a..ad869903051 100644
--- a/code/datums/components/dart_insert.dm
+++ b/code/datums/components/dart_insert.dm
@@ -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()
diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm
index 45a3c07298f..84bfa8dfad0 100644
--- a/code/datums/components/embedded.dm
+++ b/code/datums/components/embedded.dm
@@ -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
diff --git a/code/datums/components/tackle.dm b/code/datums/components/tackle.dm
index 4f2eb6fa7ad..bd5e01a221f 100644
--- a/code/datums/components/tackle.dm
+++ b/code/datums/components/tackle.dm
@@ -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)
diff --git a/code/datums/elements/caseless.dm b/code/datums/elements/caseless.dm
index 587a32f2b30..9b1c0601207 100644
--- a/code/datums/elements/caseless.dm
+++ b/code/datums/elements/caseless.dm
@@ -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)
diff --git a/code/datums/elements/embed.dm b/code/datums/elements/embed.dm
index 78f28d8b81c..6e83d91c5e7 100644
--- a/code/datums/elements/embed.dm
+++ b/code/datums/elements/embed.dm
@@ -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
diff --git a/code/datums/embed_data.dm b/code/datums/embed_data.dm
new file mode 100644
index 00000000000..ac010d170a8
--- /dev/null
+++ b/code/datums/embed_data.dm
@@ -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
diff --git a/code/datums/mutations/tongue_spike.dm b/code/datums/mutations/tongue_spike.dm
index 9e25ad6f4f2..d5db738213f 100644
--- a/code/datums/mutations/tongue_spike.dm
+++ b/code/datums/mutations/tongue_spike.dm
@@ -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)
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 41a62bda0fa..6b681f69dd0 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -163,8 +163,10 @@
///the icon to indicate this object is being dragged
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
- ///Does it embed and if yes, what kind of embed
- var/list/embedding
+ /// Does it embed and if yes, what kind of embed
+ var/embed_type
+ /// Stores embedding data
+ var/datum/embed_data/embed_data
///for flags such as [GLASSESCOVERSEYES]
var/flags_cover = 0
@@ -267,8 +269,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()
@@ -1288,9 +1290,11 @@
///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()
@@ -1323,11 +1327,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.
@@ -1335,29 +1341,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
@@ -1844,6 +1827,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
diff --git a/code/game/objects/items/grenades/plastic.dm b/code/game/objects/items/grenades/plastic.dm
index 336c9e5e2ee..49f66b06896 100644
--- a/code/game/objects/items/grenades/plastic.dm
+++ b/code/game/objects/items/grenades/plastic.dm
@@ -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
diff --git a/code/game/objects/items/knives.dm b/code/game/objects/items/knives.dm
index 1aa09dbfe68..1a16b08eb86 100644
--- a/code/game/objects/items/knives.dm
+++ b/code/game/objects/items/knives.dm
@@ -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'
diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm
index 74fefa1eaed..cb9cbb5fd82 100644
--- a/code/game/objects/items/melee/energy.dm
+++ b/code/game/objects/items/melee/energy.dm
@@ -123,13 +123,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)
@@ -183,6 +179,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."
@@ -199,7 +199,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))
diff --git a/code/game/objects/items/robot/items/food.dm b/code/game/objects/items/robot/items/food.dm
index 6e9b2143d12..865e5c792e5 100644
--- a/code/game/objects/items/robot/items/food.dm
+++ b/code/game/objects/items/robot/items/food.dm
@@ -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))
diff --git a/code/game/objects/items/shrapnel.dm b/code/game/objects/items/shrapnel.dm
index 9b024cfbb97..701a0a819d0 100644
--- a/code/game/objects/items/shrapnel.dm
+++ b/code/game/objects/items/shrapnel.dm
@@ -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)
diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/spear.dm
index 272c3c2d134..96fbde554b7 100644
--- a/code/game/objects/items/spear.dm
+++ b/code/game/objects/items/spear.dm
@@ -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
diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm
index 5d41f41afcb..5a8e1361c28 100644
--- a/code/game/objects/items/stacks/rods.dm
+++ b/code/game/objects/items/stacks/rods.dm
@@ -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
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index 59196639ffe..a9d71fa127a 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -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
diff --git a/code/game/objects/items/stacks/tape.dm b/code/game/objects/items/stacks/tape.dm
index 57aa666c046..0e054ba8d10 100644
--- a/code/game/objects/items/stacks/tape.dm
+++ b/code/game/objects/items/stacks/tape.dm
@@ -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"
diff --git a/code/game/objects/items/tail_pin.dm b/code/game/objects/items/tail_pin.dm
index de3148dd06d..71bd50b1dda 100644
--- a/code/game/objects/items/tail_pin.dm
+++ b/code/game/objects/items/tail_pin.dm
@@ -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"
diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm
index 1d4883b2c47..5384a11cf3b 100644
--- a/code/game/objects/items/weaponry.dm
+++ b/code/game/objects/items/weaponry.dm
@@ -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, \
diff --git a/code/modules/antagonists/clown_ops/clown_weapons.dm b/code/modules/antagonists/clown_ops/clown_weapons.dm
index 1c55e5416e2..130b6c9af5f 100644
--- a/code/modules/antagonists/clown_ops/clown_weapons.dm
+++ b/code/modules/antagonists/clown_ops/clown_weapons.dm
@@ -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
diff --git a/code/modules/antagonists/heretic/structures/carving_knife.dm b/code/modules/antagonists/heretic/structures/carving_knife.dm
index 9bdad0ea5fc..70133e951af 100644
--- a/code/modules/antagonists/heretic/structures/carving_knife.dm
+++ b/code/modules/antagonists/heretic/structures/carving_knife.dm
@@ -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))
diff --git a/code/modules/events/wizard/embeddies.dm b/code/modules/events/wizard/embeddies.dm
index ea8c5fd176b..8b456894215 100644
--- a/code/modules/events/wizard/embeddies.dm
+++ b/code/modules/events/wizard/embeddies.dm
@@ -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()
- embed_item.name = "[prefix] [embed_item.name]"
+ 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
diff --git a/code/modules/holodeck/items.dm b/code/modules/holodeck/items.dm
index 3d80ef6d968..7a27aecb4bc 100644
--- a/code/modules/holodeck/items.dm
+++ b/code/modules/holodeck/items.dm
@@ -14,7 +14,7 @@
throw_speed = 2
block_chance = 0
throwforce = 0
- embedding = null
+ embed_type = null
sword_color_icon = null
active_throwforce = 0
diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm
index 80f02328008..e55977e2dba 100644
--- a/code/modules/hydroponics/hydroitemdefines.dm
+++ b/code/modules/hydroponics/hydroitemdefines.dm
@@ -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, \
diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm
index 3bf71f9b8bc..952bef1c443 100644
--- a/code/modules/hydroponics/plant_genes.dm
+++ b/code/modules/hydroponics/plant_genes.dm
@@ -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.
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 03056090dd4..5d476058e53 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -461,7 +461,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 There is \a [I] stuck to your [LB.name]!")
else
to_chat(src, "\t There is \a [I] embedded in your [LB.name]!")
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index 071dadac1c0..c71962eb034 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -39,7 +39,7 @@
var/list/msg = list("")
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 += "[t_He] [t_has] [icon2html(embedded_item, user)] \a [embedded_item] stuck to [t_his] [bodypart.name]!\n"
else
msg += "[t_He] [t_has] [icon2html(embedded_item, user)] \a [embedded_item] embedded in [t_his] [bodypart.name]!\n"
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 996c94fa871..ba5836ba167 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -179,7 +179,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 += "[t_He] [t_has] [icon2html(I, user)] \a [I] stuck to [t_his] [body_part.name]!\n"
else
msg += "[t_He] [t_has] [icon2html(I, user)] \a [I] embedded in [t_his] [body_part.name]!\n"
diff --git a/code/modules/mob/living/simple_animal/hostile/ooze.dm b/code/modules/mob/living/simple_animal/hostile/ooze.dm
index e2a9d7659d5..f25fd4dc0fe 100644
--- a/code/modules/mob/living/simple_animal/hostile/ooze.dm
+++ b/code/modules/mob/living/simple_animal/hostile/ooze.dm
@@ -376,7 +376,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
@@ -385,10 +385,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
diff --git a/code/modules/mod/modules/modules_supply.dm b/code/modules/mod/modules/modules_supply.dm
index 8564dabb9ef..701861897dc 100644
--- a/code/modules/mod/modules/modules_supply.dm
+++ b/code/modules/mod/modules/modules_supply.dm
@@ -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)
. = ..()
diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm
index 36949b65c7c..41d24ea9c6d 100644
--- a/code/modules/paperwork/pen.dm
+++ b/code/modules/paperwork/pen.dm
@@ -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.")
diff --git a/code/modules/projectiles/guns/ballistic/bows/bow_arrows.dm b/code/modules/projectiles/guns/ballistic/bows/bow_arrows.dm
index 713790049b5..4ed74bc9793 100644
--- a/code/modules/projectiles/guns/ballistic/bows/bow_arrows.dm
+++ b/code/modules/projectiles/guns/ballistic/bows/bow_arrows.dm
@@ -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,
- rip_time = 1 SECONDS
- )
+ 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
@@ -59,15 +60,15 @@
desc = "Here it comes, cultist scum!"
icon_state = "holy_arrow_projectile"
damage = 20 //still a lot but this is roundstart gear so far less
- embedding = list(
- embed_chance = 50,
- fall_chance = 2,
- jostle_chance = 0,
- ignore_throwspeed_threshold = TRUE,
- pain_stam_pct = 0.5,
- pain_mult = 3,
- rip_time = 1 SECONDS
- )
+
+/datum/embed_data/holy_arrow
+ embed_chance = 50
+ fall_chance = 2
+ jostle_chance = 0
+ ignore_throwspeed_threshold = TRUE
+ pain_stam_pct = 0.5
+ pain_mult = 3
+ rip_time = 1 SECONDS
/obj/projectile/bullet/arrow/holy/Initialize(mapload)
. = ..()
@@ -87,7 +88,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)
. = ..()
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 81055e9d8bc..2f9ed7b44e0 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -190,7 +190,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
@@ -222,8 +224,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()
@@ -231,8 +233,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)
@@ -1148,26 +1150,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"?
*
@@ -1187,7 +1169,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)
@@ -1230,3 +1212,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
diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm
index 5e938c49953..1d1313d9e55 100644
--- a/code/modules/projectiles/projectile/bullets.dm
+++ b/code/modules/projectiles/projectile/bullets.dm
@@ -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
diff --git a/code/modules/projectiles/projectile/bullets/_incendiary.dm b/code/modules/projectiles/projectile/bullets/_incendiary.dm
index 85c2dce80c5..e151afa294d 100644
--- a/code/modules/projectiles/projectile/bullets/_incendiary.dm
+++ b/code/modules/projectiles/projectile/bullets/_incendiary.dm
@@ -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
diff --git a/code/modules/projectiles/projectile/bullets/cannonball.dm b/code/modules/projectiles/projectile/bullets/cannonball.dm
index 1d6108ed33f..358a23eb63c 100644
--- a/code/modules/projectiles/projectile/bullets/cannonball.dm
+++ b/code/modules/projectiles/projectile/bullets/cannonball.dm
@@ -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.
diff --git a/code/modules/projectiles/projectile/bullets/dart_syringe.dm b/code/modules/projectiles/projectile/bullets/dart_syringe.dm
index 405552a8909..1bd88d75fde 100644
--- a/code/modules/projectiles/projectile/bullets/dart_syringe.dm
+++ b/code/modules/projectiles/projectile/bullets/dart_syringe.dm
@@ -2,7 +2,7 @@
name = "dart"
icon_state = "cbbolt"
damage = 6
- embedding = null
+ embed_type = null
shrapnel_type = null
var/inject_flags = null
diff --git a/code/modules/projectiles/projectile/bullets/dnainjector.dm b/code/modules/projectiles/projectile/bullets/dnainjector.dm
index fdb051e7f80..b4029b07f2d 100644
--- a/code/modules/projectiles/projectile/bullets/dnainjector.dm
+++ b/code/modules/projectiles/projectile/bullets/dnainjector.dm
@@ -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)
diff --git a/code/modules/projectiles/projectile/bullets/foam_dart.dm b/code/modules/projectiles/projectile/bullets/foam_dart.dm
index 3f086166e6a..7eaa1ce6c8e 100644
--- a/code/modules/projectiles/projectile/bullets/foam_dart.dm
+++ b/code/modules/projectiles/projectile/bullets/foam_dart.dm
@@ -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
diff --git a/code/modules/projectiles/projectile/bullets/grenade.dm b/code/modules/projectiles/projectile/bullets/grenade.dm
index a99a7b57ff3..0814a844be4 100644
--- a/code/modules/projectiles/projectile/bullets/grenade.dm
+++ b/code/modules/projectiles/projectile/bullets/grenade.dm
@@ -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)
diff --git a/code/modules/projectiles/projectile/bullets/junk.dm b/code/modules/projectiles/projectile/bullets/junk.dm
index 344a7329113..285c3ea2815 100644
--- a/code/modules/projectiles/projectile/bullets/junk.dm
+++ b/code/modules/projectiles/projectile/bullets/junk.dm
@@ -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
diff --git a/code/modules/projectiles/projectile/bullets/pistol.dm b/code/modules/projectiles/projectile/bullets/pistol.dm
index 8fccc510ff8..6bd355219f9 100644
--- a/code/modules/projectiles/projectile/bullets/pistol.dm
+++ b/code/modules/projectiles/projectile/bullets/pistol.dm
@@ -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
diff --git a/code/modules/projectiles/projectile/bullets/revolver.dm b/code/modules/projectiles/projectile/bullets/revolver.dm
index 417f61534bc..e9d6389c89d 100644
--- a/code/modules/projectiles/projectile/bullets/revolver.dm
+++ b/code/modules/projectiles/projectile/bullets/revolver.dm
@@ -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
diff --git a/code/modules/projectiles/projectile/bullets/rifle.dm b/code/modules/projectiles/projectile/bullets/rifle.dm
index 3cbb894b8fb..7e29b7e5c24 100644
--- a/code/modules/projectiles/projectile/bullets/rifle.dm
+++ b/code/modules/projectiles/projectile/bullets/rifle.dm
@@ -44,10 +44,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"
@@ -58,11 +68,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
@@ -74,10 +94,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"
@@ -89,10 +119,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"
@@ -104,10 +144,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"
@@ -118,7 +168,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
@@ -135,7 +185,6 @@
return BULLET_ACT_HIT
-
/obj/projectile/bullet/rebar/supermatter
name = "supermatter bolt"
icon_state = "rebar_supermatter"
@@ -143,6 +192,7 @@
speed = 0.4
dismemberment = 0
damage_type = TOX
+ embed_type = null
armour_penetration = 100
shrapnel_type = /obj/item/ammo_casing/rebar/supermatter
@@ -160,7 +210,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!"))
@@ -170,7 +219,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
diff --git a/code/modules/projectiles/projectile/bullets/shotgun.dm b/code/modules/projectiles/projectile/bullets/shotgun.dm
index b3ddaf9bc90..a013aaba691 100644
--- a/code/modules/projectiles/projectile/bullets/shotgun.dm
+++ b/code/modules/projectiles/projectile/bullets/shotgun.dm
@@ -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
diff --git a/code/modules/projectiles/projectile/bullets/smg.dm b/code/modules/projectiles/projectile/bullets/smg.dm
index 8befcb690ec..ce78abf0662 100644
--- a/code/modules/projectiles/projectile/bullets/smg.dm
+++ b/code/modules/projectiles/projectile/bullets/smg.dm
@@ -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"
diff --git a/code/modules/projectiles/projectile/bullets/special.dm b/code/modules/projectiles/projectile/bullets/special.dm
index f595c3e1165..2af0fe7b9cb 100644
--- a/code/modules/projectiles/projectile/bullets/special.dm
+++ b/code/modules/projectiles/projectile/bullets/special.dm
@@ -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)
diff --git a/code/modules/projectiles/projectile/special/rocket.dm b/code/modules/projectiles/projectile/special/rocket.dm
index db452385c98..fe04fc7d986 100644
--- a/code/modules/projectiles/projectile/special/rocket.dm
+++ b/code/modules/projectiles/projectile/special/rocket.dm
@@ -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
diff --git a/code/modules/religion/burdened/psyker.dm b/code/modules/religion/burdened/psyker.dm
index 1531d07f5ea..20f478c1af1 100644
--- a/code/modules/religion/burdened/psyker.dm
+++ b/code/modules/religion/burdened/psyker.dm
@@ -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 = 0, pierce_hit)
. = ..()
diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm
index 063e49b5a16..dbb50db944b 100644
--- a/code/modules/surgery/bodyparts/_bodyparts.dm
+++ b/code/modules/surgery/bodyparts/_bodyparts.dm
@@ -355,7 +355,7 @@
check_list += "\t [span_boldwarning("Your [name] is suffering [wound.a_or_from] [wound.get_topic_name(owner)]!!")]" // SKYRAT EDIT - Medical overhaul-ish
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 There is \a [embedded_thing] [stuck_word] in your [name]!"
/obj/item/bodypart/blob_act()
@@ -1189,15 +1189,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)
@@ -1250,7 +1250,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)
diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm
index 863cdd9cb61..a0955af4e46 100644
--- a/code/modules/surgery/bodyparts/helpers.dm
+++ b/code/modules/surgery/bodyparts/helpers.dm
@@ -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
diff --git a/code/modules/vehicles/vehicle_key.dm b/code/modules/vehicles/vehicle_key.dm
index f8db861449f..5f57895d8ac 100644
--- a/code/modules/vehicles/vehicle_key.dm
+++ b/code/modules/vehicles/vehicle_key.dm
@@ -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
diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm
index f85fe033e54..30b9ed53715 100644
--- a/code/modules/vending/_vending.dm
+++ b/code/modules/vending/_vending.dm
@@ -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))
diff --git a/modular_skyrat/modules/cellguns/code/medigun_cells.dm b/modular_skyrat/modules/cellguns/code/medigun_cells.dm
index 1be7712509a..459be7edfa0 100644
--- a/modular_skyrat/modules/cellguns/code/medigun_cells.dm
+++ b/modular_skyrat/modules/cellguns/code/medigun_cells.dm
@@ -425,9 +425,16 @@
name = "salve globule"
icon_state = "glob_projectile"
shrapnel_type = /obj/item/mending_globule/hardlight
- embedding = list("embed_chance" = 100, ignore_throwspeed_threshold = TRUE, "pain_mult" = 0, "jostle_pain_mult" = 0, "fall_chance" = 0)
+ embed_type = /datum/embed_data/salve_globule
damage = 0
+/datum/embed_data/salve_globule
+ embed_chance = 100
+ ignore_throwspeed_threshold = TRUE
+ pain_mult = 0
+ jostle_pain_mult = 0
+ fall_chance = 0
+
/obj/projectile/energy/medical/utility/salve/on_hit(mob/living/target, blocked = 0, pierce_hit)
if(!IsLivingHuman(target)) //No using this on the dead or synths.
return FALSE
@@ -507,7 +514,7 @@
/obj/item/mending_globule/hardlight
name = "salve globule"
desc = "A ball of regenerative synthetic plant matter, contained within a soft hardlight field."
- embedding = list("embed_chance" = 100, ignore_throwspeed_threshold = TRUE, "pain_mult" = 0, "jostle_pain_mult" = 0, "fall_chance" = 0)
+ embed_type = /datum/embed_data/salve_globule
icon = 'modular_skyrat/modules/cellguns/icons/obj/guns/mediguns/misc.dmi'
icon_state = "globule"
heals_left = 40 //This means it'll be heaing 15 damage per type max.
diff --git a/modular_skyrat/modules/clock_cult/code/items/weaponry.dm b/modular_skyrat/modules/clock_cult/code/items/weaponry.dm
index 92bd53531dd..1f40edc6101 100644
--- a/modular_skyrat/modules/clock_cult/code/items/weaponry.dm
+++ b/modular_skyrat/modules/clock_cult/code/items/weaponry.dm
@@ -56,11 +56,14 @@
name = "brass spear"
desc = "A razor-sharp spear made of brass. It thrums with barely-contained energy."
icon_state = "ratvarian_spear"
- embedding = list("max_damage_mult" = 15, "armour_block" = 80)
+ embed_type = /datum/embed_data/spear/brass
throwforce = 36
force = 25
armour_penetration = 24
+/datum/embed_data/spear/brass
+ impact_pain_mult = parent_type::impact_pain_mult + 8
+ remove_pain_mult = parent_type::remove_pain_mult + 8
/obj/item/clockwork/weapon/brass_battlehammer
name = "brass battle-hammer"
diff --git a/modular_skyrat/modules/exp_corps/code/tomahawk.dm b/modular_skyrat/modules/exp_corps/code/tomahawk.dm
index b08a1e473a5..b03135607d1 100644
--- a/modular_skyrat/modules/exp_corps/code/tomahawk.dm
+++ b/modular_skyrat/modules/exp_corps/code/tomahawk.dm
@@ -13,12 +13,17 @@
throwforce = 18
throw_speed = 4
throw_range = 8
- embedding = list("pain_mult" = 6, "embed_chance" = 60, "fall_chance" = 10)
+ embed_type = /datum/embed_data/tomahawk
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/tomahawk
+ pain_mult = 6
+ embed_chance = 60
+ fall_chance = 10
+
/obj/item/melee/tomahawk/Initialize(mapload)
. = ..()
AddComponent(/datum/component/butchering, 70, 100)
diff --git a/modular_skyrat/modules/horrorform/code/true_changeling.dm b/modular_skyrat/modules/horrorform/code/true_changeling.dm
index 8f3b87f9714..65293dce9d0 100644
--- a/modular_skyrat/modules/horrorform/code/true_changeling.dm
+++ b/modular_skyrat/modules/horrorform/code/true_changeling.dm
@@ -148,7 +148,17 @@
ricochet_incidence_leeway = 0
embed_falloff_tile = -2
shrapnel_type = /obj/item/shrapnel/bone_fragment
- 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/tomahawk
+
+/datum/embed_data/tomahawk
+ 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/item/shrapnel/bone_fragment
name = "bone fragment"
diff --git a/modular_skyrat/modules/marines/code/gear.dm b/modular_skyrat/modules/marines/code/gear.dm
index c342c2329a7..7f5b6478a84 100644
--- a/modular_skyrat/modules/marines/code/gear.dm
+++ b/modular_skyrat/modules/marines/code/gear.dm
@@ -50,7 +50,7 @@
name = ".300 caseless bullet"
damage = 13
armour_penetration = 30 //gonna actually kill the brit that made this var require a U in armor
- embedding = null
+ embed_data = null
shrapnel_type = null
/obj/item/gun/ballistic/automatic/ar/modular/m44a/scoped
diff --git a/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/carwo_defense_systems/ammo/pistol.dm b/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/carwo_defense_systems/ammo/pistol.dm
index e20070dcef5..cc125a9b997 100644
--- a/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/carwo_defense_systems/ammo/pistol.dm
+++ b/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/carwo_defense_systems/ammo/pistol.dm
@@ -75,7 +75,7 @@
shrapnel_type = null
sharpness = NONE
- embedding = null
+ embed_data = null
/obj/item/ammo_box/c35sol/incapacitator
@@ -111,19 +111,19 @@
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/c35sol_ripper
embed_falloff_tile = -15
+/datum/embed_data/c35sol_ripper
+ 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/item/ammo_box/c35sol/ripper
name = "ammo box (.35 Sol Short ripper)"
diff --git a/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/carwo_defense_systems/ammo/rifle.dm b/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/carwo_defense_systems/ammo/rifle.dm
index 4cb969f7b65..dd335c46454 100644
--- a/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/carwo_defense_systems/ammo/rifle.dm
+++ b/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/carwo_defense_systems/ammo/rifle.dm
@@ -69,19 +69,19 @@
bare_wound_bonus = 10
shrapnel_type = /obj/item/shrapnel/stingball
- embedding = list(
- embed_chance = 50,
- fall_chance = 5,
- jostle_chance = 5,
- ignore_throwspeed_threshold = TRUE,
- pain_stam_pct = 0.4,
- pain_mult = 2,
- jostle_pain_mult = 3,
- rip_time = 0.5 SECONDS,
- )
+ embed_type = /datum/embed_data/c40sol_fragmentation
embed_falloff_tile = -5
+/datum/embed_data/c40sol_fragmentation
+ embed_chance = 50
+ fall_chance = 5
+ jostle_chance = 5
+ ignore_throwspeed_threshold = TRUE
+ pain_stam_pct = 0.4
+ pain_mult = 2
+ jostle_pain_mult = 3
+ rip_time = 0.5 SECONDS
/obj/item/ammo_box/c40sol/fragmentation
name = "ammo box (.40 Sol Long fragmentation)"
diff --git a/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/trappiste_fabriek/ammo.dm b/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/trappiste_fabriek/ammo.dm
index 498f55a5627..163128be97c 100644
--- a/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/trappiste_fabriek/ammo.dm
+++ b/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/trappiste_fabriek/ammo.dm
@@ -52,7 +52,7 @@
shrapnel_type = null
sharpness = NONE
- embedding = null
+ embed_data = null
/obj/item/ammo_box/c585trappiste/incapacitator
name = "ammo box (.585 Trappiste flathead)"
diff --git a/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/xhihao_light_arms/ammo.dm b/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/xhihao_light_arms/ammo.dm
index 7c43be2c19a..8cf2c497562 100644
--- a/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/xhihao_light_arms/ammo.dm
+++ b/modular_skyrat/modules/modular_weapons/code/company_and_or_faction_based/xhihao_light_arms/ammo.dm
@@ -24,7 +24,7 @@
ricochet_decay_damage = 0.7
shrapnel_type = null
sharpness = NONE
- embedding = null
+ embed_data = null
/obj/item/ammo_casing/strilka310/ap
name = ".310 Strilka armor-piercing bullet casing"
diff --git a/modular_skyrat/modules/modular_weapons/code/modular_projectiles.dm b/modular_skyrat/modules/modular_weapons/code/modular_projectiles.dm
index 4a0625b491f..3870c89e500 100644
--- a/modular_skyrat/modules/modular_weapons/code/modular_projectiles.dm
+++ b/modular_skyrat/modules/modular_weapons/code/modular_projectiles.dm
@@ -30,7 +30,7 @@
ricochet_decay_damage = 0.7
shrapnel_type = null
sharpness = NONE
- embedding = null
+ embed_data = null
wound_bonus = -50
/obj/item/ammo_casing/c45/hp
@@ -58,7 +58,7 @@
ricochet_decay_damage = 0.7
shrapnel_type = null
sharpness = NONE
- embedding = null
+ embed_data = null
wound_bonus = -50
/obj/item/ammo_casing/c46x30mm/rubber
@@ -92,7 +92,7 @@
ricochet_decay_damage = 0.7
shrapnel_type = null
sharpness = NONE
- embedding = null
+ embed_data = null
wound_bonus = -50
/obj/item/ammo_casing/a223/ap
@@ -138,7 +138,7 @@
wound_bonus = -75
shrapnel_type = null
sharpness = NONE
- embedding = null
+ embed_data = null
/obj/item/ammo_casing/c34/ap
name = ".34 armor-piercing bullet casing"
diff --git a/modular_skyrat/modules/modular_weapons/code/pepperball_gun.dm b/modular_skyrat/modules/modular_weapons/code/pepperball_gun.dm
index 990581bfb4a..db8efb6da16 100644
--- a/modular_skyrat/modules/modular_weapons/code/pepperball_gun.dm
+++ b/modular_skyrat/modules/modular_weapons/code/pepperball_gun.dm
@@ -43,7 +43,7 @@
stamina = 5
shrapnel_type = null
sharpness = NONE
- embedding = null
+ embed_data = null
impact_effect_type = /obj/effect/temp_visual/impact_effect
var/contained_reagent = /datum/reagent/consumable/condensedcapsaicin
var/reagent_volume = 5
diff --git a/modular_skyrat/modules/moretraitoritems/code/weapons.dm b/modular_skyrat/modules/moretraitoritems/code/weapons.dm
index 1a29d0242d6..48a823694ec 100644
--- a/modular_skyrat/modules/moretraitoritems/code/weapons.dm
+++ b/modular_skyrat/modules/moretraitoritems/code/weapons.dm
@@ -182,11 +182,21 @@
/obj/projectile/bullet/c14mm
name = "14mm bullet"
damage = 60
- embedding = list(embed_chance = 90, fall_chance = 3, jostle_chance = 4, ignore_throwspeed_threshold = TRUE, pain_stam_pct = 0.4, pain_mult = 5, jostle_pain_mult = 9, rip_time = 10)
+ embed_type = /datum/embed_data/c14mm
dismemberment = 50
pierces = 1
projectile_piercing = PASSCLOSEDTURF|PASSGRILLE|PASSGLASS
+/datum/embed_data/c14mm
+ embed_chance = 90
+ fall_chance = 3
+ jostle_chance = 4
+ ignore_throwspeed_threshold = TRUE
+ pain_stam_pct = 0.4
+ pain_mult = 5
+ jostle_pain_mult = 9
+ rip_time = 10
+
//nullrod katana
/obj/item/katana/weak/curator //This has the same stats as the curator's claymore
desc = "An ancient Katana. Forged by... Well, it doesn't really say, but surely it's authentic! And sharp to boot!"
diff --git a/modular_skyrat/modules/reagent_forging/code/forge_weapons.dm b/modular_skyrat/modules/reagent_forging/code/forge_weapons.dm
index e93141134d8..fa60c021e8c 100644
--- a/modular_skyrat/modules/reagent_forging/code/forge_weapons.dm
+++ b/modular_skyrat/modules/reagent_forging/code/forge_weapons.dm
@@ -72,6 +72,7 @@
worn_icon_state = "dagger_back"
belt_icon_state = "dagger_belt"
hitsound = 'sound/weapons/bladeslice.ogg'
+ embed_type = /datum/embed_data/forged_dagger
throwforce = 10
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
w_class = WEIGHT_CLASS_SMALL
@@ -80,6 +81,11 @@
attack_verb_simple = list("attack", "slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut")
sharpness = SHARP_EDGED
+/datum/embed_data/forged_dagger
+ embed_chance = 50
+ fall_chance = 1
+ pain_mult = 2
+
/obj/item/forging/reagent_weapon/dagger/Initialize(mapload)
. = ..()
AddComponent(/datum/component/butchering, speed = 10 SECONDS, effectiveness = 70)
@@ -116,6 +122,7 @@
inhand_icon_state = "spear"
worn_icon_state = "spear_back"
throwforce = 15 //not a javelin, throwing specialty is for the axe.
+ embed_data = /datum/embed_data/forged_spear
slot_flags = ITEM_SLOT_BACK
w_class = WEIGHT_CLASS_BULKY
resistance_flags = FIRE_PROOF
@@ -126,6 +133,11 @@
bare_wound_bonus = 15
sharpness = SHARP_POINTY
+/datum/embed_data/forged_spear
+ embed_chance = 75
+ fall_chance = 0
+ pain_mult = 6
+
/obj/item/forging/reagent_weapon/spear/Initialize(mapload)
. = ..()
AddComponent(/datum/component/jousting, max_tile_charge = 9, min_tile_charge = 6)
@@ -144,7 +156,7 @@
worn_icon_state = "axe_back"
throwforce = 22 //ouch
throw_speed = 4
- embedding = list("impact_pain_mult" = 2, "remove_pain_mult" = 4, "jostle_chance" = 2.5)
+ embed_type = /datum/embed_data/forged_axe
slot_flags = ITEM_SLOT_BACK
w_class = WEIGHT_CLASS_BULKY
resistance_flags = FIRE_PROOF
@@ -152,6 +164,11 @@
attack_verb_simple = list("slash", "bash")
sharpness = SHARP_EDGED
+/datum/embed_data/forged_axe
+ embed_chance = 65
+ fall_chance = 10
+ pain_mult = 4
+
/obj/item/forging/reagent_weapon/axe/Initialize(mapload)
. = ..()
AddComponent(/datum/component/butchering, speed = 10 SECONDS, effectiveness = 70)
diff --git a/modular_skyrat/modules/sec_haul/code/guns/bullets.dm b/modular_skyrat/modules/sec_haul/code/guns/bullets.dm
index c7bc249b351..d342340466f 100644
--- a/modular_skyrat/modules/sec_haul/code/guns/bullets.dm
+++ b/modular_skyrat/modules/sec_haul/code/guns/bullets.dm
@@ -33,7 +33,17 @@
name = "9x25mm IHDF bullet"
damage = 30
damage_type = STAMINA
- embedding = list(embed_chance=0, 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/c9mm_ihdf
+
+/datum/embed_data/c9mm_ihdf
+ embed_chance = 0
+ fall_chance = 3
+ jostle_chance = 4
+ pain_mult = 5
+ pain_stam_pct = 0.4
+ ignore_throwspeed_threshold = TRUE
+ jostle_pain_mult = 6
+ rip_time = 1 SECONDS
/obj/item/ammo_casing/c9mm/rubber
name = "9x25mm Mk.12 rubber casing"
@@ -52,7 +62,7 @@
ricochet_decay_damage = 0.8
shrapnel_type = null
sharpness = NONE
- embedding = null
+ embed_type = null
/*
* 10mm Auto
@@ -90,7 +100,7 @@
ricochet_decay_damage = 0.8
shrapnel_type = null
sharpness = NONE
- embedding = null
+ embed_type = null
/obj/item/ammo_casing/c10mm/ihdf
name = "10mm IHDF bullet casing"
@@ -102,4 +112,14 @@
name = "10mm IHDF bullet"
damage = 40
damage_type = STAMINA
- embedding = list(embed_chance=0, 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/c10mm_ihdf
+
+/datum/embed_data/c10mm_ihdf
+ embed_chance = 0
+ 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
diff --git a/modular_skyrat/modules/shotgunrebalance/code/shotgun.dm b/modular_skyrat/modules/shotgunrebalance/code/shotgun.dm
index a4e237b0f11..0ef23660a3a 100644
--- a/modular_skyrat/modules/shotgunrebalance/code/shotgun.dm
+++ b/modular_skyrat/modules/shotgunrebalance/code/shotgun.dm
@@ -232,7 +232,17 @@
eyeblur = 1 SECONDS
sharpness = NONE
range = 8
- embedding = list(embed_chance=70, pain_chance=25, fall_chance=15, jostle_chance=80, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.9, pain_mult=2, rip_time=10)
+ embed_type = /datum/embed_data/shotgun_buckshot/antitide
+
+/datum/embed_data/shotgun_buckshot/antitide
+ embed_chance = 70
+ pain_chance = 25
+ fall_chance = 15
+ jostle_chance = 80
+ ignore_throwspeed_threshold = TRUE
+ pain_stam_pct = 0.9
+ pain_mult = 2
+ rip_time = 1 SECONDS
/obj/projectile/bullet/pellet/shotgun_buckshot/antitide/on_range()
do_sparks(1, TRUE, src)
diff --git a/modular_skyrat/modules/tribal_extended/code/ammo/reusable/arrow.dm b/modular_skyrat/modules/tribal_extended/code/ammo/reusable/arrow.dm
index 0fdfb0967d1..5fd451bb0f4 100644
--- a/modular_skyrat/modules/tribal_extended/code/ammo/reusable/arrow.dm
+++ b/modular_skyrat/modules/tribal_extended/code/ammo/reusable/arrow.dm
@@ -39,16 +39,17 @@
/mob/living/basic/wumborian_fugu,
)
shrapnel_type = /obj/item/ammo_casing/arrow/bone
- embedding = list(
- embed_chance = 33,
- fall_chance = 3,
- jostle_chance = 4,
- ignore_throwspeed_threshold = TRUE,
- pain_stam_pct = 0.4,
- pain_mult = 5,
- jostle_pain_mult = 6,
- rip_time = 0.5 SECONDS
- )
+ embed_type = /datum/embed_data/bone_arrow
+
+/datum/embed_data/bone_arrow
+ embed_chance = 33
+ fall_chance = 3
+ jostle_chance = 4
+ ignore_throwspeed_threshold = TRUE
+ pain_stam_pct = 0.4
+ pain_mult = 5
+ jostle_pain_mult = 6
+ rip_time = 0.5 SECONDS
/obj/projectile/bullet/arrow/bronze
name = "bronze arrow"
diff --git a/tgstation.dme b/tgstation.dme
index 794bd603835..71fddd79922 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -872,6 +872,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"