Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into Ghommie-cit265
This commit is contained in:
@@ -1,26 +1,48 @@
|
||||
/datum/component/anti_magic
|
||||
var/magic = FALSE
|
||||
var/holy = FALSE
|
||||
var/psychic = FALSE
|
||||
var/allowed_slots = ~ITEM_SLOT_BACKPACK
|
||||
var/charges = INFINITY
|
||||
var/blocks_self = TRUE
|
||||
var/datum/callback/reaction
|
||||
var/datum/callback/expire
|
||||
|
||||
/datum/component/anti_magic/Initialize(_magic = FALSE, _holy = FALSE)
|
||||
/datum/component/anti_magic/Initialize(_magic = FALSE, _holy = FALSE, _psychic = FALSE, _allowed_slots, _charges, _blocks_self = TRUE, datum/callback/_reaction, datum/callback/_expire)
|
||||
if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
|
||||
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
|
||||
else if(ismob(parent))
|
||||
RegisterSignal(parent, COMSIG_MOB_RECEIVE_MAGIC, .proc/can_protect)
|
||||
RegisterSignal(parent, COMSIG_MOB_RECEIVE_MAGIC, .proc/protect)
|
||||
else
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
magic = _magic
|
||||
holy = _holy
|
||||
psychic = _psychic
|
||||
if(_allowed_slots)
|
||||
allowed_slots = _allowed_slots
|
||||
if(!isnull(_charges))
|
||||
charges = _charges
|
||||
blocks_self = _blocks_self
|
||||
reaction = _reaction
|
||||
expire = _expire
|
||||
|
||||
/datum/component/anti_magic/proc/on_equip(datum/source, mob/equipper, slot)
|
||||
RegisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC, .proc/can_protect, TRUE)
|
||||
if(!CHECK_BITFIELD(allowed_slots, slotdefine2slotbit(slot))) //Check that the slot is valid for antimagic
|
||||
UnregisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC)
|
||||
return
|
||||
RegisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC, .proc/protect, TRUE)
|
||||
|
||||
/datum/component/anti_magic/proc/on_drop(datum/source, mob/user)
|
||||
UnregisterSignal(user, COMSIG_MOB_RECEIVE_MAGIC)
|
||||
|
||||
/datum/component/anti_magic/proc/can_protect(datum/source, _magic, _holy, list/protection_sources)
|
||||
if((_magic && magic) || (_holy && holy))
|
||||
/datum/component/anti_magic/proc/protect(datum/source, mob/user, _magic, _holy, _psychic, chargecost = 1, self, list/protection_sources)
|
||||
if(((_magic && magic) || (_holy && holy) || (_psychic && psychic)) && (!self || blocks_self))
|
||||
protection_sources += parent
|
||||
reaction?.Invoke(user, chargecost)
|
||||
charges -= chargecost
|
||||
if(charges <= 0)
|
||||
expire?.Invoke(user)
|
||||
qdel(src)
|
||||
return COMPONENT_BLOCK_MAGIC
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/datum/component/bane
|
||||
dupe_mode = COMPONENT_DUPE_ALLOWED
|
||||
|
||||
var/mobtype
|
||||
var/speciestype
|
||||
var/damage_multiplier
|
||||
|
||||
/datum/component/bane/Initialize(mobtype, damage_multiplier=1)
|
||||
if(!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
if(ispath(mobtype, /mob/living))
|
||||
src.mobtype = mobtype
|
||||
else if(ispath(mobtype, /datum/species))
|
||||
speciestype = mobtype
|
||||
else
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.damage_multiplier = damage_multiplier
|
||||
|
||||
/datum/component/bane/RegisterWithParent()
|
||||
if(speciestype)
|
||||
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/speciesCheck)
|
||||
else
|
||||
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/mobCheck)
|
||||
|
||||
/datum/component/bane/UnregisterFromParent()
|
||||
UnregisterSignal(parent, COMSIG_ITEM_AFTERATTACK)
|
||||
|
||||
/datum/component/bane/proc/speciesCheck(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
if(!is_species(target, speciestype))
|
||||
return
|
||||
activate(source, target, user)
|
||||
|
||||
/datum/component/bane/proc/mobCheck(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
if(!istype(target, mobtype))
|
||||
return
|
||||
activate(source, target, user)
|
||||
|
||||
/datum/component/bane/proc/activate(obj/item/source, mob/living/target, mob/attacker)
|
||||
if(attacker.a_intent != INTENT_HARM)
|
||||
return
|
||||
|
||||
var/extra_damage = max(0, source.force * damage_multiplier)
|
||||
target.apply_damage(extra_damage, source.damtype, attacker.zone_selected)
|
||||
@@ -65,7 +65,7 @@
|
||||
return FALSE
|
||||
if(!isliving(AM) && !isobj(AM))
|
||||
return FALSE
|
||||
if(is_type_in_typecache(AM, forbidden_types) || AM.throwing || AM.floating)
|
||||
if(is_type_in_typecache(AM, forbidden_types) || AM.throwing || (AM.movement_type & FLOATING))
|
||||
return FALSE
|
||||
//Flies right over the chasm
|
||||
if(ismob(AM))
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/datum/component/fantasy
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
||||
|
||||
var/quality
|
||||
|
||||
var/canFail
|
||||
var/announce
|
||||
|
||||
var/originalName
|
||||
var/list/affixes
|
||||
var/list/appliedComponents
|
||||
|
||||
var/static/list/affixListing
|
||||
|
||||
/datum/component/fantasy/Initialize(quality, list/affixes = list(), canFail=FALSE, announce=FALSE)
|
||||
if(!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.quality = quality || randomQuality()
|
||||
src.canFail = canFail
|
||||
src.announce = announce
|
||||
|
||||
src.affixes = affixes
|
||||
appliedComponents = list()
|
||||
randomAffixes()
|
||||
|
||||
/datum/component/fantasy/Destroy()
|
||||
unmodify()
|
||||
affixes = null
|
||||
return ..()
|
||||
|
||||
/datum/component/fantasy/RegisterWithParent()
|
||||
var/obj/item/master = parent
|
||||
originalName = master.name
|
||||
modify()
|
||||
|
||||
/datum/component/fantasy/UnregisterFromParent()
|
||||
unmodify()
|
||||
|
||||
/datum/component/fantasy/InheritComponent(datum/component/fantasy/newComp, original, list/arguments)
|
||||
unmodify()
|
||||
if(newComp)
|
||||
quality += newComp.quality
|
||||
canFail = newComp.canFail
|
||||
announce = newComp.announce
|
||||
else
|
||||
arguments.len = 5 // This is done to replicate what happens when an arglist smaller than the necessary arguments is given
|
||||
quality += arguments[1]
|
||||
canFail = arguments[4] || canFail
|
||||
announce = arguments[5] || announce
|
||||
modify()
|
||||
|
||||
/datum/component/fantasy/proc/randomQuality()
|
||||
var/quality = pick(1;15, 2;14, 2;13, 2;12, 3;11, 3;10, 3;9, 4;8, 4;7, 4;6, 5;5, 5;4, 5;3, 6;2, 6;1, 6;0)
|
||||
if(prob(50))
|
||||
quality = -quality
|
||||
return quality
|
||||
|
||||
/datum/component/fantasy/proc/randomAffixes(force)
|
||||
if(!affixListing)
|
||||
affixListing = list()
|
||||
for(var/T in subtypesof(/datum/fantasy_affix))
|
||||
var/datum/fantasy_affix/affix = new T
|
||||
affixListing[affix] = affix.weight
|
||||
|
||||
if(length(affixes))
|
||||
if(!force)
|
||||
return
|
||||
affixes = list()
|
||||
|
||||
var/alignment
|
||||
if(quality >= 0)
|
||||
alignment |= AFFIX_GOOD
|
||||
if(quality <= 0)
|
||||
alignment |= AFFIX_EVIL
|
||||
|
||||
var/usedSlots = NONE
|
||||
for(var/i in 1 to max(1, abs(quality))) // We want at least 1 affix applied
|
||||
var/datum/fantasy_affix/affix = pickweight(affixListing)
|
||||
if(affix.placement & usedSlots)
|
||||
continue
|
||||
if(!(affix.alignment & alignment))
|
||||
continue
|
||||
if(!affix.validate(src))
|
||||
continue
|
||||
affixes += affix
|
||||
usedSlots |= affix.placement
|
||||
|
||||
/datum/component/fantasy/proc/modify()
|
||||
var/obj/item/master = parent
|
||||
|
||||
master.force = max(0, master.force + quality)
|
||||
master.throwforce = max(0, master.throwforce + quality)
|
||||
master.armor = master.armor?.modifyAllRatings(quality)
|
||||
|
||||
var/newName = originalName
|
||||
for(var/i in affixes)
|
||||
var/datum/fantasy_affix/affix = i
|
||||
newName = affix.apply(src, newName)
|
||||
|
||||
if(quality != 0)
|
||||
newName = "[newName] [quality > 0 ? "+" : ""][quality]"
|
||||
|
||||
if(canFail && prob((quality - 9)*10))
|
||||
var/turf/place = get_turf(parent)
|
||||
place.visible_message("<span class='danger'>[parent] <span class='blue'>violently glows blue</span> for a while, then evaporates.</span>")
|
||||
master.burn()
|
||||
return
|
||||
else if(announce)
|
||||
announce()
|
||||
|
||||
master.name = newName
|
||||
|
||||
/datum/component/fantasy/proc/unmodify()
|
||||
var/obj/item/master = parent
|
||||
|
||||
for(var/i in affixes)
|
||||
var/datum/fantasy_affix/affix = i
|
||||
affix.remove(src)
|
||||
for(var/i in appliedComponents)
|
||||
qdel(i)
|
||||
|
||||
master.force = max(0, master.force - quality)
|
||||
master.throwforce = max(0, master.throwforce - quality)
|
||||
master.armor = master.armor?.modifyAllRatings(-quality)
|
||||
|
||||
master.name = originalName
|
||||
|
||||
/datum/component/fantasy/proc/announce()
|
||||
var/turf/location = get_turf(parent)
|
||||
var/span
|
||||
var/effect_description
|
||||
if(quality >= 0)
|
||||
span = "<span class='notice'>"
|
||||
effect_description = "<span class='heavy_brass'>shimmering golden glow</span>"
|
||||
else
|
||||
span = "<span class='danger'>"
|
||||
effect_description = "<span class='bold'>mottled black glow</span>"
|
||||
|
||||
location.visible_message("[span][originalName] is covered by a [effect_description] and then transforms into [parent]!</span>")
|
||||
@@ -0,0 +1,13 @@
|
||||
/datum/fantasy_affix
|
||||
var/placement // A bitflag of "slots" this affix takes up, for example pre/suffix
|
||||
var/alignment
|
||||
var/weight = 10
|
||||
|
||||
// For those occasional affixes which only make sense in certain circumstances
|
||||
/datum/fantasy_affix/proc/validate(datum/component/fantasy/comp)
|
||||
return TRUE
|
||||
|
||||
/datum/fantasy_affix/proc/apply(datum/component/fantasy/comp, newName)
|
||||
return newName
|
||||
|
||||
/datum/fantasy_affix/proc/remove(datum/component/fantasy/comp)
|
||||
@@ -0,0 +1,68 @@
|
||||
/datum/fantasy_affix/cosmetic_prefixes
|
||||
placement = AFFIX_PREFIX
|
||||
alignment = AFFIX_GOOD | AFFIX_EVIL
|
||||
|
||||
var/list/goodPrefixes
|
||||
var/list/badPrefixes
|
||||
|
||||
/datum/fantasy_affix/cosmetic_prefixes/New()
|
||||
goodPrefixes = list(
|
||||
"greater",
|
||||
"major",
|
||||
"blessed",
|
||||
"superior",
|
||||
"empowered",
|
||||
"honed",
|
||||
"true",
|
||||
"glorious",
|
||||
"robust",
|
||||
)
|
||||
badPrefixes = list(
|
||||
"lesser",
|
||||
"minor",
|
||||
"blighted",
|
||||
"inferior",
|
||||
"enfeebled",
|
||||
"rusted",
|
||||
"unsteady",
|
||||
"tragic",
|
||||
"gimped",
|
||||
"cursed",
|
||||
)
|
||||
|
||||
weight = (length(goodPrefixes) + length(badPrefixes)) * 10
|
||||
|
||||
/datum/fantasy_affix/cosmetic_prefixes/apply(datum/component/fantasy/comp, newName)
|
||||
if(comp.quality > 0 || (comp.quality == 0 && prob(50)))
|
||||
return "[pick(goodPrefixes)] [newName]"
|
||||
else
|
||||
return "[pick(badPrefixes)] [newName]"
|
||||
|
||||
/datum/fantasy_affix/tactical
|
||||
placement = AFFIX_PREFIX
|
||||
alignment = AFFIX_GOOD
|
||||
weight = 1 // Very powerful, no one should have such power
|
||||
|
||||
/datum/fantasy_affix/tactical/apply(datum/component/fantasy/comp, newName)
|
||||
var/obj/item/master = comp.parent
|
||||
comp.appliedComponents += master.AddComponent(/datum/component/tactical)
|
||||
return "tactical [newName]"
|
||||
|
||||
/datum/fantasy_affix/pyromantic
|
||||
placement = AFFIX_PREFIX
|
||||
alignment = AFFIX_GOOD
|
||||
|
||||
/datum/fantasy_affix/pyromantic/apply(datum/component/fantasy/comp, newName)
|
||||
var/obj/item/master = comp.parent
|
||||
comp.appliedComponents += master.AddComponent(/datum/component/igniter, CLAMP(comp.quality, 1, 10))
|
||||
return "pyromantic [newName]"
|
||||
|
||||
/datum/fantasy_affix/vampiric
|
||||
placement = AFFIX_PREFIX
|
||||
alignment = AFFIX_GOOD
|
||||
weight = 5
|
||||
|
||||
/datum/fantasy_affix/vampiric/apply(datum/component/fantasy/comp, newName)
|
||||
var/obj/item/master = comp.parent
|
||||
comp.appliedComponents += master.AddComponent(/datum/component/lifesteal, comp.quality)
|
||||
return "vampiric [newName]"
|
||||
@@ -0,0 +1,170 @@
|
||||
/datum/fantasy_affix/cosmetic_suffixes
|
||||
placement = AFFIX_SUFFIX
|
||||
alignment = AFFIX_GOOD | AFFIX_EVIL
|
||||
|
||||
var/list/goodSuffixes
|
||||
var/list/badSuffixes
|
||||
|
||||
/datum/fantasy_affix/cosmetic_suffixes/New()
|
||||
goodSuffixes = list(
|
||||
"dexterity",
|
||||
"constitution",
|
||||
"intelligence",
|
||||
"wisdom",
|
||||
"charisma",
|
||||
"the forest",
|
||||
"the hills",
|
||||
"the plains",
|
||||
"the sea",
|
||||
"the sun",
|
||||
"the moon",
|
||||
"the void",
|
||||
"the world",
|
||||
"many secrets",
|
||||
"many tales",
|
||||
"many colors",
|
||||
"rending",
|
||||
"sundering",
|
||||
"the night",
|
||||
"the day",
|
||||
)
|
||||
badSuffixes = list(
|
||||
"draining",
|
||||
"burden",
|
||||
"discomfort",
|
||||
"awkwardness",
|
||||
"poor hygiene",
|
||||
"timidity",
|
||||
)
|
||||
|
||||
weight = (length(goodSuffixes) + length(badSuffixes)) * 10
|
||||
|
||||
/datum/fantasy_affix/cosmetic_suffixes/apply(datum/component/fantasy/comp, newName)
|
||||
if(comp.quality > 0 || (comp.quality == 0 && prob(50)))
|
||||
return "[newName] of [pick(goodSuffixes)]"
|
||||
else
|
||||
return "[newName] of [pick(badSuffixes)]"
|
||||
|
||||
//////////// Good suffixes
|
||||
/datum/fantasy_affix/bane
|
||||
placement = AFFIX_SUFFIX
|
||||
alignment = AFFIX_GOOD
|
||||
weight = 20
|
||||
|
||||
/datum/fantasy_affix/bane/apply(datum/component/fantasy/comp, newName)
|
||||
. = ..()
|
||||
// This is set up to be easy to add to these lists as I expect it will need modifications
|
||||
var/static/list/possible_mobtypes
|
||||
if(!possible_mobtypes)
|
||||
// The base list of allowed mob/species types
|
||||
possible_mobtypes = typecacheof(list(
|
||||
/mob/living/simple_animal,
|
||||
/mob/living/carbon,
|
||||
/datum/species,
|
||||
))
|
||||
// Some particular types to disallow if they're too broad/abstract
|
||||
possible_mobtypes -= list(
|
||||
/mob/living/simple_animal/hostile,
|
||||
)
|
||||
// Some types to remove them and their subtypes
|
||||
possible_mobtypes -= typecacheof(list(
|
||||
/mob/living/carbon/human/species,
|
||||
))
|
||||
|
||||
var/mob/picked_mobtype = pick(possible_mobtypes)
|
||||
// This works even with the species picks since we're only accessing the name
|
||||
|
||||
var/obj/item/master = comp.parent
|
||||
comp.appliedComponents += master.AddComponent(/datum/component/bane, picked_mobtype)
|
||||
return "[newName] of [initial(picked_mobtype.name)] slaying"
|
||||
|
||||
/datum/fantasy_affix/summoning
|
||||
placement = AFFIX_SUFFIX
|
||||
alignment = AFFIX_GOOD
|
||||
weight = 5
|
||||
|
||||
/datum/fantasy_affix/summoning/apply(datum/component/fantasy/comp, newName)
|
||||
. = ..()
|
||||
// This is set up to be easy to add to these lists as I expect it will need modifications
|
||||
var/static/list/possible_mobtypes
|
||||
if(!possible_mobtypes)
|
||||
// The base list of allowed mob/species types
|
||||
possible_mobtypes = typecacheof(list(
|
||||
/mob/living/simple_animal,
|
||||
/mob/living/carbon,
|
||||
/datum/species,
|
||||
))
|
||||
// Some particular types to disallow if they're too broad/abstract
|
||||
possible_mobtypes -= list(
|
||||
/mob/living/simple_animal/hostile,
|
||||
)
|
||||
// Some types to remove them and their subtypes
|
||||
possible_mobtypes -= typecacheof(list(
|
||||
/mob/living/carbon/human/species,
|
||||
/mob/living/simple_animal/hostile/megafauna,
|
||||
))
|
||||
|
||||
var/mob/picked_mobtype = pick(possible_mobtypes)
|
||||
// This works even with the species picks since we're only accessing the name
|
||||
|
||||
var/obj/item/master = comp.parent
|
||||
var/max_mobs = max(CEILING(comp.quality/2, 1), 1)
|
||||
var/spawn_delay = 300 - 30 * comp.quality
|
||||
comp.appliedComponents += master.AddComponent(/datum/component/summoning, list(picked_mobtype), 100, max_mobs, spawn_delay)
|
||||
return "[newName] of [initial(picked_mobtype.name)] summoning"
|
||||
|
||||
/datum/fantasy_affix/shrapnel
|
||||
placement = AFFIX_SUFFIX
|
||||
alignment = AFFIX_GOOD
|
||||
|
||||
/datum/fantasy_affix/shrapnel/validate(datum/component/fantasy/comp)
|
||||
if(isgun(comp.parent))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/fantasy_affix/shrapnel/apply(datum/component/fantasy/comp, newName)
|
||||
. = ..()
|
||||
// higher means more likely
|
||||
var/list/weighted_projectile_types = list(/obj/item/projectile/meteor = 1,
|
||||
/obj/item/projectile/energy/nuclear_particle = 1,
|
||||
/obj/item/projectile/beam/pulse = 1,
|
||||
/obj/item/projectile/bullet/honker = 15,
|
||||
/obj/item/projectile/temp = 15,
|
||||
/obj/item/projectile/ion = 15,
|
||||
/obj/item/projectile/magic/door = 15,
|
||||
/obj/item/projectile/magic/locker = 15,
|
||||
// /obj/item/projectile/magic/fetch = 15,
|
||||
/obj/item/projectile/beam/emitter = 15,
|
||||
// /obj/item/projectile/magic/flying = 15,
|
||||
/obj/item/projectile/energy/net = 15,
|
||||
/obj/item/projectile/bullet/incendiary/c9mm = 15,
|
||||
/obj/item/projectile/temp/hot = 15,
|
||||
/obj/item/projectile/beam/disabler = 15)
|
||||
|
||||
var/obj/item/projectile/picked_projectiletype = pickweight(weighted_projectile_types)
|
||||
|
||||
var/obj/item/master = comp.parent
|
||||
comp.appliedComponents += master.AddComponent(/datum/component/shrapnel, picked_projectiletype)
|
||||
return "[newName] of [initial(picked_projectiletype.name)] shrapnel"
|
||||
|
||||
/datum/fantasy_affix/strength
|
||||
placement = AFFIX_SUFFIX
|
||||
alignment = AFFIX_GOOD
|
||||
|
||||
/datum/fantasy_affix/strength/apply(datum/component/fantasy/comp, newName)
|
||||
. = ..()
|
||||
var/obj/item/master = comp.parent
|
||||
comp.appliedComponents += master.AddComponent(/datum/component/knockback, CEILING(comp.quality/2, 1), FLOOR(comp.quality/10, 1))
|
||||
return "[newName] of strength"
|
||||
|
||||
//////////// Bad suffixes
|
||||
|
||||
/datum/fantasy_affix/fool
|
||||
placement = AFFIX_SUFFIX
|
||||
alignment = AFFIX_EVIL
|
||||
|
||||
/datum/fantasy_affix/fool/apply(datum/component/fantasy/comp, newName)
|
||||
. = ..()
|
||||
var/obj/item/master = comp.parent
|
||||
comp.appliedComponents += master.AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 50)
|
||||
return "[newName] of the fool"
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
/datum/component/igniter
|
||||
var/fire_stacks
|
||||
|
||||
/datum/component/igniter/Initialize(fire_stacks=1)
|
||||
if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.fire_stacks = fire_stacks
|
||||
|
||||
/datum/component/igniter/RegisterWithParent()
|
||||
if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
|
||||
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
|
||||
else if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack)
|
||||
else if(ishostile(parent))
|
||||
RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
|
||||
|
||||
/datum/component/igniter/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
|
||||
|
||||
/datum/component/igniter/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
if(!proximity_flag)
|
||||
return
|
||||
do_igniter(target)
|
||||
|
||||
/datum/component/igniter/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target)
|
||||
do_igniter(target)
|
||||
|
||||
/datum/component/igniter/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
|
||||
do_igniter(target)
|
||||
|
||||
/datum/component/igniter/proc/do_igniter(atom/target)
|
||||
if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
L.adjust_fire_stacks(fire_stacks)
|
||||
L.IgniteMob()
|
||||
@@ -45,7 +45,7 @@
|
||||
var/knockdown_chance = (target_buckled? mounted_knockdown_chance_per_tile : unmounted_knockdown_chance_per_tile) * current
|
||||
var/knockdown_time = (target_buckled? mounted_knockdown_time : unmounted_knockdown_time)
|
||||
var/damage = (target_buckled? mounted_damage_boost_per_tile : unmounted_damage_boost_per_tile) * current
|
||||
var/sharp = I.is_sharp()
|
||||
var/sharp = I.get_sharpness()
|
||||
var/msg
|
||||
if(damage)
|
||||
msg += "[user] [sharp? "impales" : "slams into"] [target] [sharp? "on" : "with"] their [parent]"
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/datum/component/knockback
|
||||
var/throw_distance
|
||||
var/throw_anchored
|
||||
|
||||
/datum/component/knockback/Initialize(throw_distance=1)
|
||||
if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.throw_distance = throw_distance
|
||||
src.throw_anchored = throw_anchored
|
||||
|
||||
/datum/component/knockback/RegisterWithParent()
|
||||
if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
|
||||
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
|
||||
else if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack)
|
||||
else if(ishostile(parent))
|
||||
RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
|
||||
|
||||
/datum/component/knockback/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
|
||||
|
||||
/datum/component/knockback/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
if(!proximity_flag)
|
||||
return
|
||||
do_knockback(target, user, get_dir(source, target))
|
||||
|
||||
/datum/component/knockback/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target)
|
||||
do_knockback(target, attacker, get_dir(attacker, target))
|
||||
|
||||
/datum/component/knockback/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
|
||||
do_knockback(target, null, angle2dir(Angle))
|
||||
|
||||
/datum/component/knockback/proc/do_knockback(atom/target, mob/thrower, throw_dir)
|
||||
if(!ismovableatom(target) || throw_dir == null)
|
||||
return
|
||||
var/atom/movable/throwee = target
|
||||
if(throwee.anchored && !throw_anchored)
|
||||
return
|
||||
if(throw_distance < 0)
|
||||
throw_dir = turn(throw_dir, 180)
|
||||
throw_distance *= -1
|
||||
var/atom/throw_target = get_edge_target_turf(throwee, throw_dir)
|
||||
throwee.safe_throw_at(throw_target, throw_distance, 1, thrower)
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
/datum/component/lifesteal
|
||||
var/flat_heal // heals a constant amount every time a hit occurs
|
||||
var/static/list/damage_heal_order = list(BRUTE, BURN, OXY)
|
||||
|
||||
/datum/component/lifesteal/Initialize(flat_heal=0)
|
||||
if(!isitem(parent) && !ishostile(parent) && !isgun(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.flat_heal = flat_heal
|
||||
|
||||
/datum/component/lifesteal/RegisterWithParent()
|
||||
if(isgun(parent))
|
||||
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
|
||||
else if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack)
|
||||
else if(ishostile(parent))
|
||||
RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
|
||||
|
||||
/datum/component/lifesteal/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
|
||||
|
||||
/datum/component/lifesteal/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
if(!proximity_flag)
|
||||
return
|
||||
do_lifesteal(user, target)
|
||||
|
||||
/datum/component/lifesteal/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target)
|
||||
do_lifesteal(attacker, target)
|
||||
|
||||
/datum/component/lifesteal/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
|
||||
do_lifesteal(firer, target)
|
||||
|
||||
/datum/component/lifesteal/proc/do_lifesteal(atom/heal_target, atom/damage_target)
|
||||
if(isliving(heal_target) && isliving(damage_target))
|
||||
var/mob/living/healing = heal_target
|
||||
var/mob/living/damaging = damage_target
|
||||
if(damaging.stat != DEAD)
|
||||
healing.heal_ordered_damage(flat_heal, damage_heal_order)
|
||||
@@ -10,7 +10,6 @@
|
||||
var/mood_modifier = 1 //Modifier to allow certain mobs to be less affected by moodlets
|
||||
var/datum/mood_event/list/mood_events = list()
|
||||
var/insanity_effect = 0 //is the owner being punished for low mood? If so, how much?
|
||||
var/holdmyinsanityeffect = 0 //before we edit our sanity lets take a look
|
||||
var/obj/screen/mood/screen_obj
|
||||
|
||||
/datum/component/mood/Initialize()
|
||||
@@ -21,8 +20,7 @@
|
||||
|
||||
RegisterSignal(parent, COMSIG_ADD_MOOD_EVENT, .proc/add_event)
|
||||
RegisterSignal(parent, COMSIG_CLEAR_MOOD_EVENT, .proc/clear_event)
|
||||
RegisterSignal(parent, COMSIG_INCREASE_SANITY, .proc/IncreaseSanity)
|
||||
RegisterSignal(parent, COMSIG_DECREASE_SANITY, .proc/DecreaseSanity)
|
||||
RegisterSignal(parent, COMSIG_MODIFY_SANITY, .proc/modify_sanity)
|
||||
|
||||
RegisterSignal(parent, COMSIG_MOB_HUD_CREATED, .proc/modify_hud)
|
||||
var/mob/living/owner = parent
|
||||
@@ -131,31 +129,23 @@
|
||||
|
||||
switch(mood_level)
|
||||
if(1)
|
||||
DecreaseSanity(src, 0.2)
|
||||
setSanity(sanity-0.2)
|
||||
if(2)
|
||||
DecreaseSanity(src, 0.125, SANITY_CRAZY)
|
||||
setSanity(sanity-0.125, minimum=SANITY_CRAZY)
|
||||
if(3)
|
||||
DecreaseSanity(src, 0.075, SANITY_UNSTABLE)
|
||||
setSanity(sanity-0.075, minimum=SANITY_UNSTABLE)
|
||||
if(4)
|
||||
DecreaseSanity(src, 0.025, SANITY_DISTURBED)
|
||||
setSanity(sanity-0.025, minimum=SANITY_DISTURBED)
|
||||
if(5)
|
||||
IncreaseSanity(src, 0.1)
|
||||
setSanity(sanity+0.1)
|
||||
if(6)
|
||||
IncreaseSanity(src, 0.15)
|
||||
setSanity(sanity+0.15)
|
||||
if(7)
|
||||
IncreaseSanity(src, 0.20)
|
||||
setSanity(sanity+0.20)
|
||||
if(8)
|
||||
IncreaseSanity(src, 0.25, SANITY_GREAT)
|
||||
setSanity(sanity+0.25, maximum=SANITY_GREAT)
|
||||
if(9)
|
||||
IncreaseSanity(src, 0.4, SANITY_GREAT)
|
||||
|
||||
/*
|
||||
if(insanity_effect != holdmyinsanityeffect)
|
||||
if(insanity_effect > holdmyinsanityeffect)
|
||||
owner.crit_threshold += (insanity_effect - holdmyinsanityeffect)
|
||||
else
|
||||
owner.crit_threshold -= (holdmyinsanityeffect - insanity_effect)
|
||||
*/
|
||||
setSanity(sanity+0.4, maximum=SANITY_GREAT)
|
||||
|
||||
if(HAS_TRAIT(owner, TRAIT_DEPRESSION))
|
||||
if(prob(0.05))
|
||||
@@ -166,8 +156,6 @@
|
||||
add_event(null, "jolly", /datum/mood_event/jolly)
|
||||
clear_event(null, "depression")
|
||||
|
||||
holdmyinsanityeffect = insanity_effect
|
||||
|
||||
HandleNutrition(owner)
|
||||
|
||||
/datum/component/mood/proc/setSanity(amount, minimum=SANITY_INSANE, maximum=SANITY_NEUTRAL)//I'm sure bunging this in here will have no negative repercussions.
|
||||
@@ -189,7 +177,7 @@
|
||||
sanity = amount
|
||||
|
||||
switch(sanity)
|
||||
if(SANITY_INSANE to SANITY_CRAZY)
|
||||
if(-INFINITY to SANITY_CRAZY)
|
||||
setInsanityEffect(MAJOR_INSANITY_PEN)
|
||||
master.add_movespeed_modifier(MOVESPEED_ID_SANITY, TRUE, 100, override=TRUE, multiplicative_slowdown=1.5) //Did we change something ? movetypes is runtiming, movetypes=(~FLYING))
|
||||
sanity_level = 6
|
||||
@@ -222,31 +210,8 @@
|
||||
//master.crit_threshold = (master.crit_threshold - insanity_effect) + newval
|
||||
insanity_effect = newval
|
||||
|
||||
/datum/component/mood/proc/DecreaseSanity(datum/source, amount, minimum = SANITY_INSANE)
|
||||
if(sanity < minimum) //This might make KevinZ stop fucking pinging me.
|
||||
IncreaseSanity(src, 0.5)
|
||||
else
|
||||
sanity = max(minimum, sanity - amount)
|
||||
if(sanity < SANITY_UNSTABLE)
|
||||
if(sanity < SANITY_CRAZY)
|
||||
insanity_effect = (MAJOR_INSANITY_PEN)
|
||||
else
|
||||
insanity_effect = (MINOR_INSANITY_PEN)
|
||||
|
||||
/datum/component/mood/proc/IncreaseSanity(datum/source, amount, maximum = SANITY_NEUTRAL)
|
||||
// Disturbed stops you from getting any more sane - I'm just gonna bung this in here
|
||||
var/mob/living/owner = parent
|
||||
if(HAS_TRAIT(owner, TRAIT_UNSTABLE))
|
||||
return
|
||||
if(sanity > maximum)
|
||||
DecreaseSanity(src, 0.5) //Removes some sanity to go back to our current limit.
|
||||
else
|
||||
sanity = min(maximum, sanity + amount)
|
||||
if(sanity > SANITY_CRAZY)
|
||||
if(sanity > SANITY_UNSTABLE)
|
||||
insanity_effect = 0
|
||||
else
|
||||
insanity_effect = MINOR_INSANITY_PEN
|
||||
/datum/component/mood/proc/modify_sanity(datum/source, amount, minimum = -INFINITY, maximum = INFINITY)
|
||||
setSanity(sanity + amount, minimum, maximum)
|
||||
|
||||
/datum/component/mood/proc/add_event(datum/source, category, type, param) //Category will override any events in the same category, should be unique unless the event is based on the same thing like hunger.
|
||||
var/datum/mood_event/the_event
|
||||
|
||||
@@ -7,33 +7,24 @@
|
||||
var/filter_x
|
||||
var/filter_y
|
||||
var/filter_size
|
||||
var/filter_border
|
||||
var/filter_color
|
||||
|
||||
/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _border = 0, _color = "#E62111", list/_valid_slots = list(SLOT_GLASSES))
|
||||
/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _color = "#E62111", list/_valid_slots = list(SLOT_GLASSES))
|
||||
. = ..()
|
||||
if(. == COMPONENT_INCOMPATIBLE)
|
||||
return
|
||||
filter_x = _x
|
||||
filter_y = _y
|
||||
filter_size = _size
|
||||
filter_border = _border
|
||||
filter_color = _color
|
||||
valid_slots = _valid_slots
|
||||
|
||||
/datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(datum/source, mob/user, combatmodestate)
|
||||
if(istype(user))
|
||||
var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
|
||||
if(!combatmodestate)
|
||||
user.filters -= thefilter
|
||||
else
|
||||
user.filters += thefilter
|
||||
|
||||
/datum/component/wearertargeting/phantomthief/proc/stripdesiredfilter(mob/user)
|
||||
if(istype(user))
|
||||
var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color)
|
||||
user.filters -= thefilter
|
||||
if(!combatmodestate)
|
||||
user.remove_filter("phantomthief")
|
||||
else
|
||||
user.add_filter("phantomthief", 4, list(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, color = filter_color))
|
||||
|
||||
/datum/component/wearertargeting/phantomthief/on_drop(datum/source, mob/user)
|
||||
. = ..()
|
||||
stripdesiredfilter(user)
|
||||
user.remove_filter("phantomthief")
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
var/ride_check_rider_incapacitated = FALSE
|
||||
var/ride_check_rider_restrained = FALSE
|
||||
var/ride_check_ridden_incapacitated = FALSE
|
||||
var/list/offhands = list() // keyed list containing all the current riding offsets associated by mob
|
||||
|
||||
/datum/component/riding/Initialize()
|
||||
if(!ismovableatom(parent))
|
||||
@@ -299,36 +300,34 @@
|
||||
M.throw_at(target, 14, 5, AM)
|
||||
M.Knockdown(60)
|
||||
|
||||
/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1, riding_target_override = null)
|
||||
var/atom/movable/AM = parent
|
||||
var/amount_equipped = 0
|
||||
/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1, mob/living/riding_target_override)
|
||||
var/list/equipped
|
||||
var/mob/living/L = riding_target_override ? riding_target_override : user
|
||||
for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--)
|
||||
var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user)
|
||||
if(!riding_target_override)
|
||||
inhand.rider = user
|
||||
else
|
||||
inhand.rider = riding_target_override
|
||||
inhand.parent = AM
|
||||
if(user.put_in_hands(inhand, TRUE))
|
||||
amount_equipped++
|
||||
else
|
||||
var/obj/item/riding_offhand/inhand = new
|
||||
inhand.rider = L
|
||||
inhand.parent = parent
|
||||
if(!user.put_in_hands(inhand, TRUE))
|
||||
qdel(inhand) // it isn't going to be added to offhands anyway
|
||||
break
|
||||
LAZYADD(equipped, src)
|
||||
var/amount_equipped = LAZYLEN(equipped)
|
||||
if(amount_equipped)
|
||||
LAZYADD(offhands[L], amount_equipped)
|
||||
if(amount_equipped >= amount_required)
|
||||
return TRUE
|
||||
else
|
||||
unequip_buckle_inhands(user)
|
||||
return FALSE
|
||||
unequip_buckle_inhands(L)
|
||||
return FALSE
|
||||
|
||||
/datum/component/riding/proc/unequip_buckle_inhands(mob/living/carbon/user)
|
||||
var/atom/movable/AM = parent
|
||||
for(var/obj/item/riding_offhand/O in user.contents)
|
||||
if(O.parent != AM)
|
||||
CRASH("RIDING OFFHAND ON WRONG MOB")
|
||||
continue
|
||||
if(O.selfdeleting)
|
||||
continue
|
||||
else
|
||||
qdel(O)
|
||||
for(var/a in offhands[user])
|
||||
LAZYREMOVE(offhands[user], a)
|
||||
if(a) //edge cases null entries
|
||||
var/obj/item/riding_offhand/O = a
|
||||
if(O.parent != parent)
|
||||
CRASH("RIDING OFFHAND ON WRONG MOB")
|
||||
else if(!O.selfdeleting)
|
||||
qdel(O)
|
||||
return TRUE
|
||||
|
||||
/obj/item/riding_offhand
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
set src in oview(1)
|
||||
var/datum/component/simple_rotation/rotcomp = GetComponent(/datum/component/simple_rotation)
|
||||
if(rotcomp)
|
||||
rotcomp.HandRot(usr,ROTATION_CLOCKWISE)
|
||||
rotcomp.HandRot(null,usr,ROTATION_CLOCKWISE)
|
||||
|
||||
/atom/movable/proc/simple_rotate_counterclockwise()
|
||||
set name = "Rotate Counter-Clockwise"
|
||||
@@ -153,7 +153,7 @@
|
||||
set src in oview(1)
|
||||
var/datum/component/simple_rotation/rotcomp = GetComponent(/datum/component/simple_rotation)
|
||||
if(rotcomp)
|
||||
rotcomp.HandRot(usr,ROTATION_COUNTERCLOCKWISE)
|
||||
rotcomp.HandRot(null,usr,ROTATION_COUNTERCLOCKWISE)
|
||||
|
||||
/atom/movable/proc/simple_rotate_flip()
|
||||
set name = "Flip"
|
||||
@@ -161,4 +161,4 @@
|
||||
set src in oview(1)
|
||||
var/datum/component/simple_rotation/rotcomp = GetComponent(/datum/component/simple_rotation)
|
||||
if(rotcomp)
|
||||
rotcomp.HandRot(usr,ROTATION_FLIP)
|
||||
rotcomp.HandRot(null,usr,ROTATION_FLIP)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
/datum/component/shrapnel
|
||||
var/projectile_type
|
||||
var/radius // shoots a projectile for every turf on this radius from the hit target
|
||||
var/override_projectile_range
|
||||
|
||||
/datum/component/shrapnel/Initialize(projectile_type, radius=1, override_projectile_range)
|
||||
if(!isgun(parent) && !ismachinery(parent) && !isstructure(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.projectile_type = projectile_type
|
||||
src.radius = radius
|
||||
src.override_projectile_range = override_projectile_range
|
||||
|
||||
/datum/component/shrapnel/RegisterWithParent()
|
||||
if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc
|
||||
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
|
||||
|
||||
/datum/component/shrapnel/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(COMSIG_PROJECTILE_ON_HIT))
|
||||
|
||||
/datum/component/shrapnel/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
|
||||
do_shrapnel(firer, target)
|
||||
|
||||
/datum/component/shrapnel/proc/do_shrapnel(mob/firer, atom/target)
|
||||
if(radius < 1)
|
||||
return
|
||||
var/turf/target_turf = get_turf(target)
|
||||
for(var/turf/shootat_turf in RANGE_TURFS(radius, target) - RANGE_TURFS(radius-1, target))
|
||||
var/obj/item/projectile/P = new projectile_type(target_turf)
|
||||
|
||||
//Shooting Code:
|
||||
P.range = radius+1
|
||||
if(override_projectile_range)
|
||||
P.range = override_projectile_range
|
||||
P.preparePixelProjectile(shootat_turf, target)
|
||||
P.firer = firer // don't hit ourself that would be really annoying
|
||||
P.permutated += target // don't hit the target we hit already with the flak
|
||||
P.fire()
|
||||
@@ -0,0 +1,69 @@
|
||||
|
||||
/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))
|
||||
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)) // turrets, etc
|
||||
RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit)
|
||||
else if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack)
|
||||
else if(ishostile(parent))
|
||||
RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget)
|
||||
|
||||
/datum/component/summoning/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT))
|
||||
|
||||
/datum/component/summoning/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters)
|
||||
if(!proximity_flag)
|
||||
return
|
||||
do_spawn_mob(get_turf(target), user)
|
||||
|
||||
/datum/component/summoning/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target)
|
||||
do_spawn_mob(get_turf(target), attacker)
|
||||
|
||||
/datum/component/summoning/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle)
|
||||
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 0
|
||||
if(last_spawned_time > world.time)
|
||||
return 0
|
||||
if(!prob(spawn_chance))
|
||||
return 0
|
||||
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_MOB_DEATH, .proc/on_spawned_death) // so we can remove them from the list, etc (for mobs with corpses)
|
||||
playsound(spawn_location,spawn_sound, 50, 1)
|
||||
spawn_location.visible_message("<span class='danger'>[L] [spawn_text].</span>")
|
||||
|
||||
/datum/component/summoning/proc/on_spawned_death(mob/killed, gibbed)
|
||||
spawned_mobs -= killed
|
||||
@@ -0,0 +1,42 @@
|
||||
|
||||
/datum/component/tactical
|
||||
var/allowed_slot
|
||||
|
||||
/datum/component/tactical/Initialize(allowed_slot)
|
||||
if(!isitem(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.allowed_slot = allowed_slot
|
||||
|
||||
/datum/component/tactical/RegisterWithParent()
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/modify)
|
||||
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/unmodify)
|
||||
|
||||
/datum/component/tactical/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED))
|
||||
unmodify()
|
||||
|
||||
/datum/component/fantasy/Destroy()
|
||||
unmodify()
|
||||
return ..()
|
||||
|
||||
/datum/component/tactical/proc/modify(obj/item/source, mob/user, slot)
|
||||
if(allowed_slot && slot != allowed_slot)
|
||||
unmodify()
|
||||
return
|
||||
|
||||
var/obj/item/master = parent
|
||||
var/image/I = image(icon = master.icon, icon_state = master.icon_state, loc = user)
|
||||
I.copy_overlays(master)
|
||||
I.override = TRUE
|
||||
source.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I)
|
||||
I.layer = ABOVE_MOB_LAYER
|
||||
|
||||
/datum/component/tactical/proc/unmodify(obj/item/source, mob/user)
|
||||
var/obj/item/master = source || parent
|
||||
if(!user)
|
||||
if(!ismob(master.loc))
|
||||
return
|
||||
user = master.loc
|
||||
|
||||
user.remove_alt_appearance("sneaking_mission")
|
||||
@@ -15,7 +15,7 @@
|
||||
/turf/closed/indestructible,
|
||||
/turf/open/indestructible)
|
||||
)
|
||||
|
||||
|
||||
var/static/list/resistlist = typecacheof(
|
||||
/turf/closed/wall/r_wall
|
||||
)
|
||||
@@ -77,5 +77,5 @@
|
||||
thermite_melt()
|
||||
|
||||
/datum/component/thermite/proc/attackby_react(datum/source, obj/item/thing, mob/user, params)
|
||||
if(thing.is_hot())
|
||||
if(thing.get_temperature())
|
||||
thermite_melt(user)
|
||||
Reference in New Issue
Block a user