mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-23 03:57:48 +01:00
Swarm Component + Pixel shift attack animation (#17179)
* Swarm!! * carp dmi * swarm * Proper swarming * Swarmers * Update --------- Co-authored-by: Selis <12716288+ItsSelis@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
/// 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 separate listener however
|
||||
/// This has great use, primarily for components, but it carries with it some overhead
|
||||
/// So we do it separately 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/RegisterWithParent()
|
||||
RegisterSignal(tracked, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved))
|
||||
RegisterSignal(tracked, COMSIG_PARENT_QDELETING, PROC_REF(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 // COMSIG_PARENT_QDELETING
|
||||
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
|
||||
|
||||
parent.UnregisterSignal(tracked_loc, connections)
|
||||
|
||||
tracked_loc = null
|
||||
|
||||
/datum/component/connect_loc_behalf/proc/on_moved(sigtype, atom/movable/tracked, atom/old_loc)
|
||||
SIGNAL_HANDLER // COMSIG_MOVABLE_MOVED
|
||||
update_signals()
|
||||
@@ -0,0 +1,59 @@
|
||||
/datum/component/swarming
|
||||
var/offset_x = 0
|
||||
var/offset_y = 0
|
||||
var/is_swarming = FALSE
|
||||
var/list/swarm_members = list()
|
||||
var/static/list/swarming_loc_connections = list(
|
||||
COMSIG_ATOM_EXITED = PROC_REF(leave_swarm),
|
||||
COMSIG_ATOM_ENTERED = PROC_REF(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)
|
||||
|
||||
AddComponent(/datum/component/connect_loc_behalf, parent, swarming_loc_connections)
|
||||
|
||||
/datum/component/swarming/Destroy()
|
||||
for(var/other in swarm_members)
|
||||
var/datum/component/swarming/other_swarm = other
|
||||
other_swarm.swarm_members -= src
|
||||
if(!length(other_swarm.swarm_members))
|
||||
other_swarm.unswarm()
|
||||
swarm_members = null
|
||||
return ..()
|
||||
|
||||
/datum/component/swarming/proc/join_swarm(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
||||
var/datum/component/swarming/other_swarm = arrived.GetComponent(/datum/component/swarming)
|
||||
if(!other_swarm)
|
||||
return
|
||||
swarm()
|
||||
swarm_members |= other_swarm
|
||||
other_swarm.swarm()
|
||||
other_swarm.swarm_members |= src
|
||||
|
||||
/datum/component/swarming/proc/leave_swarm(datum/source, atom/movable/gone, direction)
|
||||
var/datum/component/swarming/other_swarm = gone.GetComponent(/datum/component/swarming)
|
||||
if(!other_swarm || !(other_swarm in swarm_members))
|
||||
return
|
||||
swarm_members -= other_swarm
|
||||
if(!length(swarm_members))
|
||||
unswarm()
|
||||
other_swarm.swarm_members -= src
|
||||
if(!length(other_swarm.swarm_members))
|
||||
other_swarm.unswarm()
|
||||
|
||||
/datum/component/swarming/proc/swarm()
|
||||
var/atom/movable/owner = parent
|
||||
if(!is_swarming)
|
||||
is_swarming = TRUE
|
||||
animate(owner, pixel_x = owner.pixel_x + offset_x, pixel_y = owner.pixel_y + offset_y, time = 2)
|
||||
|
||||
/datum/component/swarming/proc/unswarm()
|
||||
var/atom/movable/owner = parent
|
||||
if(is_swarming)
|
||||
animate(owner, pixel_x = owner.pixel_x - offset_x, pixel_y = owner.pixel_y - offset_y, time = 2)
|
||||
is_swarming = FALSE
|
||||
Reference in New Issue
Block a user