Merge branch 'master' into upstream-merge-33614
This commit is contained in:
@@ -40,6 +40,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
* `COMPONENT_DUPE_HIGHLANDER` (default): Old component will be deleted, new component will first have `/datum/component/proc/InheritComponent(datum/component/old, FALSE)` on it
|
||||
* `COMPONENT_DUPE_ALLOWED`: The components will be treated as separate, `GetComponent()` will return the first added
|
||||
* `COMPONENT_DUPE_UNIQUE`: New component will be deleted, old component will first have `/datum/component/proc/InheritComponent(datum/component/new, TRUE)` on it
|
||||
* `COMPONENT_DUPE_UNIQUE_PASSARGS`: New component will never exist and instead its initialization arguments will be passed on to the old component.
|
||||
1. `/datum/component/var/dupe_type` (protected, type)
|
||||
* Definition of a duplicate component type
|
||||
* `null` means exact match on `type` (default)
|
||||
@@ -66,6 +67,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
* All components a datum owns are deleted with the datum
|
||||
* Returns the component that was created. Or the old component in a dupe situation where `COMPONENT_DUPE_UNIQUE` was set
|
||||
* If this tries to add an component to an incompatible type, the component will be deleted and the result will be `null`. This is very unperformant, try not to do it
|
||||
* Properly handles duplicate situations based on the `dupe_mode` var
|
||||
1. `/datum/proc/LoadComponent(component_type(type), ...) -> datum/component` (public, final)
|
||||
* Equivalent to calling `GetComponent(component_type)` where, if the result would be `null`, returns `AddComponent(component_type, ...)` instead
|
||||
1. `/datum/proc/ComponentActivated(datum/component/C)` (abstract, async)
|
||||
@@ -104,9 +106,8 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
* Allows the component to react to ownership transfers
|
||||
1. `/datum/component/proc/_RemoveFromParent()` (private, final)
|
||||
* Clears `parent` and removes the component from it's component list
|
||||
1. `/datum/component/proc/_CheckDupesAndJoinParent` (private, final)
|
||||
1. `/datum/component/proc/_JoinParent` (private, final)
|
||||
* Tries to add the component to it's `parent`s `datum_components` list
|
||||
* Properly handles duplicate situations based on the `dupe_mode` var
|
||||
1. `/datum/component/proc/RegisterSignal(signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final) (Consider removing for performance gainz)
|
||||
* If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments
|
||||
* Makes a component listen for the specified `signal` on it's `parent` datum.
|
||||
|
||||
@@ -6,54 +6,16 @@
|
||||
var/datum/parent
|
||||
|
||||
/datum/component/New(datum/P, ...)
|
||||
if(type == /datum/component)
|
||||
qdel(src)
|
||||
CRASH("[type] instantiated!")
|
||||
|
||||
//check for common mishaps
|
||||
if(!isnum(dupe_mode))
|
||||
qdel(src)
|
||||
CRASH("[type]: Invalid dupe_mode!")
|
||||
var/dt = dupe_type
|
||||
if(dt && !ispath(dt))
|
||||
qdel(src)
|
||||
CRASH("[type]: Invalid dupe_type!")
|
||||
|
||||
parent = P
|
||||
var/list/arguments = args.Copy(2)
|
||||
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
|
||||
qdel(src, TRUE, TRUE)
|
||||
return
|
||||
|
||||
_CheckDupesAndJoinParent(P)
|
||||
_JoinParent(P)
|
||||
|
||||
/datum/component/proc/_CheckDupesAndJoinParent()
|
||||
/datum/component/proc/_JoinParent()
|
||||
var/datum/P = parent
|
||||
var/dm = dupe_mode
|
||||
|
||||
var/datum/component/old
|
||||
if(dm != COMPONENT_DUPE_ALLOWED)
|
||||
var/dt = dupe_type
|
||||
if(!dt)
|
||||
old = P.GetExactComponent(type)
|
||||
else
|
||||
old = P.GetComponent(dt)
|
||||
if(old)
|
||||
//One or the other has to die
|
||||
switch(dm)
|
||||
if(COMPONENT_DUPE_UNIQUE)
|
||||
old.InheritComponent(src, TRUE)
|
||||
qdel(src, TRUE, TRUE)
|
||||
return
|
||||
if(COMPONENT_DUPE_HIGHLANDER)
|
||||
InheritComponent(old, FALSE)
|
||||
qdel(old, FALSE, TRUE)
|
||||
|
||||
//provided we didn't eat someone
|
||||
if(!old)
|
||||
//let the others know
|
||||
P.SendSignal(COMSIG_COMPONENT_ADDED, src)
|
||||
|
||||
//lazy init the parent's dc list
|
||||
var/list/dc = P.datum_components
|
||||
if(!dc)
|
||||
@@ -212,10 +174,59 @@
|
||||
return list(.)
|
||||
|
||||
/datum/proc/AddComponent(new_type, ...)
|
||||
var/nt = new_type
|
||||
var/datum/component/nt = new_type
|
||||
var/dm = initial(nt.dupe_mode)
|
||||
var/dt = initial(nt.dupe_type)
|
||||
|
||||
var/datum/component/old_comp
|
||||
var/datum/component/new_comp
|
||||
|
||||
if(ispath(nt))
|
||||
if(nt == /datum/component)
|
||||
CRASH("[nt] attempted instantiation!")
|
||||
if(!isnum(dm))
|
||||
CRASH("[nt]: Invalid dupe_mode ([dm])!")
|
||||
if(dt && !ispath(dt))
|
||||
CRASH("[nt]: Invalid dupe_type ([dt])!")
|
||||
else
|
||||
new_comp = nt
|
||||
|
||||
args[1] = src
|
||||
var/datum/component/C = new nt(arglist(args))
|
||||
return QDELING(C) ? GetExactComponent(new_type) : C
|
||||
|
||||
if(dm != COMPONENT_DUPE_ALLOWED)
|
||||
if(!dt)
|
||||
old_comp = GetExactComponent(nt)
|
||||
else
|
||||
old_comp = GetComponent(dt)
|
||||
if(old_comp)
|
||||
switch(dm)
|
||||
if(COMPONENT_DUPE_UNIQUE)
|
||||
if(!new_comp)
|
||||
new_comp = new nt(arglist(args))
|
||||
if(!QDELETED(new_comp))
|
||||
old_comp.InheritComponent(new_comp, TRUE)
|
||||
qdel(new_comp)
|
||||
if(COMPONENT_DUPE_HIGHLANDER)
|
||||
if(!new_comp)
|
||||
new_comp = new nt(arglist(args))
|
||||
if(!QDELETED(new_comp))
|
||||
new_comp.InheritComponent(old_comp, FALSE)
|
||||
qdel(old_comp)
|
||||
if(COMPONENT_DUPE_UNIQUE_PASSARGS)
|
||||
if(!new_comp)
|
||||
var/list/arguments = args.Copy(2)
|
||||
old_comp.InheritComponent(null, TRUE, arguments)
|
||||
else
|
||||
old_comp.InheritComponent(new_comp, TRUE)
|
||||
else if(!new_comp)
|
||||
new_comp = new nt(arglist(args)) // There's a valid dupe mode but there's no old component, act like normal
|
||||
else if(!new_comp)
|
||||
new_comp = new nt(arglist(args)) // Dupes are allowed, act like normal
|
||||
|
||||
if(!old_comp && !QDELETED(new_comp)) // Nothing related to duplicate components happened and the new component is healthy
|
||||
SendSignal(COMSIG_COMPONENT_ADDED, new_comp)
|
||||
return new_comp
|
||||
return old_comp
|
||||
|
||||
/datum/proc/LoadComponent(component_type, ...)
|
||||
. = GetComponent(component_type)
|
||||
@@ -235,7 +246,8 @@
|
||||
C._RemoveFromParent()
|
||||
helicopter.SendSignal(COMSIG_COMPONENT_REMOVING, C)
|
||||
C.parent = src
|
||||
C._CheckDupesAndJoinParent()
|
||||
if(C == AddComponent(C))
|
||||
C._JoinParent()
|
||||
|
||||
/datum/proc/TransferComponents(datum/target)
|
||||
var/list/dc = datum_components
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
var/datum/callback/callback
|
||||
|
||||
/datum/component/archaeology/Initialize(_prob2drop, list/_archdrops = list(), datum/callback/_callback)
|
||||
prob2drop = Clamp(_prob2drop, 0, 100)
|
||||
prob2drop = CLAMP(_prob2drop, 0, 100)
|
||||
archdrops = _archdrops
|
||||
callback = _callback
|
||||
RegisterSignal(COMSIG_PARENT_ATTACKBY,.proc/Dig)
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/datum/component/jousting
|
||||
var/current_direction = NONE
|
||||
var/max_tile_charge = 5
|
||||
var/min_tile_charge = 2 //tiles before this code gets into effect.
|
||||
var/current_tile_charge = 0
|
||||
var/movement_reset_tolerance = 2 //deciseconds
|
||||
var/unmounted_damage_boost_per_tile = 0
|
||||
var/unmounted_knockdown_chance_per_tile = 0
|
||||
var/unmounted_knockdown_time = 0
|
||||
var/mounted_damage_boost_per_tile = 2
|
||||
var/mounted_knockdown_chance_per_tile = 20
|
||||
var/mounted_knockdown_time = 20
|
||||
var/requires_mob_riding = TRUE //whether this only works if the attacker is riding a mob, rather than anything they can buckle to.
|
||||
var/requires_mount = TRUE //kinda defeats the point of jousting if you're not mounted but whatever.
|
||||
var/mob/current_holder
|
||||
var/datum/component/redirect/listener
|
||||
var/current_timerid
|
||||
|
||||
/datum/component/jousting/Initialize()
|
||||
if(!isitem(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
stack_trace("Warning: Jousting component incorrectly applied to invalid parent type [parent.type]")
|
||||
RegisterSignal(COMSIG_ITEM_EQUIPPED, .proc/on_equip)
|
||||
RegisterSignal(COMSIG_ITEM_DROPPED, .proc/on_drop)
|
||||
RegisterSignal(COMSIG_ITEM_ATTACK, .proc/on_attack)
|
||||
|
||||
/datum/component/jousting/Destroy()
|
||||
QDEL_NULL(listener)
|
||||
return ..()
|
||||
|
||||
/datum/component/jousting/proc/on_equip(mob/user, slot)
|
||||
QDEL_NULL(listener)
|
||||
current_holder = user
|
||||
listener = new(user, COMSIG_MOVABLE_MOVED, CALLBACK(src, .proc/mob_move))
|
||||
|
||||
/datum/component/jousting/proc/on_drop(mob/user)
|
||||
QDEL_NULL(listener)
|
||||
current_holder = null
|
||||
current_direction = NONE
|
||||
current_tile_charge = 0
|
||||
|
||||
/datum/component/jousting/proc/on_attack(mob/living/target, mob/user)
|
||||
if(user != current_holder)
|
||||
return
|
||||
var/current = current_tile_charge
|
||||
var/obj/item/I = parent
|
||||
var/target_buckled = target.buckled ? TRUE : FALSE //we don't need the reference of what they're buckled to, just whether they are.
|
||||
if((requires_mount && ((requires_mob_riding && !ismob(user.buckled)) || (!user.buckled))) || !current_direction || (current_tile_charge < min_tile_charge))
|
||||
return
|
||||
var/turf/target_turf = get_step(user, current_direction)
|
||||
if(target in range(1, target_turf))
|
||||
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/msg
|
||||
if(damage)
|
||||
msg += "[user] [sharp? "impales" : "slams into"] [target] [sharp? "on" : "with"] their [parent]"
|
||||
target.apply_damage(damage, BRUTE, user.zone_selected, 0)
|
||||
if(prob(knockdown_chance))
|
||||
msg += " and knocks [target] [target_buckled? "off of [target.buckled]" : "down"]"
|
||||
if(target_buckled)
|
||||
target.buckled.unbuckle_mob(target)
|
||||
target.Knockdown(knockdown_time)
|
||||
if(length(msg))
|
||||
user.visible_message("<span class='danger'>[msg]!</span>")
|
||||
|
||||
/datum/component/jousting/proc/mob_move(newloc, dir)
|
||||
if(!current_holder || (requires_mount && ((requires_mob_riding && !ismob(current_holder.buckled)) || (!current_holder.buckled))))
|
||||
return
|
||||
if(dir != current_direction)
|
||||
current_tile_charge = 0
|
||||
current_direction = dir
|
||||
if(current_tile_charge < max_tile_charge)
|
||||
current_tile_charge++
|
||||
if(current_timerid)
|
||||
deltimer(current_timerid)
|
||||
current_timerid = addtimer(CALLBACK(src, .proc/reset_charge), movement_reset_tolerance, TIMER_STOPPABLE)
|
||||
|
||||
/datum/component/jousting/proc/reset_charge()
|
||||
current_tile_charge = 0
|
||||
@@ -0,0 +1,53 @@
|
||||
//Items with these will have a chance to get knocked off when disarming
|
||||
/datum/component/knockoff
|
||||
var/knockoff_chance = 100 //Chance to knockoff
|
||||
var/list/target_zones //Aiming for these zones will cause the knockoff, null means all zones allowed
|
||||
var/list/slots_knockoffable //Can be only knocked off from these slots, null means all slots allowed
|
||||
var/datum/component/redirect/disarm_redirect
|
||||
|
||||
/datum/component/knockoff/Initialize(knockoff_chance,zone_override,slots_knockoffable)
|
||||
if(!isitem(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Knockoff component misuse")
|
||||
RegisterSignal(COMSIG_ITEM_EQUIPPED,.proc/OnEquipped)
|
||||
RegisterSignal(COMSIG_ITEM_DROPPED,.proc/OnDropped)
|
||||
|
||||
src.knockoff_chance = knockoff_chance
|
||||
|
||||
if(zone_override)
|
||||
target_zones = zone_override
|
||||
|
||||
if(slots_knockoffable)
|
||||
src.slots_knockoffable = slots_knockoffable
|
||||
|
||||
/datum/component/knockoff/proc/Knockoff(mob/living/attacker,zone)
|
||||
var/obj/item/I = parent
|
||||
var/mob/living/carbon/human/wearer = I.loc
|
||||
if(!istype(wearer))
|
||||
return
|
||||
if(target_zones && !(zone in target_zones))
|
||||
return
|
||||
if(!prob(knockoff_chance))
|
||||
return
|
||||
if(!wearer.dropItemToGround(I))
|
||||
return
|
||||
|
||||
wearer.visible_message("<span class='warning'>[attacker] knocks off [wearer]'s [I.name]!</span>","<span class='userdanger'>[attacker] knocks off your [I.name]!</span>")
|
||||
|
||||
/datum/component/knockoff/proc/OnEquipped(mob/living/carbon/human/H,slot)
|
||||
if(!istype(H))
|
||||
return
|
||||
if(slots_knockoffable && !(slot in slots_knockoffable))
|
||||
if(disarm_redirect)
|
||||
QDEL_NULL(disarm_redirect)
|
||||
return
|
||||
if(!disarm_redirect)
|
||||
disarm_redirect = H.AddComponent(/datum/component/redirect,list(COMSIG_HUMAN_DISARM_HIT),CALLBACK(src,.proc/Knockoff))
|
||||
|
||||
/datum/component/knockoff/proc/OnDropped(mob/living/M)
|
||||
if(disarm_redirect)
|
||||
QDEL_NULL(disarm_redirect)
|
||||
|
||||
/datum/component/knockoff/Destroy()
|
||||
QDEL_NULL(disarm_redirect)
|
||||
. = ..()
|
||||
@@ -4,7 +4,7 @@
|
||||
#define RAD_AMOUNT_EXTREME 1000
|
||||
|
||||
/datum/component/radioactive
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
||||
|
||||
var/source
|
||||
|
||||
@@ -47,13 +47,16 @@
|
||||
if(strength <= RAD_BACKGROUND_RADIATION)
|
||||
return PROCESS_KILL
|
||||
|
||||
/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original)
|
||||
/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original, list/arguments)
|
||||
if(!i_am_original)
|
||||
return
|
||||
if(!hl3_release_date) // Permanently radioactive things don't get to grow stronger
|
||||
return
|
||||
var/datum/component/radioactive/other = C
|
||||
strength = max(strength, other.strength)
|
||||
if(C)
|
||||
var/datum/component/radioactive/other = C
|
||||
strength = max(strength, other.strength)
|
||||
else
|
||||
strength = max(strength, arguments[1])
|
||||
|
||||
/datum/component/radioactive/proc/rad_examine(mob/user, atom/thing)
|
||||
var/atom/master = parent
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/datum/component/thermite
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
||||
var/amount
|
||||
var/overlay
|
||||
|
||||
@@ -46,10 +46,13 @@
|
||||
master.cut_overlay(overlay)
|
||||
return ..()
|
||||
|
||||
/datum/component/thermite/InheritComponent(datum/component/thermite/newC, i_am_original)
|
||||
/datum/component/thermite/InheritComponent(datum/component/thermite/newC, i_am_original, list/arguments)
|
||||
if(!i_am_original)
|
||||
return
|
||||
amount += newC.amount
|
||||
if(newC)
|
||||
amount += newC.amount
|
||||
else
|
||||
amount += arguments[1]
|
||||
|
||||
/datum/component/thermite/proc/thermite_melt(mob/user)
|
||||
var/turf/master = parent
|
||||
|
||||
Reference in New Issue
Block a user