mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-30 16:47:13 +01:00
[MIRROR] Refactors connect_loc_behalf into a component (#7613)
* Refactors connect_loc_behalf into a component (#60678) See title. Also refactors caltrops into a component because they use connect_loc_behalf which requires them to hold the state. This also fixes COMPONENT_DUPE_SELECTIVE from just outright not working. connect_loc_behalf doesn't make sense as an element because it tries to hold states. There is also no way to maintain current behaviour and not have the states that it needs. Due to the fact that it tries to hold states, it means the code itself is a lot more buggy because it's a lot harder to successfully manage these states without runtimes or bugs. On metastation, there is only 2519 connect_loc_behalf components at roundstart. MrStonedOne has told me that datums take up this much space: image If we do the (oversimplified) math, there are only ever 5 variables that'll likely be changed on most connect_loc_behalf components at runtime: connections, tracked, signal_atom, parent, signal_procs This means that on metastation at roundstart, we take up this amount: (24 + 16 * 5) * 2519 = 261.97600 kilobytes This is not really significant and the benefits of moving this to a component greatly outweighs the memory cost. (Basically the memory cost is outweighed by the maint cost of tracking down issues with the thing. It's too buggy to be viable longterm basically) * Update glass.dm Co-authored-by: Watermelon914 <37270891+Watermelon914@users.noreply.github.com> Co-authored-by: Gandalf <jzo123@hotmail.com>
This commit is contained in:
co-authored by
Watermelon914
Gandalf
parent
044cde205f
commit
169c42a262
@@ -54,25 +54,25 @@ have ways of interacting with a specific mob and control it.
|
||||
RegisterSignal(new_pawn, COMSIG_MOB_MOVESPEED_UPDATED, .proc/update_movespeed)
|
||||
RegisterSignal(new_pawn, COMSIG_FOOD_EATEN, .proc/on_eat)
|
||||
|
||||
AddElement(/datum/element/connect_loc_behalf, new_pawn, loc_connections)
|
||||
AddComponent(/datum/component/connect_loc_behalf, new_pawn, loc_connections)
|
||||
movement_delay = living_pawn.cached_multiplicative_slowdown
|
||||
return ..() //Run parent at end
|
||||
|
||||
/datum/ai_controller/monkey/UnpossessPawn(destroy)
|
||||
UnregisterSignal(pawn, list(COMSIG_PARENT_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_ATTACK_PAW, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_HITBY, COMSIG_LIVING_START_PULL,\
|
||||
COMSIG_LIVING_TRY_SYRINGE, COMSIG_ATOM_HULK_ATTACK, COMSIG_CARBON_CUFF_ATTEMPTED, COMSIG_MOB_MOVESPEED_UPDATED, COMSIG_ATOM_ATTACK_ANIMAL, COMSIG_MOB_ATTACK_ALIEN))
|
||||
RemoveElement(/datum/element/connect_loc_behalf, pawn, loc_connections)
|
||||
qdel(GetComponent(/datum/component/connect_loc_behalf))
|
||||
|
||||
return ..() //Run parent at end
|
||||
|
||||
// Stops sentient monkeys from being knocked over like weak dunces.
|
||||
/datum/ai_controller/monkey/on_sentience_gained()
|
||||
. = ..()
|
||||
RemoveElement(/datum/element/connect_loc_behalf, pawn, loc_connections)
|
||||
qdel(GetComponent(/datum/component/connect_loc_behalf))
|
||||
|
||||
/datum/ai_controller/monkey/on_sentience_lost()
|
||||
. = ..()
|
||||
AddElement(/datum/element/connect_loc_behalf, pawn, loc_connections)
|
||||
AddComponent(/datum/component/connect_loc_behalf, pawn, loc_connections)
|
||||
|
||||
/datum/ai_controller/monkey/able_to_run()
|
||||
. = ..()
|
||||
|
||||
@@ -417,7 +417,7 @@
|
||||
|
||||
raw_args[1] = src
|
||||
|
||||
if(dm != COMPONENT_DUPE_ALLOWED)
|
||||
if(dm != COMPONENT_DUPE_ALLOWED && dm != COMPONENT_DUPE_SELECTIVE)
|
||||
if(!dt)
|
||||
old_comp = GetExactComponent(nt)
|
||||
else
|
||||
@@ -443,19 +443,19 @@
|
||||
old_comp.InheritComponent(arglist(arguments))
|
||||
else
|
||||
old_comp.InheritComponent(new_comp, TRUE)
|
||||
if(COMPONENT_DUPE_SELECTIVE)
|
||||
var/list/arguments = raw_args.Copy()
|
||||
arguments[1] = new_comp
|
||||
var/make_new_component = TRUE
|
||||
for(var/datum/component/existing_component as anything in GetComponents(new_type))
|
||||
if(existing_component.CheckDupeComponent(arglist(arguments)))
|
||||
make_new_component = FALSE
|
||||
QDEL_NULL(new_comp)
|
||||
break
|
||||
if(!new_comp && make_new_component)
|
||||
new_comp = new nt(raw_args)
|
||||
else if(!new_comp)
|
||||
new_comp = new nt(raw_args) // There's a valid dupe mode but there's no old component, act like normal
|
||||
else if(dm == COMPONENT_DUPE_SELECTIVE)
|
||||
var/list/arguments = raw_args.Copy()
|
||||
arguments[1] = new_comp
|
||||
var/make_new_component = TRUE
|
||||
for(var/datum/component/existing_component as anything in GetComponents(new_type))
|
||||
if(existing_component.CheckDupeComponent(arglist(arguments)))
|
||||
make_new_component = FALSE
|
||||
QDEL_NULL(new_comp)
|
||||
break
|
||||
if(!new_comp && make_new_component)
|
||||
new_comp = new nt(raw_args)
|
||||
else if(!new_comp)
|
||||
new_comp = new nt(raw_args) // Dupes are allowed, act like normal
|
||||
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
///Special snowflake component only used for the recycler.
|
||||
/datum/component/butchering/recycler
|
||||
|
||||
|
||||
/datum/component/butchering/recycler/Initialize(_speed, _effectiveness, _bonus_modifier, _butcher_sound, disabled, _can_be_blunt)
|
||||
if(!istype(parent, /obj/machinery/recycler)) //EWWW
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
@@ -147,7 +148,7 @@
|
||||
var/static/list/loc_connections = list(
|
||||
COMSIG_ATOM_ENTERED = .proc/on_entered,
|
||||
)
|
||||
AddElement(/datum/element/connect_loc_behalf, parent, loc_connections)
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections)
|
||||
|
||||
/datum/component/butchering/recycler/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -3,10 +3,7 @@
|
||||
*
|
||||
* Used for broken glass, cactuses and four sided dice.
|
||||
*/
|
||||
/datum/element/caltrop
|
||||
element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH
|
||||
id_arg_index = 2
|
||||
|
||||
/datum/component/caltrop
|
||||
///Minimum damage done when crossed
|
||||
var/min_damage
|
||||
|
||||
@@ -27,10 +24,11 @@
|
||||
COMSIG_ATOM_ENTERED = .proc/on_entered,
|
||||
)
|
||||
|
||||
/datum/element/caltrop/Attach(datum/target, min_damage = 0, max_damage = 0, probability = 100, flags = NONE, soundfile = null)
|
||||
|
||||
/datum/component/caltrop/Initialize(min_damage = 0, max_damage = 0, probability = 100, flags = NONE, soundfile = null)
|
||||
. = ..()
|
||||
if(!isatom(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
if(!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
src.min_damage = min_damage
|
||||
src.max_damage = max(min_damage, max_damage)
|
||||
@@ -38,12 +36,12 @@
|
||||
src.flags = flags
|
||||
src.soundfile = soundfile
|
||||
|
||||
if(ismovable(target))
|
||||
AddElement(/datum/element/connect_loc_behalf, target, crossed_connections)
|
||||
if(ismovable(parent))
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, crossed_connections)
|
||||
else
|
||||
RegisterSignal(get_turf(target), COMSIG_ATOM_ENTERED, .proc/on_entered)
|
||||
RegisterSignal(get_turf(parent), COMSIG_ATOM_ENTERED, .proc/on_entered)
|
||||
|
||||
/datum/element/caltrop/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
||||
/datum/component/caltrop/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!prob(probability))
|
||||
@@ -106,7 +104,6 @@
|
||||
return
|
||||
playsound(H, soundfile, 15, TRUE, -3)
|
||||
|
||||
/datum/element/caltrop/Detach(datum/target)
|
||||
. = ..()
|
||||
if(ismovable(target))
|
||||
RemoveElement(/datum/element/connect_loc_behalf, target, crossed_connections)
|
||||
/datum/component/caltrop/UnregisterFromParent()
|
||||
if(ismovable(parent))
|
||||
qdel(GetComponent(/datum/component/connect_loc_behalf))
|
||||
@@ -0,0 +1,81 @@
|
||||
/// This component behaves similar to connect_loc, hooking into a signal on a tracked object's turf
|
||||
/// It has the ability to react to that signal on behalf of a seperate listener however
|
||||
/// This has great use, primarially for components, but it carries with it some overhead
|
||||
/// So we do it seperately as it needs to hold state which is very likely to lead to bugs if it remains as an element.
|
||||
/datum/component/connect_loc_behalf
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE
|
||||
|
||||
/// An assoc list of signal -> procpath to register to the loc this object is on.
|
||||
var/list/connections
|
||||
|
||||
var/atom/movable/tracked
|
||||
|
||||
var/atom/tracked_loc
|
||||
|
||||
/datum/component/connect_loc_behalf/Initialize(atom/movable/tracked, list/connections)
|
||||
. = ..()
|
||||
if (!istype(tracked))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
src.connections = connections
|
||||
src.tracked = tracked
|
||||
|
||||
/datum/component/connect_loc_behalf/CheckDupeComponent(datum/component/component, atom/movable/tracked, list/connections)
|
||||
if(src.tracked != tracked)
|
||||
return FALSE
|
||||
|
||||
// Not equivalent. Checks if they are not the same list via shallow comparison.
|
||||
if(!compare_list(src.connections, connections))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/component/connect_loc_behalf/RegisterWithParent()
|
||||
RegisterSignal(tracked, COMSIG_MOVABLE_MOVED, .proc/on_moved)
|
||||
RegisterSignal(tracked, COMSIG_PARENT_QDELETING, .proc/handle_tracked_qdel)
|
||||
update_signals()
|
||||
|
||||
/datum/component/connect_loc_behalf/UnregisterFromParent()
|
||||
unregister_signals()
|
||||
UnregisterSignal(tracked, list(
|
||||
COMSIG_MOVABLE_MOVED,
|
||||
COMSIG_PARENT_QDELETING,
|
||||
))
|
||||
|
||||
tracked = null
|
||||
|
||||
/datum/component/connect_loc_behalf/proc/handle_tracked_qdel()
|
||||
SIGNAL_HANDLER
|
||||
qdel(src)
|
||||
|
||||
/datum/component/connect_loc_behalf/proc/update_signals()
|
||||
unregister_signals()
|
||||
//You may ask yourself, isn't this just silencing an error?
|
||||
//The answer is yes, but there's no good cheap way to fix it
|
||||
//What happens is the tracked object or hell the listener gets say, deleted, which makes targets[old_loc] return a null
|
||||
//The null results in a bad index, because of course it does
|
||||
//It's not a solvable problem though, since both actions, the destroy and the move, are sourced from the same signal send
|
||||
//And sending a signal should be agnostic of the order of listeners
|
||||
//So we need to either pick the order agnositic, or destroy safe
|
||||
//And I picked destroy safe. Let's hope this is the right path!
|
||||
if(isnull(tracked.loc))
|
||||
return
|
||||
|
||||
tracked_loc = tracked.loc
|
||||
|
||||
for (var/signal in connections)
|
||||
parent.RegisterSignal(tracked_loc, signal, connections[signal])
|
||||
|
||||
/datum/component/connect_loc_behalf/proc/unregister_signals()
|
||||
if(isnull(tracked_loc))
|
||||
return
|
||||
|
||||
for (var/signal in connections)
|
||||
parent.UnregisterSignal(tracked_loc, signal)
|
||||
|
||||
tracked_loc = null
|
||||
|
||||
/datum/component/connect_loc_behalf/proc/on_moved(sigtype, atom/movable/tracked, atom/old_loc)
|
||||
SIGNAL_HANDLER
|
||||
update_signals()
|
||||
|
||||
@@ -45,6 +45,7 @@ Behavior that's still missing from this component that original food items had t
|
||||
///The type of atom this creates when the object is microwaved.
|
||||
var/atom/microwaved_type
|
||||
|
||||
|
||||
/datum/component/edible/Initialize(
|
||||
list/initial_reagents,
|
||||
food_flags = NONE,
|
||||
@@ -73,7 +74,7 @@ Behavior that's still missing from this component that original food items had t
|
||||
var/static/list/loc_connections = list(
|
||||
COMSIG_ATOM_ENTERED = .proc/on_entered,
|
||||
)
|
||||
AddElement(/datum/element/connect_loc_behalf, parent, loc_connections)
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections)
|
||||
|
||||
if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/UseFromHand)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
var/expire_time
|
||||
var/required_clean_types = CLEAN_TYPE_DISEASE
|
||||
|
||||
|
||||
/datum/component/infective/Initialize(list/datum/disease/_diseases, expire_in)
|
||||
if(islist(_diseases))
|
||||
diseases = _diseases
|
||||
@@ -18,7 +19,7 @@
|
||||
var/static/list/disease_connections = list(
|
||||
COMSIG_ATOM_ENTERED = .proc/try_infect_crossed,
|
||||
)
|
||||
AddElement(/datum/element/connect_loc_behalf, parent, disease_connections)
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, disease_connections)
|
||||
|
||||
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, .proc/try_infect_buckle)
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
/// for if we're an ammo casing being fired
|
||||
var/mob/living/shooter
|
||||
|
||||
|
||||
/datum/component/pellet_cloud/Initialize(projectile_type=/obj/item/shrapnel, magnitude=5)
|
||||
if(!isammocasing(parent) && !isgrenade(parent) && !islandmine(parent) && !issupplypod(parent) && !ishorrorling(parent)) //SKYRAT EDIT CHANGE: if(!isammocasing(parent) && !isgrenade(parent) && !islandmine(parent) && !issupplypod(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
@@ -339,7 +340,7 @@
|
||||
var/static/list/loc_connections = list(
|
||||
COMSIG_ATOM_EXITED =.proc/grenade_uncrossed,
|
||||
)
|
||||
AddElement(/datum/element/connect_loc_behalf, parent, loc_connections)
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections)
|
||||
|
||||
/// Someone dropped the grenade, so set them to the shooter in case they're on top of it when it goes off
|
||||
/datum/component/pellet_cloud/proc/grenade_dropped(obj/item/nade, mob/living/slick_willy)
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
COMSIG_ATOM_ENTERED = .proc/on_entered,
|
||||
)
|
||||
|
||||
|
||||
|
||||
/datum/component/rot/Initialize(delay, scaling, severity)
|
||||
if(!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
@@ -37,7 +39,7 @@
|
||||
RegisterSignal(parent, list(COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_ANIMAL, COMSIG_ATOM_ATTACK_HAND), .proc/rot_react_touch)
|
||||
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/rot_hit_react)
|
||||
if(ismovable(parent))
|
||||
AddElement(/datum/element/connect_loc_behalf, parent, loc_connections)
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_BUMP, .proc/rot_react)
|
||||
if(isliving(parent))
|
||||
RegisterSignal(parent, COMSIG_LIVING_REVIVE, .proc/react_to_revive) //mobs stop this when they come to life
|
||||
@@ -60,7 +62,7 @@
|
||||
/datum/component/rot/UnregisterFromParent()
|
||||
. = ..()
|
||||
if(ismovable(parent))
|
||||
RemoveElement(/datum/element/connect_loc_behalf, parent, loc_connections)
|
||||
qdel(GetComponent(/datum/component/connect_loc_behalf))
|
||||
|
||||
///One of two procs that modifies blockers, this one handles removing a blocker and potentially restarting the rot
|
||||
/datum/component/rot/proc/start_up(blocker_type)
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
/// If specified, the singularity will slowly move to this target
|
||||
var/atom/target
|
||||
|
||||
|
||||
|
||||
/datum/component/singularity/Initialize(
|
||||
bsa_targetable = TRUE,
|
||||
consume_range = 0,
|
||||
@@ -85,7 +87,7 @@
|
||||
var/static/list/loc_connections = list(
|
||||
COMSIG_ATOM_ENTERED = .proc/on_entered,
|
||||
)
|
||||
AddElement(/datum/element/connect_loc_behalf, parent, loc_connections)
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections)
|
||||
|
||||
RegisterSignal(parent, COMSIG_ATOM_BULLET_ACT, .proc/consume_bullets)
|
||||
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
COMSIG_ATOM_ENTERED = .proc/Slip_on_wearer,
|
||||
)
|
||||
|
||||
/// The connect_loc_behalf component for the holder_connections list.
|
||||
var/datum/weakref/holder_connect_loc_behalf
|
||||
|
||||
/datum/component/slippery/Initialize(knockdown, lube_flags = NONE, datum/callback/callback, paralyze, force_drop = FALSE, slot_whitelist)
|
||||
src.knockdown_time = max(knockdown, 0)
|
||||
src.paralyze_time = max(paralyze, 0)
|
||||
@@ -33,15 +36,19 @@
|
||||
src.callback = callback
|
||||
if(slot_whitelist)
|
||||
src.slot_whitelist = slot_whitelist
|
||||
if(ismovable(parent))
|
||||
AddElement(/datum/element/connect_loc_behalf, parent, default_connections)
|
||||
|
||||
if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
|
||||
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
|
||||
add_connect_loc_behalf_to_parent()
|
||||
if(ismovable(parent))
|
||||
if(isitem(parent))
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
|
||||
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
|
||||
else
|
||||
RegisterSignal(parent, COMSIG_ATOM_ENTERED, .proc/Slip)
|
||||
|
||||
/datum/component/slippery/proc/add_connect_loc_behalf_to_parent()
|
||||
if(ismovable(parent))
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, default_connections)
|
||||
|
||||
/datum/component/slippery/InheritComponent(datum/component/slippery/component, i_am_original, knockdown, lube_flags = NONE, datum/callback/callback, paralyze, force_drop = FALSE, slot_whitelist)
|
||||
if(component)
|
||||
knockdown = component.knockdown_time
|
||||
@@ -86,7 +93,8 @@
|
||||
|
||||
if((!LAZYLEN(slot_whitelist) || (slot in slot_whitelist)) && isliving(equipper))
|
||||
holder = equipper
|
||||
AddElement(/datum/element/connect_loc_behalf, holder, holder_connections)
|
||||
qdel(GetComponent(/datum/component/connect_loc_behalf))
|
||||
AddComponent(/datum/component/connect_loc_behalf, holder, holder_connections)
|
||||
RegisterSignal(holder, COMSIG_PARENT_PREQDELETED, .proc/holder_deleted)
|
||||
|
||||
/*
|
||||
@@ -113,9 +121,11 @@
|
||||
SIGNAL_HANDLER
|
||||
|
||||
UnregisterSignal(user, COMSIG_PARENT_PREQDELETED)
|
||||
if(holder)
|
||||
RemoveElement(/datum/element/connect_loc_behalf, holder, holder_connections)
|
||||
holder = null
|
||||
|
||||
qdel(GetComponent(/datum/component/connect_loc_behalf))
|
||||
add_connect_loc_behalf_to_parent()
|
||||
|
||||
holder = null
|
||||
|
||||
/*
|
||||
* The slip proc, but for equipped items.
|
||||
@@ -132,9 +142,7 @@
|
||||
|
||||
/datum/component/slippery/UnregisterFromParent()
|
||||
. = ..()
|
||||
if(holder)
|
||||
RemoveElement(/datum/element/connect_loc_behalf, holder, holder_connections)
|
||||
RemoveElement(/datum/element/connect_loc_behalf, parent, default_connections)
|
||||
qdel(GetComponent(/datum/component/connect_loc_behalf))
|
||||
|
||||
/// Used for making the clown PDA only slip if the clown is wearing his shoes and the elusive banana-skin belt
|
||||
/datum/component/slippery/clowning
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
if(!src.on_squash_callback && squash_callback)
|
||||
on_squash_callback = CALLBACK(parent, squash_callback)
|
||||
|
||||
AddElement(/datum/element/connect_loc_behalf, parent, loc_connections)
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections)
|
||||
|
||||
///Handles the squashing of the mob
|
||||
/datum/component/squashable/proc/on_entered(turf/source_turf, atom/movable/crossing_movable)
|
||||
@@ -72,4 +72,4 @@
|
||||
|
||||
/datum/component/squashable/UnregisterFromParent()
|
||||
. = ..()
|
||||
RemoveElement(/datum/element/connect_loc_behalf, parent, loc_connections)
|
||||
qdel(GetComponent(/datum/component/connect_loc_behalf))
|
||||
@@ -26,6 +26,7 @@
|
||||
COMSIG_ATOM_ENTERED = .proc/play_squeak_crossed,
|
||||
)
|
||||
|
||||
|
||||
/datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override, extrarange, falloff_exponent, fallof_distance)
|
||||
if(!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
@@ -33,7 +34,7 @@
|
||||
if(ismovable(parent))
|
||||
RegisterSignal(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT, COMSIG_PROJECTILE_BEFORE_FIRE), .proc/play_squeak)
|
||||
|
||||
AddElement(/datum/element/connect_loc_behalf, parent, item_connections)
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, item_connections)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react)
|
||||
if(isitem(parent))
|
||||
RegisterSignal(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_HIT_REACT), .proc/play_squeak)
|
||||
@@ -67,7 +68,7 @@
|
||||
|
||||
/datum/component/squeak/UnregisterFromParent()
|
||||
. = ..()
|
||||
RemoveElement(/datum/element/connect_loc_behalf, parent, item_connections)
|
||||
qdel(GetComponent(/datum/component/connect_loc_behalf))
|
||||
|
||||
/datum/component/squeak/proc/play_squeak()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
COMSIG_ATOM_ENTERED = .proc/join_swarm
|
||||
)
|
||||
|
||||
|
||||
/datum/component/swarming/Initialize(max_x = 24, max_y = 24)
|
||||
if(!ismovable(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
offset_x = rand(-max_x, max_x)
|
||||
offset_y = rand(-max_y, max_y)
|
||||
|
||||
AddElement(/datum/element/connect_loc_behalf, parent, swarming_loc_connections)
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, swarming_loc_connections)
|
||||
|
||||
/datum/component/swarming/Destroy()
|
||||
for(var/other in swarm_members)
|
||||
|
||||
@@ -42,94 +42,3 @@
|
||||
SIGNAL_HANDLER
|
||||
unregister_signals(listener, old_loc)
|
||||
update_signals(listener)
|
||||
|
||||
/// This element behaves the same as connect_loc, hooking into a signal on a tracked object's turf
|
||||
/// It has the ability to react to that signal on behalf of a seperate listener however
|
||||
/// This has great use, primarially for components, but it carries with it some overhead
|
||||
/// So we do it seperately rather then intigrating the behavior with the main element
|
||||
/datum/element/connect_loc_behalf
|
||||
element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH | ELEMENT_COMPLEX_DETACH
|
||||
id_arg_index = 3
|
||||
|
||||
/// An assoc list of signal -> procpath to register to the loc this object is on.
|
||||
var/list/connections
|
||||
|
||||
/// An assoc list of locs that are being occupied and a list of targets that occupy them.
|
||||
var/list/targets = list()
|
||||
|
||||
/datum/element/connect_loc_behalf/Attach(datum/listener, atom/movable/tracked, list/connections)
|
||||
. = ..()
|
||||
if (!istype(tracked))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
src.connections = connections
|
||||
|
||||
RegisterSignal(tracked, COMSIG_MOVABLE_MOVED, .proc/on_moved, override = TRUE)
|
||||
update_signals(listener, tracked)
|
||||
|
||||
/datum/element/connect_loc_behalf/Detach(datum/listener, atom/movable/tracked, list/connections)
|
||||
. = ..()
|
||||
|
||||
if(!tracked)
|
||||
unregister_all(listener)
|
||||
else if(targets[tracked.loc]) // Detach can happen multiple times due to qdel
|
||||
unregister_signals(listener, tracked, tracked.loc)
|
||||
UnregisterSignal(tracked, COMSIG_MOVABLE_MOVED)
|
||||
|
||||
/datum/element/connect_loc_behalf/proc/update_signals(datum/listener, atom/movable/tracked)
|
||||
var/existing = length(targets[tracked.loc])
|
||||
if(!existing)
|
||||
targets[tracked.loc] = list()
|
||||
targets[tracked.loc][tracked] = listener
|
||||
|
||||
if(isnull(tracked.loc))
|
||||
return
|
||||
|
||||
for (var/signal in connections)
|
||||
listener.RegisterSignal(tracked.loc, signal, connections[signal], override=TRUE)
|
||||
//override=TRUE because more than one connect_loc element instance tracked object can be on the same loc
|
||||
|
||||
/datum/element/connect_loc_behalf/proc/unregister_all(datum/listener)
|
||||
for(var/atom/location as anything in targets)
|
||||
var/list/loc_targets = targets[location]
|
||||
for(var/atom/movable/tracked as anything in loc_targets)
|
||||
if(tracked == listener)
|
||||
unregister_signals(loc_targets[tracked], tracked, location)
|
||||
else if(loc_targets[tracked] == listener)
|
||||
unregister_signals(listener, tracked, location)
|
||||
else
|
||||
continue
|
||||
UnregisterSignal(tracked, COMSIG_MOVABLE_MOVED)
|
||||
|
||||
/datum/element/connect_loc_behalf/proc/unregister_signals(datum/listener, atom/movable/tracked, atom/old_loc)
|
||||
if (length(targets[old_loc]) <= 1)
|
||||
targets -= old_loc
|
||||
else
|
||||
targets[old_loc] -= tracked
|
||||
|
||||
// Yes this is after the above because we use null as a key when objects are in nullspace
|
||||
if(isnull(old_loc))
|
||||
return
|
||||
|
||||
for (var/signal in connections)
|
||||
listener.UnregisterSignal(old_loc, signal)
|
||||
|
||||
/datum/element/connect_loc_behalf/proc/on_moved(atom/movable/tracked, atom/old_loc)
|
||||
SIGNAL_HANDLER
|
||||
var/list/objects_in_old_loc = targets[old_loc]
|
||||
//You may ask yourself, isn't this just silencing an error?
|
||||
//The answer is yes, but there's no good cheap way to fix it
|
||||
//What happens is the tracked object or hell the listener gets say, deleted, which makes targets[old_loc] return a null
|
||||
//The null results in a bad index, because of course it does
|
||||
//It's not a solvable problem though, since both actions, the destroy and the move, are sourced from the same signal send
|
||||
//And sending a signal should be agnostic of the order of listeners
|
||||
//So we need to either pick the order agnositic, or destroy safe
|
||||
//And I picked destroy safe. Let's hope this is the right path!
|
||||
if(!objects_in_old_loc)
|
||||
return
|
||||
var/datum/listener = objects_in_old_loc[tracked]
|
||||
if(!listener) //See above
|
||||
return
|
||||
unregister_signals(listener, tracked, old_loc)
|
||||
update_signals(listener, tracked)
|
||||
|
||||
|
||||
@@ -273,4 +273,4 @@
|
||||
reagents.add_reagent(/datum/reagent/ants, rand(2, 5))
|
||||
pixel_x = rand(-5, 5)
|
||||
pixel_y = rand(-5, 5)
|
||||
AddElement(/datum/element/caltrop, min_damage = 0.2, max_damage = 1, flags = (CALTROP_NOCRAWL | CALTROP_NOSTUN | CALTROP_BYPASS_SHOES), soundfile = 'sound/weapons/bite.ogg')
|
||||
AddComponent(/datum/component/caltrop, min_damage = 0.2, max_damage = 1, flags = (CALTROP_NOCRAWL | CALTROP_NOSTUN | CALTROP_BYPASS_SHOES), soundfile = 'sound/weapons/bite.ogg')
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
/obj/item/dice/d4/Initialize(mapload)
|
||||
. = ..()
|
||||
// 1d4 damage
|
||||
AddElement(/datum/element/caltrop, min_damage = 1, max_damage = 4)
|
||||
AddComponent(/datum/component/caltrop, min_damage = 1, max_damage = 4)
|
||||
|
||||
/obj/item/dice/d6
|
||||
name = "d6"
|
||||
|
||||
@@ -275,7 +275,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
|
||||
|
||||
/obj/item/shard/Initialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/caltrop, min_damage = force)
|
||||
AddComponent(/datum/component/caltrop, min_damage = force)
|
||||
AddComponent(/datum/component/butchering, 150, 65)
|
||||
icon_state = pick("large", "medium", "small")
|
||||
switch(icon_state)
|
||||
|
||||
@@ -47,11 +47,11 @@
|
||||
|
||||
/obj/item/assembly/mousetrap/on_attach()
|
||||
. = ..()
|
||||
AddElement(/datum/element/connect_loc_behalf, holder, holder_connections)
|
||||
AddComponent(/datum/component/connect_loc_behalf, holder, holder_connections)
|
||||
|
||||
/obj/item/assembly/mousetrap/on_detach()
|
||||
. = ..()
|
||||
RemoveElement(/datum/element/connect_loc_behalf, holder, holder_connections)
|
||||
qdel(GetComponent(/datum/component/connect_loc_behalf))
|
||||
|
||||
/obj/item/assembly/mousetrap/proc/triggered(mob/target, type = "feet")
|
||||
if(!armed)
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
|
||||
/obj/structure/punji_sticks/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/caltrop, min_damage = 20, max_damage = 30, flags = CALTROP_BYPASS_SHOES)
|
||||
AddComponent(/datum/component/caltrop, min_damage = 20, max_damage = 30, flags = CALTROP_BYPASS_SHOES)
|
||||
|
||||
/obj/structure/punji_sticks/spikes
|
||||
name = "wooden spikes"
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
|
||||
/obj/structure/flora/ash/cacti/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/caltrop, min_damage = 3, max_damage = 6, probability = 70)
|
||||
AddComponent(/datum/component/caltrop, min_damage = 3, max_damage = 6, probability = 70)
|
||||
|
||||
/obj/structure/flora/ash/seraka
|
||||
icon_state = "seraka_mushroom"
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/cockroach/hauberoach/Initialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/caltrop, min_damage = 10, max_damage = 15, flags = (CALTROP_BYPASS_SHOES | CALTROP_SILENT))
|
||||
AddComponent(/datum/component/caltrop, min_damage = 10, max_damage = 15, flags = (CALTROP_BYPASS_SHOES | CALTROP_SILENT))
|
||||
|
||||
/mob/living/simple_animal/hostile/cockroach/hauberoach/make_squashable()
|
||||
AddComponent(/datum/component/squashable, squash_chance = 100, squash_damage = 1, squash_callback = /mob/living/simple_animal/hostile/cockroach/hauberoach/.proc/on_squish)
|
||||
|
||||
@@ -959,7 +959,7 @@
|
||||
/obj/item/light/Initialize()
|
||||
. = ..()
|
||||
create_reagents(LIGHT_REAGENT_CAPACITY, INJECTABLE | DRAINABLE)
|
||||
AddElement(/datum/element/caltrop, min_damage = force)
|
||||
AddComponent(/datum/component/caltrop, min_damage = force)
|
||||
update()
|
||||
var/static/list/loc_connections = list(
|
||||
COMSIG_ATOM_ENTERED = .proc/on_entered,
|
||||
|
||||
@@ -258,7 +258,7 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
|
||||
|
||||
/obj/item/shard/Initialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/caltrop, min_damage = force)
|
||||
AddComponent(/datum/component/caltrop, min_damage = force)
|
||||
AddComponent(/datum/component/butchering, 150, 65)
|
||||
icon_state = pick("large", "medium", "small")
|
||||
switch(icon_state)
|
||||
|
||||
+3
-2
@@ -548,8 +548,10 @@
|
||||
#include "code\datums\components\beetlejuice.dm"
|
||||
#include "code\datums\components\bloodysoles.dm"
|
||||
#include "code\datums\components\butchering.dm"
|
||||
#include "code\datums\components\caltrop.dm"
|
||||
#include "code\datums\components\chasm.dm"
|
||||
#include "code\datums\components\codeword_hearing.dm"
|
||||
#include "code\datums\components\connect_loc_behalf.dm"
|
||||
#include "code\datums\components\construction.dm"
|
||||
#include "code\datums\components\cracked.dm"
|
||||
#include "code\datums\components\creamed.dm"
|
||||
@@ -617,6 +619,7 @@
|
||||
#include "code\datums\components\spill.dm"
|
||||
#include "code\datums\components\spinny.dm"
|
||||
#include "code\datums\components\spirit_holding.dm"
|
||||
#include "code\datums\components\squashable.dm"
|
||||
#include "code\datums\components\squeak.dm"
|
||||
#include "code\datums\components\stationloving.dm"
|
||||
#include "code\datums\components\stationstuck.dm"
|
||||
@@ -740,7 +743,6 @@
|
||||
#include "code\datums\elements\beauty.dm"
|
||||
#include "code\datums\elements\bed_tucking.dm"
|
||||
#include "code\datums\elements\bsa_blocker.dm"
|
||||
#include "code\datums\elements\caltrop.dm"
|
||||
#include "code\datums\elements\chewable.dm"
|
||||
#include "code\datums\elements\cleaning.dm"
|
||||
#include "code\datums\elements\climbable.dm"
|
||||
@@ -785,7 +787,6 @@
|
||||
#include "code\datums\elements\skittish.dm"
|
||||
#include "code\datums\elements\snail_crawl.dm"
|
||||
#include "code\datums\elements\spooky.dm"
|
||||
#include "code\datums\elements\squashable.dm"
|
||||
#include "code\datums\elements\squish.dm"
|
||||
#include "code\datums\elements\strippable.dm"
|
||||
#include "code\datums\elements\surgery_initiator.dm"
|
||||
|
||||
Reference in New Issue
Block a user