mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-31 20:11:56 +00:00
Necessary for #72292 to work effectively, and probably not very useful out of that context. Split out of its own PR because this is long and boring. I want to make sure that we're catching actual mistakes there, and not just experiencing side effects of how shitty the attack chain is.
80 lines
3.0 KiB
Plaintext
80 lines
3.0 KiB
Plaintext
/datum/component/summoning
|
|
var/list/mob_types = list()
|
|
var/spawn_chance // chance for the mob to spawn on hit in percent
|
|
var/max_mobs
|
|
var/spawn_delay // delay in spawning between mobs (deciseconds)
|
|
var/spawn_text
|
|
var/spawn_sound
|
|
var/list/faction
|
|
|
|
var/last_spawned_time = 0
|
|
var/list/spawned_mobs = list()
|
|
|
|
/datum/component/summoning/Initialize(mob_types, spawn_chance=100, max_mobs=3, spawn_delay=100, spawn_text="appears out of nowhere", spawn_sound='sound/magic/summon_magic.ogg', faction)
|
|
if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent) && !isprojectilespell(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
src.mob_types = mob_types
|
|
src.spawn_chance = spawn_chance
|
|
src.max_mobs = max_mobs
|
|
src.spawn_delay = spawn_delay
|
|
src.spawn_text = spawn_text
|
|
src.spawn_sound = spawn_sound
|
|
src.faction = faction
|
|
|
|
/datum/component/summoning/RegisterWithParent()
|
|
if(ismachinery(parent) || isstructure(parent) || isgun(parent) || isprojectilespell(parent)) // turrets, etc
|
|
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, PROC_REF(projectile_hit))
|
|
else if(isitem(parent))
|
|
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, PROC_REF(item_afterattack))
|
|
else if(ishostile(parent))
|
|
RegisterSignal(parent, COMSIG_HOSTILE_POST_ATTACKINGTARGET, PROC_REF(hostile_attackingtarget))
|
|
|
|
/datum/component/summoning/UnregisterFromParent()
|
|
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_POST_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
|
|
|
|
/datum/component/summoning/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!proximity_flag)
|
|
return
|
|
do_spawn_mob(get_turf(target), user)
|
|
return COMPONENT_AFTERATTACK_PROCESSED_ITEM
|
|
|
|
/datum/component/summoning/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target, success)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!success)
|
|
return
|
|
do_spawn_mob(get_turf(target), attacker)
|
|
|
|
/datum/component/summoning/proc/projectile_hit(datum/fired_from, atom/movable/firer, atom/target, Angle)
|
|
SIGNAL_HANDLER
|
|
|
|
do_spawn_mob(get_turf(target), firer)
|
|
|
|
/datum/component/summoning/proc/do_spawn_mob(atom/spawn_location, summoner)
|
|
if(spawned_mobs.len >= max_mobs)
|
|
return
|
|
if(last_spawned_time > world.time)
|
|
return
|
|
if(!prob(spawn_chance))
|
|
return
|
|
last_spawned_time = world.time + spawn_delay
|
|
var/chosen_mob_type = pick(mob_types)
|
|
var/mob/living/simple_animal/L = new chosen_mob_type(spawn_location)
|
|
if(ishostile(L))
|
|
var/mob/living/simple_animal/hostile/H = L
|
|
H.friends += summoner // do not attack our summon boy
|
|
spawned_mobs += L
|
|
if(faction != null)
|
|
L.faction = faction
|
|
RegisterSignal(L, COMSIG_LIVING_DEATH, PROC_REF(on_spawned_death)) // so we can remove them from the list, etc (for mobs with corpses)
|
|
playsound(spawn_location,spawn_sound, 50, TRUE)
|
|
spawn_location.visible_message(span_danger("[L] [spawn_text]."))
|
|
|
|
/datum/component/summoning/proc/on_spawned_death(mob/killed, gibbed)
|
|
SIGNAL_HANDLER
|
|
|
|
spawned_mobs -= killed
|