mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 16:47:13 +01:00
Throwing a bee at someone injects reagents (#80354)
## About The Pull Request Throwing a bee at someone injects that bee's reagents. This has a larger code footprint than you might expect because venom injection is done via an element which in turn gives a callback to a component. While I was touching that I also separated `COMSIG_MOVABLE_IMPACT` into `COMSIG_MOVABLE_PRE_IMPACT` because a lot of effects trigger from `COMSIG_MOVABLE_IMPACT` despite the fact that the throw impact can be cancelled after the signal is sent. I also added an inject check onto the venomous element for mob attacks, so thick clothing can now protect you from venom injection. I elected that Giant Spiders have big enough fangs to ignore this such that this isn't a major balance change, as do moonicorns (that horn is massive), Fire Sharks, and Clowns (no idea how they are applying chems at all to be honest). ## Why It's Good For The Game I thought about someone throwing a bee at someone like a little dart and thought "hee hee" ## Changelog 🆑 add: If you throw a bee at someone it will hit them sting-first and inject that bee's reagent balance: Thick clothing can now protect you from the venom of bees, snakes, frogs, and (small) spiders /🆑 --------- Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
This commit is contained in:
co-authored by
John Willard
parent
0f54943cc8
commit
29590d467c
@@ -23,9 +23,11 @@
|
||||
#define COMSIG_MOVABLE_DRIFT_BLOCK_INPUT "movable_drift_block_input"
|
||||
#define DRIFT_ALLOW_INPUT (1<<0)
|
||||
///from base of atom/movable/throw_impact(): (/atom/hit_atom, /datum/thrownthing/throwingdatum)
|
||||
#define COMSIG_MOVABLE_IMPACT "movable_impact"
|
||||
#define COMSIG_MOVABLE_PRE_IMPACT "movable_pre_impact"
|
||||
#define COMPONENT_MOVABLE_IMPACT_FLIP_HITPUSH (1<<0) //if true, flip if the impact will push what it hits
|
||||
#define COMPONENT_MOVABLE_IMPACT_NEVERMIND (1<<1) //return true if you destroyed whatever it was you're impacting and there won't be anything for hitby() to run on
|
||||
///from base of atom/movable/throw_impact() after confirming a hit: (/atom/hit_atom, /datum/thrownthing/throwingdatum)
|
||||
#define COMSIG_MOVABLE_IMPACT "movable_impact"
|
||||
///from base of mob/living/hitby(): (mob/living/target, hit_zone, blocked, datum/thrownthing/throwingdatum)
|
||||
#define COMSIG_MOVABLE_IMPACT_ZONE "item_impact_zone"
|
||||
///from /atom/movable/proc/buckle_mob(): (mob/living/M, force, check_loc, buckle_mob_flags)
|
||||
|
||||
@@ -11,12 +11,15 @@
|
||||
var/datum/callback/on_hit_callback
|
||||
///callback optionally used for more checks
|
||||
var/datum/callback/extra_check_callback
|
||||
///optionally should we also apply the effect if thrown at something?
|
||||
var/thrown_effect
|
||||
|
||||
/datum/component/on_hit_effect/Initialize(on_hit_callback, extra_check_callback)
|
||||
/datum/component/on_hit_effect/Initialize(on_hit_callback, extra_check_callback, thrown_effect = FALSE)
|
||||
src.on_hit_callback = on_hit_callback
|
||||
src.extra_check_callback = extra_check_callback
|
||||
if(!(ismachinery(parent) || isstructure(parent) || isgun(parent) || isprojectilespell(parent) || isitem(parent) || isanimal_or_basicmob(parent) || isprojectile(parent)))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
src.thrown_effect = thrown_effect
|
||||
|
||||
/datum/component/on_hit_effect/Destroy(force, silent)
|
||||
on_hit_callback = null
|
||||
@@ -33,12 +36,16 @@
|
||||
else if(isprojectile(parent))
|
||||
RegisterSignal(parent, COMSIG_PROJECTILE_SELF_ON_HIT, PROC_REF(on_projectile_self_hit))
|
||||
|
||||
if(thrown_effect)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_IMPACT, PROC_REF(on_thrown_hit))
|
||||
|
||||
/datum/component/on_hit_effect/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(
|
||||
COMSIG_PROJECTILE_ON_HIT,
|
||||
COMSIG_ITEM_AFTERATTACK,
|
||||
COMSIG_HOSTILE_POST_ATTACKINGTARGET,
|
||||
COMSIG_PROJECTILE_SELF_ON_HIT,
|
||||
COMSIG_MOVABLE_IMPACT,
|
||||
))
|
||||
|
||||
/datum/component/on_hit_effect/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
@@ -79,3 +86,9 @@
|
||||
if(!extra_check_callback.Invoke(firer, target))
|
||||
return
|
||||
on_hit_callback.Invoke(source, firer, target, body_zone)
|
||||
|
||||
/datum/component/on_hit_effect/proc/on_thrown_hit(datum/source, atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
SIGNAL_HANDLER
|
||||
if(extra_check_callback && !extra_check_callback.Invoke(source, hit_atom))
|
||||
return
|
||||
on_hit_callback.Invoke(source, source, hit_atom, null)
|
||||
|
||||
@@ -54,11 +54,11 @@
|
||||
|
||||
/datum/component/tackler/RegisterWithParent()
|
||||
RegisterSignal(parent, COMSIG_MOB_CLICKON, PROC_REF(checkTackle))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_IMPACT, PROC_REF(sack))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_PRE_IMPACT, PROC_REF(sack))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_POST_THROW, PROC_REF(registerTackle))
|
||||
|
||||
/datum/component/tackler/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(COMSIG_MOB_CLICKON, COMSIG_MOVABLE_IMPACT, COMSIG_MOVABLE_MOVED, COMSIG_MOVABLE_POST_THROW))
|
||||
UnregisterSignal(parent, list(COMSIG_MOB_CLICKON, COMSIG_MOVABLE_PRE_IMPACT, COMSIG_MOVABLE_MOVED, COMSIG_MOVABLE_POST_THROW))
|
||||
|
||||
///Store the thrownthing datum for later use
|
||||
/datum/component/tackler/proc/registerTackle(mob/living/carbon/user, datum/thrownthing/tackle)
|
||||
|
||||
@@ -8,14 +8,21 @@
|
||||
argument_hash_start_idx = 2
|
||||
///Path of the reagent added
|
||||
var/poison_type
|
||||
///Details of how we inject our venom
|
||||
var/injection_flags
|
||||
///How much of the reagent added. if it's a list, it'll pick a range with the range being list(lower_value, upper_value)
|
||||
var/list/amount_added
|
||||
|
||||
/datum/element/venomous/Attach(datum/target, poison_type, amount_added)
|
||||
/datum/element/venomous/Attach(datum/target, poison_type, amount_added, injection_flags = NONE, thrown_effect = FALSE)
|
||||
. = ..()
|
||||
src.poison_type = poison_type
|
||||
src.amount_added = amount_added
|
||||
target.AddComponent(/datum/component/on_hit_effect, CALLBACK(src, PROC_REF(do_venom)))
|
||||
src.injection_flags = injection_flags
|
||||
target.AddComponent(\
|
||||
/datum/component/on_hit_effect,\
|
||||
on_hit_callback = CALLBACK(src, PROC_REF(do_venom)),\
|
||||
thrown_effect = thrown_effect,\
|
||||
)
|
||||
|
||||
/datum/element/venomous/Detach(datum/target)
|
||||
qdel(target.GetComponent(/datum/component/on_hit_effect))
|
||||
@@ -26,6 +33,8 @@
|
||||
return
|
||||
if(target.stat == DEAD)
|
||||
return
|
||||
if(isliving(element_owner) && !target.try_inject(element_owner, hit_zone, injection_flags))
|
||||
return
|
||||
var/final_amount_added
|
||||
if(islist(amount_added))
|
||||
final_amount_added = rand(amount_added[1], amount_added[2])
|
||||
|
||||
@@ -1242,7 +1242,7 @@
|
||||
/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
set waitfor = FALSE
|
||||
var/hitpush = TRUE
|
||||
var/impact_signal = SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
|
||||
var/impact_signal = SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_IMPACT, hit_atom, throwingdatum)
|
||||
if(impact_signal & COMPONENT_MOVABLE_IMPACT_FLIP_HITPUSH)
|
||||
hitpush = FALSE // hacky, tie this to something else or a proper workaround later
|
||||
|
||||
@@ -1250,6 +1250,7 @@
|
||||
return // in case a signal interceptor broke or deleted the thing before we could process our hit
|
||||
if(SEND_SIGNAL(hit_atom, COMSIG_ATOM_PREHITBY, src, throwingdatum) & COMSIG_HIT_PREVENTED)
|
||||
return
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
|
||||
return hit_atom.hitby(src, throwingdatum=throwingdatum, hitpush=hitpush)
|
||||
|
||||
/atom/movable/hitby(atom/movable/hitting_atom, skipcatch, hitpush = TRUE, blocked, datum/thrownthing/throwingdatum)
|
||||
|
||||
@@ -772,10 +772,12 @@
|
||||
/obj/item/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
if(QDELETED(hit_atom))
|
||||
return
|
||||
if(SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum) & COMPONENT_MOVABLE_IMPACT_NEVERMIND)
|
||||
if(SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_IMPACT, hit_atom, throwingdatum) & COMPONENT_MOVABLE_IMPACT_NEVERMIND)
|
||||
return
|
||||
if(SEND_SIGNAL(hit_atom, COMSIG_ATOM_PREHITBY, src, throwingdatum) & COMSIG_HIT_PREVENTED)
|
||||
return
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
|
||||
if(get_temperature() && isliving(hit_atom))
|
||||
var/mob/living/L = hit_atom
|
||||
L.ignite_mob()
|
||||
|
||||
@@ -112,7 +112,12 @@
|
||||
var/static/list/injection_range
|
||||
if(!injection_range)
|
||||
injection_range = string_numbers_list(list(1, 5))
|
||||
AddElement(/datum/element/venomous, /datum/reagent/consumable/laughter, injection_range)
|
||||
AddElement(\
|
||||
/datum/element/venomous,\
|
||||
/datum/reagent/consumable/laughter,\
|
||||
injection_range,\
|
||||
injection_flags = INJECT_CHECK_PENETRATE_THICK | INJECT_CHECK_IGNORE_SPECIES,\
|
||||
)
|
||||
|
||||
/mob/living/basic/clown/fleshclown
|
||||
name = "Fleshclown"
|
||||
@@ -288,7 +293,12 @@
|
||||
var/static/list/injection_range
|
||||
if(!injection_range)
|
||||
injection_range = string_numbers_list(list(1, 5))
|
||||
AddElement(/datum/element/venomous, /datum/reagent/peaceborg/confuse, injection_range)
|
||||
AddElement(\
|
||||
/datum/element/venomous,\
|
||||
/datum/reagent/peaceborg/confuse,\
|
||||
injection_range,\
|
||||
injection_flags = INJECT_CHECK_PENETRATE_THICK | INJECT_CHECK_IGNORE_SPECIES,\
|
||||
) // I don't really know what a clown is using to inject people but let's assume it doesn't need to penetrate at all
|
||||
|
||||
/mob/living/basic/clown/clownhulk/destroyer
|
||||
name = "The Destroyer"
|
||||
|
||||
@@ -192,11 +192,11 @@
|
||||
if(!injection_range)
|
||||
injection_range = string_numbers_list(list(1, 5))
|
||||
if(beegent) //clear the old since this one is going to have some new value
|
||||
RemoveElement(/datum/element/venomous, beegent.type, injection_range)
|
||||
RemoveElement(/datum/element/venomous, beegent.type, injection_range, thrown_effect = TRUE)
|
||||
beegent = toxin
|
||||
name = "[initial(name)] ([toxin.name])"
|
||||
real_name = name
|
||||
AddElement(/datum/element/venomous, beegent.type, injection_range)
|
||||
AddElement(/datum/element/venomous, beegent.type, injection_range, thrown_effect = TRUE)
|
||||
generate_bee_visuals()
|
||||
|
||||
/mob/living/basic/bee/queen
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
/mob/living/basic/cow/moonicorn/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/venomous, /datum/reagent/pax, 5)
|
||||
AddElement(/datum/element/venomous, /datum/reagent/pax, 5, injection_flags = INJECT_CHECK_PENETRATE_THICK | INJECT_CHECK_IGNORE_SPECIES)
|
||||
AddElement(/datum/element/movement_turf_changer, /turf/open/floor/grass/fairy)
|
||||
|
||||
/mob/living/basic/cow/moonicorn/udder_component()
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
. = ..()
|
||||
AddElement(/datum/element/death_gases, /datum/gas/plasma, 40)
|
||||
AddElement(/datum/element/simple_flying)
|
||||
AddElement(/datum/element/venomous, /datum/reagent/phlogiston, 2)
|
||||
AddElement(/datum/element/venomous, /datum/reagent/phlogiston, 2, injection_flags = INJECT_CHECK_PENETRATE_THICK)
|
||||
AddComponent(/datum/component/swarming)
|
||||
AddComponent(/datum/component/regenerator, outline_colour = COLOR_DARK_RED)
|
||||
ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
ADD_TRAIT(src, TRAIT_WEB_SURFER, INNATE_TRAIT)
|
||||
AddElement(/datum/element/cliff_walking)
|
||||
AddElement(/datum/element/footstep, FOOTSTEP_MOB_CLAW)
|
||||
AddElement(/datum/element/venomous, /datum/reagent/toxin/hunterspider, 5)
|
||||
AddElement(/datum/element/venomous, /datum/reagent/toxin/hunterspider, 5, injection_flags = INJECT_CHECK_PENETRATE_THICK)
|
||||
AddElement(/datum/element/web_walker, /datum/movespeed_modifier/fast_web)
|
||||
AddElement(/datum/element/nerfed_pulling, GLOB.typecache_general_bad_things_to_easily_move)
|
||||
AddElement(/datum/element/prevent_attacking_of_types, GLOB.typecache_general_bad_hostile_attack_targets, "this tastes awful!")
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
melee_damage_upper = 25
|
||||
gold_core_spawnable = HOSTILE_SPAWN
|
||||
ai_controller = /datum/ai_controller/basic_controller/giant_spider
|
||||
bite_injection_flags = INJECT_CHECK_PENETRATE_THICK
|
||||
/// Actions to grant on Initialize
|
||||
var/list/innate_actions = null
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
var/poison_type = /datum/reagent/toxin/hunterspider
|
||||
/// How much of a reagent the mob injects on attack
|
||||
var/poison_per_bite = 0
|
||||
/// How tough is our bite?
|
||||
var/bite_injection_flags = NONE
|
||||
/// Multiplier to apply to web laying speed. Fractional numbers make it faster, because it's a multiplier.
|
||||
var/web_speed = 1
|
||||
/// Type of webbing ability to learn.
|
||||
@@ -57,7 +59,7 @@
|
||||
AddComponent(/datum/component/health_scaling_effects, min_health_slowdown = 1.5)
|
||||
|
||||
if(poison_per_bite)
|
||||
AddElement(/datum/element/venomous, poison_type, poison_per_bite)
|
||||
AddElement(/datum/element/venomous, poison_type, poison_per_bite, injection_flags = bite_injection_flags)
|
||||
|
||||
var/datum/action/cooldown/mob_cooldown/lay_web/webbing = new web_type(src)
|
||||
webbing.webbing_time *= web_speed
|
||||
|
||||
@@ -218,7 +218,7 @@
|
||||
|
||||
/obj/item/mod/module/weapon_recall/proc/set_weapon(obj/item/weapon)
|
||||
linked_weapon = weapon
|
||||
RegisterSignal(linked_weapon, COMSIG_MOVABLE_IMPACT, PROC_REF(catch_weapon))
|
||||
RegisterSignal(linked_weapon, COMSIG_MOVABLE_PRE_IMPACT, PROC_REF(catch_weapon))
|
||||
RegisterSignal(linked_weapon, COMSIG_QDELETING, PROC_REF(deleted_weapon))
|
||||
|
||||
/obj/item/mod/module/weapon_recall/proc/recall_weapon(caught = FALSE)
|
||||
|
||||
Reference in New Issue
Block a user