From 94ed7ed0f1ca77e1b0c368e7b62947dbf678ecbd Mon Sep 17 00:00:00 2001
From: SkyratBot <59378654+SkyratBot@users.noreply.github.com>
Date: Tue, 29 Dec 2020 03:39:03 +0100
Subject: [PATCH] [MIRROR] Refactors how movetypes are added and removed, No
timers this time. (#2358)
* Refactors how movetypes are added and removed, No timers this time. (#55444)
* Refactors how movetypes are added and removed, No timers this time.
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
---
code/__DEFINES/dcs/signals.dm | 8 ++
code/__DEFINES/traits.dm | 23 +++-
code/_globalvars/traits.dm | 28 +++++
code/datums/components/caltrop.dm | 2 +-
code/datums/components/chasm.dm | 4 +-
code/datums/components/slippery.dm | 2 +-
code/datums/elements/movetype_handler.dm | 109 ++++++++++++++++++
code/game/atoms_movable.dm | 34 ++----
code/game/objects/buckling.dm | 19 +++
.../game/objects/items/stacks/sheets/glass.dm | 2 +-
code/game/objects/items/tanks/jetpack.dm | 2 +-
code/game/objects/structures/life_candle.dm | 9 +-
code/modules/admin/verbs/randomverbs.dm | 2 +
code/modules/antagonists/blob/blob_mobs.dm | 2 +-
code/modules/antagonists/revenant/revenant.dm | 2 +-
code/modules/clothing/shoes/miscellaneous.dm | 1 -
.../carbon/alien/humanoid/caste/hunter.dm | 6 -
.../mob/living/carbon/carbon_defense.dm | 2 +-
.../mob/living/carbon/carbon_movement.dm | 20 ++--
.../mob/living/carbon/carbon_update_icons.dm | 4 +-
code/modules/mob/living/carbon/human/human.dm | 5 -
.../mob/living/carbon/human/species.dm | 12 +-
code/modules/mob/living/init_signals.dm | 12 ++
code/modules/mob/living/life.dm | 3 -
code/modules/mob/living/living.dm | 34 ++----
code/modules/mob/living/living_defense.dm | 1 -
.../mob/living/simple_animal/constructs.dm | 2 +-
.../simple_animal/friendly/butterfly.dm | 2 +-
.../living/simple_animal/guardian/guardian.dm | 2 +-
.../mob/living/simple_animal/hostile/bees.dm | 2 +-
.../mob/living/simple_animal/hostile/carp.dm | 2 +-
.../living/simple_animal/hostile/eyeballs.dm | 2 +-
.../simple_animal/hostile/jungle/leaper.dm | 6 +-
.../hostile/megafauna/colossus.dm | 14 +--
.../hostile/megafauna/demonic_frost_miner.dm | 2 +-
.../hostile/megafauna/megafauna.dm | 2 +-
.../hostile/mining_mobs/basilisk.dm | 2 +-
.../hostile/mining_mobs/curse_blob.dm | 2 +-
.../hostile/mining_mobs/elites/herald.dm | 2 +-
.../hostile/mining_mobs/hivelord.dm | 2 +-
.../hostile/mining_mobs/ice demon.dm | 2 +-
.../simple_animal/hostile/retaliate/bat.dm | 2 +-
.../simple_animal/hostile/retaliate/ghost.dm | 2 +-
.../living/simple_animal/hostile/syndicate.dm | 2 +-
.../mob/living/simple_animal/parrot.dm | 2 +-
.../modules/mob/living/simple_animal/shade.dm | 2 +-
.../mob/living/simple_animal/simple_animal.dm | 22 +++-
code/modules/mob/living/ventcrawling.dm | 5 +-
code/modules/mob/mob.dm | 8 --
code/modules/mob/mob_helpers.dm | 8 --
code/modules/power/lighting.dm | 2 +-
code/modules/surgery/organs/augments_chest.dm | 2 +-
tgstation.dme | 1 +
53 files changed, 302 insertions(+), 150 deletions(-)
create mode 100644 code/datums/elements/movetype_handler.dm
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 9784890bcd4..eab95d05eb3 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -887,6 +887,14 @@
///from base of datum/component/two_handed/proc/unwield(mob/living/carbon/user): (/mob/user)
#define COMSIG_TWOHANDED_UNWIELD "twohanded_unwield"
+// /datum/element/movetype_handler signals
+/// Called when the floating anim has to be temporarily stopped and restarted later: (timer)
+#define COMSIG_PAUSE_FLOATING_ANIM "pause_floating_anim"
+/// From base of datum/element/movetype_handler/on_movement_type_trait_gain: (flag)
+#define COMSIG_MOVETYPE_FLAG_ENABLED "movetype_flag_enabled"
+/// From base of datum/element/movetype_handler/on_movement_type_trait_loss: (flag)
+#define COMSIG_MOVETYPE_FLAG_DISABLED "movetype_flag_disabled"
+
// /datum/action signals
///from base of datum/action/proc/Trigger(): (datum/action)
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index d29991d8073..4655b4d36c9 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -9,14 +9,14 @@
target.status_traits = list(); \
_L = target.status_traits; \
_L[trait] = list(source); \
- SEND_SIGNAL(target, SIGNAL_ADDTRAIT(trait)); \
+ SEND_SIGNAL(target, SIGNAL_ADDTRAIT(trait), trait); \
} else { \
_L = target.status_traits; \
if (_L[trait]) { \
_L[trait] |= list(source); \
} else { \
_L[trait] = list(source); \
- SEND_SIGNAL(target, SIGNAL_ADDTRAIT(trait)); \
+ SEND_SIGNAL(target, SIGNAL_ADDTRAIT(trait), trait); \
} \
} \
} while (0)
@@ -37,7 +37,7 @@
};\
if (!length(_L[trait])) { \
_L -= trait; \
- SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(trait)); \
+ SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(trait), trait); \
}; \
if (!length(_L)) { \
target.status_traits = null \
@@ -53,7 +53,7 @@
_L[_T] &= _S;\
if (!length(_L[_T])) { \
_L -= _T; \
- SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(_T)); \
+ SEND_SIGNAL(target, SIGNAL_REMOVETRAIT(_T), _T); \
}; \
};\
if (!length(_L)) { \
@@ -228,6 +228,15 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_KNOW_CYBORG_WIRES "know_cyborg_wires"
#define TRAIT_KNOW_ENGI_WIRES "know_engi_wires"
+///Movement type traits for movables. See elements/movetype_handler.dm
+#define TRAIT_MOVE_GROUND "move_ground"
+#define TRAIT_MOVE_FLYING "move_flying"
+#define TRAIT_MOVE_VENTCRAWLING "move_ventcrawling"
+#define TRAIT_MOVE_FLOATING "move_floating"
+#define TRAIT_MOVE_PHASING "move_phasing"
+/// Disables the floating animation. See above.
+#define TRAIT_NO_FLOATING_ANIM "no-floating-animation"
+
//non-mob traits
/// Used for limb-based paralysis, where replacing the limb will fix it.
#define TRAIT_PARALYSIS "paralysis"
@@ -369,6 +378,12 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define SLEEPING_CARP_TRAIT "sleeping_carp"
#define MADE_UNCLONEABLE "made-uncloneable"
#define TIMESTOP_TRAIT "timestop"
+#define LIFECANDLE_TRAIT "lifecandle"
+#define VENTCRAWLING_TRAIT "ventcrawling"
+#define SPECIES_FLIGHT_TRAIT "species-flight"
+#define FROSTMINER_ENRAGE_TRAIT "frostminer-enrage"
+#define NO_GRAVITY_TRAIT "no-gravity"
+#define LEAPER_BUBBLE_TRAIT "leaper-bubble"
#define STICKY_NODROP "sticky-nodrop" //sticky nodrop sounds like a bad soundcloud rapper's name
#define SKILLCHIP_TRAIT "skillchip"
#define PULLED_WHILE_SOFTCRIT_TRAIT "pulled-while-softcrit"
diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm
index e9747f2d153..a78d8f99319 100644
--- a/code/_globalvars/traits.dm
+++ b/code/_globalvars/traits.dm
@@ -167,6 +167,13 @@ GLOBAL_LIST_INIT(traits_by_type, list(
),
/atom = list(
"TRAIT_KEEP_TOGETHER" = TRAIT_KEEP_TOGETHER
+ ),
+ /atom/movable = list(
+ "TRAIT_MOVE_GROUND" = TRAIT_MOVE_GROUND,
+ "TRAIT_MOVE_FLYING" = TRAIT_MOVE_FLYING,
+ "TRAIT_MOVE_VENTCRAWLING" = TRAIT_MOVE_VENTCRAWLING,
+ "TRAIT_MOVE_FLOATING" = TRAIT_MOVE_FLOATING,
+ "TRAIT_MOVE_PHASING" = TRAIT_MOVE_PHASING
)
))
@@ -179,3 +186,24 @@ GLOBAL_LIST(trait_name_map)
for(var/tname in GLOB.traits_by_type[key])
var/val = GLOB.traits_by_type[key][tname]
.[val] = tname
+
+GLOBAL_LIST_INIT(movement_type_trait_to_flag, list(
+ TRAIT_MOVE_GROUND = GROUND,
+ TRAIT_MOVE_FLYING = FLYING,
+ TRAIT_MOVE_VENTCRAWLING = VENTCRAWLING,
+ TRAIT_MOVE_FLOATING = FLOATING,
+ TRAIT_MOVE_PHASING = PHASING
+ ))
+
+GLOBAL_LIST_INIT(movement_type_addtrait_signals, set_movement_type_addtrait_signals())
+GLOBAL_LIST_INIT(movement_type_removetrait_signals, set_movement_type_removetrait_signals())
+
+/proc/set_movement_type_addtrait_signals(signal_prefix)
+ . = list()
+ for(var/trait in GLOB.movement_type_trait_to_flag)
+ . += SIGNAL_ADDTRAIT(trait)
+
+/proc/set_movement_type_removetrait_signals(signal_prefix)
+ . = list()
+ for(var/trait in GLOB.movement_type_trait_to_flag)
+ . += SIGNAL_REMOVETRAIT(trait)
diff --git a/code/datums/components/caltrop.dm b/code/datums/components/caltrop.dm
index d6fea8e7244..97772d0f2e8 100644
--- a/code/datums/components/caltrop.dm
+++ b/code/datums/components/caltrop.dm
@@ -29,7 +29,7 @@
return
//move these next two down a level if you add more mobs to this.
- if(H.is_flying() || H.is_floating()) //check if they are able to pass over us
+ if(H.movement_type & (FLOATING|FLYING)) //check if they are able to pass over us
return //gravity checking only our parent would prevent us from triggering they're using magboots / other gravity assisting items that would cause them to still touch us.
if(H.buckled) //if they're buckled to something, that something should be checked instead.
return
diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm
index e0a96bc6217..481173731f3 100644
--- a/code/datums/components/chasm.dm
+++ b/code/datums/components/chasm.dm
@@ -69,7 +69,7 @@
return FALSE
if(!isliving(AM) && !isobj(AM))
return FALSE
- if(is_type_in_typecache(AM, forbidden_types) || AM.throwing || (AM.movement_type & FLOATING))
+ if(is_type_in_typecache(AM, forbidden_types) || AM.throwing || (AM.movement_type & (FLOATING|FLYING)))
return FALSE
//Flies right over the chasm
if(ismob(AM))
@@ -78,8 +78,6 @@
var/mob/buckled_to = M.buckled
if((!ismob(M.buckled) || (buckled_to.buckled != M)) && !droppable(M.buckled))
return FALSE
- if(M.is_flying())
- return FALSE
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
if(istype(H.belt, /obj/item/wormhole_jaunter))
diff --git a/code/datums/components/slippery.dm b/code/datums/components/slippery.dm
index 5f9aa29d083..ce7dc1ed78f 100644
--- a/code/datums/components/slippery.dm
+++ b/code/datums/components/slippery.dm
@@ -18,7 +18,7 @@
SIGNAL_HANDLER
var/mob/victim = AM
- if(istype(victim) && !victim.is_flying() && victim.slip(knockdown_time, parent, lube_flags, paralyze_time, force_drop_items) && callback)
+ if(istype(victim) && !(victim.movement_type & FLYING) && victim.slip(knockdown_time, parent, lube_flags, paralyze_time, force_drop_items) && callback)
callback.Invoke(victim)
diff --git a/code/datums/elements/movetype_handler.dm b/code/datums/elements/movetype_handler.dm
new file mode 100644
index 00000000000..f93f57e2c78
--- /dev/null
+++ b/code/datums/elements/movetype_handler.dm
@@ -0,0 +1,109 @@
+/**
+ * An element that enables and disables movetype bitflags as movetype traits are added and removed.
+ * It also handles the +2/-2 pixel y anim loop typical of mobs possessing the FLYING or FLOATING movetypes.
+ * This element is necessary for the TRAIT_MOVE_ traits to work correctly. So make sure to include it when
+ * manipulating those traits on non-living movables.
+ */
+/datum/element/movetype_handler
+ element_flags = ELEMENT_DETACH
+
+ var/list/attached_atoms = list()
+ var/list/paused_floating_anim_atoms = list()
+
+/datum/element/movetype_handler/Attach(datum/target)
+ . = ..()
+ if(!ismovable(target))
+ return ELEMENT_INCOMPATIBLE
+ if(attached_atoms[target]) //Already attached.
+ return
+
+ var/atom/movable/movable_target = target
+ RegisterSignal(movable_target, GLOB.movement_type_addtrait_signals, .proc/on_movement_type_trait_gain)
+ RegisterSignal(movable_target, GLOB.movement_type_removetrait_signals, .proc/on_movement_type_trait_loss)
+ RegisterSignal(movable_target, SIGNAL_ADDTRAIT(TRAIT_NO_FLOATING_ANIM), .proc/on_no_floating_anim_trait_gain)
+ RegisterSignal(movable_target, SIGNAL_REMOVETRAIT(TRAIT_NO_FLOATING_ANIM), .proc/on_no_floating_anim_trait_loss)
+ RegisterSignal(movable_target, COMSIG_PAUSE_FLOATING_ANIM, .proc/pause_floating_anim)
+ attached_atoms[movable_target] = TRUE
+
+ if(movable_target.movement_type & (FLOATING|FLYING) && !HAS_TRAIT(movable_target, TRAIT_NO_FLOATING_ANIM))
+ float(movable_target)
+
+/datum/element/movetype_handler/Detach(datum/source)
+ UnregisterSignal(source, list(
+ GLOB.movement_type_addtrait_signals,
+ GLOB.movement_type_removetrait_signals,
+ SIGNAL_ADDTRAIT(TRAIT_NO_FLOATING_ANIM),
+ SIGNAL_REMOVETRAIT(TRAIT_NO_FLOATING_ANIM),
+ COMSIG_PAUSE_FLOATING_ANIM
+ ))
+ attached_atoms -= source
+ paused_floating_anim_atoms -= source
+ stop_floating(source)
+ return ..()
+
+/// Called when a movement type trait is added to the movable. Enables the relative bitflag.
+/datum/element/movetype_handler/proc/on_movement_type_trait_gain(atom/movable/source, trait)
+ SIGNAL_HANDLER
+ var/flag = GLOB.movement_type_trait_to_flag[trait]
+ if(source.movement_type & flag)
+ return
+ if(!(source.movement_type & (FLOATING|FLYING)) && (trait == TRAIT_MOVE_FLYING || trait == TRAIT_MOVE_FLOATING) && !paused_floating_anim_atoms[source] && !HAS_TRAIT(source, TRAIT_NO_FLOATING_ANIM))
+ float(source)
+ source.movement_type |= flag
+ SEND_SIGNAL(source, COMSIG_MOVETYPE_FLAG_ENABLED, flag)
+
+/// Called when a movement type trait is removed from the movable. Disables the relative bitflag if it wasn't there in the compile-time bitfield.
+/datum/element/movetype_handler/proc/on_movement_type_trait_loss(atom/movable/source, trait)
+ SIGNAL_HANDLER
+ var/flag = GLOB.movement_type_trait_to_flag[trait]
+ if(initial(source.movement_type) & flag)
+ return
+ source.movement_type &= ~flag
+ if((trait == TRAIT_MOVE_FLYING || trait == TRAIT_MOVE_FLOATING) && !(source.movement_type & (FLOATING|FLYING)))
+ stop_floating(source)
+ SEND_SIGNAL(source, COMSIG_MOVETYPE_FLAG_DISABLED, flag)
+
+/// Called when the TRAIT_NO_FLOATING_ANIM trait is added to the movable. Stops it from bobbing up and down.
+/datum/element/movetype_handler/proc/on_no_floating_anim_trait_gain(atom/movable/source, trait)
+ SIGNAL_HANDLER
+ stop_floating(source)
+
+/// Called when the TRAIT_NO_FLOATING_ANIM trait is removed from the mob. Restarts the bobbing animation.
+/datum/element/movetype_handler/proc/on_no_floating_anim_trait_loss(atom/movable/source, trait)
+ SIGNAL_HANDLER
+ if(source.movement_type & (FLOATING|FLYING) && !paused_floating_anim_atoms[source])
+ float(source)
+
+///Pauses the floating animation for the duration of the timer... plus [tickrate - (world.time + timer) % tickrate] to be precise.
+/datum/element/movetype_handler/proc/pause_floating_anim(atom/movable/source, timer)
+ SIGNAL_HANDLER
+ if(paused_floating_anim_atoms[source] < world.time + timer)
+ stop_floating(source)
+ if(!length(paused_floating_anim_atoms))
+ START_PROCESSING(SSdcs, src) //1 second tickrate.
+ paused_floating_anim_atoms[source] = world.time + timer
+
+/datum/element/movetype_handler/process()
+ for(var/_paused in paused_floating_anim_atoms)
+ var/atom/movable/paused = _paused
+ if(!paused)
+ paused_floating_anim_atoms -= paused
+ else if(paused_floating_anim_atoms[paused] < world.time)
+ if(paused.movement_type & (FLOATING|FLYING) && !HAS_TRAIT(paused, TRAIT_NO_FLOATING_ANIM))
+ float(paused)
+ paused_floating_anim_atoms -= paused
+ if(!length(paused_floating_anim_atoms))
+ STOP_PROCESSING(SSdcs, src)
+
+///Floats the movable up and down. Not a comsig proc.
+/datum/element/movetype_handler/proc/float(atom/movable/target)
+ animate(target, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE|ANIMATION_PARALLEL)
+ animate(pixel_y = -2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
+
+/// Stops the above. Also not a comsig proc.
+/datum/element/movetype_handler/proc/stop_floating(atom/movable/target)
+ var/final_pixel_y = target.base_pixel_y
+ if(isliving(target)) //Living mobs also have a 'body_position_pixel_y_offset' variable that has to be taken into account here.
+ var/mob/living/living_target = target
+ final_pixel_y += living_target.body_position_pixel_y_offset
+ animate(target, pixel_y = final_pixel_y, time = 1 SECONDS)
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 7cfb22dbb1c..4010870cbbd 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -35,8 +35,14 @@
var/list/client_mobs_in_contents // This contains all the client mobs within this container
var/list/acted_explosions //for explosion dodging
var/datum/forced_movement/force_moving = null //handled soley by forced_movement.dm
- ///In case you have multiple types, you automatically use the most useful one. IE: Skating on ice, flippers on water, flying over chasm/space, etc. Should only be changed through setMovetype()
+
+ /**
+ * In case you have multiple types, you automatically use the most useful one.
+ * IE: Skating on ice, flippers on water, flying over chasm/space, etc.
+ * I reccomend you use the movetype_handler system and not modify this directly, especially for living mobs.
+ */
var/movement_type = GROUND
+
var/atom/movable/pulling
var/grab_state = 0
var/throwforce = 0
@@ -594,15 +600,6 @@
var/atom/movable/AM = item
AM.onTransitZ(old_z,new_z)
-
-///Proc to modify the movement_type and hook behavior associated with it changing.
-/atom/movable/proc/setMovetype(newval)
- if(movement_type == newval)
- return
- . = movement_type
- movement_type = newval
-
-
/**
* Called whenever an object moves and by mobs when they attempt to move themselves through space
* And when an object or action applies a force on src, see [newtonian_move][/atom/movable/proc/newtonian_move]
@@ -848,8 +845,8 @@
var/matrix/initial_transform = matrix(transform)
var/matrix/rotated_transform = transform.Turn(15 * turn_dir)
- animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform=rotated_transform, time = 1, easing=BACK_EASING|EASE_IN)
- animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform=initial_transform, time = 2, easing=SINE_EASING)
+ animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform=rotated_transform, time = 1, easing=BACK_EASING|EASE_IN, flags = ANIMATION_PARALLEL)
+ animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform=initial_transform, time = 2, easing=SINE_EASING, flags = ANIMATION_PARALLEL)
/atom/movable/proc/do_item_attack_animation(atom/A, visual_effect_icon, obj/item/used_item)
var/image/I
@@ -903,19 +900,6 @@
acted_explosions += ex_id
return TRUE
-//TODO: Better floating
-/atom/movable/proc/float(on)
- if(throwing)
- return
- if(on && !(movement_type & FLOATING))
- animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
- animate(pixel_y = -2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
- setMovetype(movement_type | FLOATING)
- else if (!on && (movement_type & FLOATING))
- animate(src, pixel_y = base_pixel_y, time = 10)
- setMovetype(movement_type & ~FLOATING)
-
-
/* Language procs
* Unless you are doing something very specific, these are the ones you want to use.
*/
diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm
index cf102950bc7..7bc6eceb63f 100644
--- a/code/game/objects/buckling.dm
+++ b/code/game/objects/buckling.dm
@@ -108,6 +108,10 @@
if(!check_loc && M.loc != loc)
M.forceMove(loc)
+ if(anchored)
+ ADD_TRAIT(M, TRAIT_NO_FLOATING_ANIM, BUCKLED_TRAIT)
+ if(!length(buckled_mobs))
+ RegisterSignal(src, COMSIG_MOVABLE_SET_ANCHORED, .proc/on_set_anchored)
M.set_buckled(src)
M.setDir(dir)
buckled_mobs |= M
@@ -146,10 +150,25 @@
buckled_mob.clear_alert("buckled")
buckled_mob.set_glide_size(DELAY_TO_GLIDE_SIZE(buckled_mob.total_multiplicative_slowdown()))
buckled_mobs -= buckled_mob
+ if(anchored)
+ REMOVE_TRAIT(buckled_mob, TRAIT_NO_FLOATING_ANIM, BUCKLED_TRAIT)
+ if(!length(buckled_mobs))
+ UnregisterSignal(src, COMSIG_MOVABLE_SET_ANCHORED, .proc/on_set_anchored)
SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force)
post_unbuckle_mob(.)
+/atom/movable/proc/on_set_anchored(atom/movable/source, anchorvalue)
+ SIGNAL_HANDLER
+ for(var/_buckled_mob in buckled_mobs)
+ if(!_buckled_mob)
+ continue
+ var/mob/living/buckled_mob = _buckled_mob
+ if(anchored)
+ ADD_TRAIT(buckled_mob, TRAIT_NO_FLOATING_ANIM, BUCKLED_TRAIT)
+ else
+ REMOVE_TRAIT(buckled_mob, TRAIT_NO_FLOATING_ANIM, BUCKLED_TRAIT)
+
/**
* Call [/atom/movable/proc/unbuckle_mob] for all buckled mobs
*/
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index 0470fdcca56..63b5a209cc0 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -355,7 +355,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
/obj/item/shard/Crossed(atom/movable/AM)
if(isliving(AM))
var/mob/living/L = AM
- if(!(L.is_flying() || L.is_floating() || L.buckled))
+ if(!(L.movement_type & (FLYING|FLOATING)) || L.buckled)
playsound(src, 'sound/effects/glass_step.ogg', HAS_TRAIT(L, TRAIT_LIGHT_STEP) ? 30 : 50, TRUE)
return ..()
diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm
index 3d4e0307ece..0fd34857efc 100644
--- a/code/game/objects/items/tanks/jetpack.dm
+++ b/code/game/objects/items/tanks/jetpack.dm
@@ -78,7 +78,7 @@
return
if(!isturf(user.loc))//You can't use jet in nowhere or from mecha/closet
return
- if(!(user.is_flying() || user.is_floating()) || user.buckled)//You don't want use jet in gravity or while buckled.
+ if(!(user.movement_type & FLOATING) || user.buckled)//You don't want use jet in gravity or while buckled.
return
if(user.pulledby)//You don't must use jet if someone pull you
return
diff --git a/code/game/objects/structures/life_candle.dm b/code/game/objects/structures/life_candle.dm
index 3a0cb6bd6db..6159ad81d3f 100644
--- a/code/game/objects/structures/life_candle.dm
+++ b/code/game/objects/structures/life_candle.dm
@@ -24,6 +24,10 @@
var/respawn_time = 50
var/respawn_sound = 'sound/magic/staff_animation.ogg'
+/obj/structure/life_candle/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/movetype_handler)
+
/obj/structure/life_candle/attack_hand(mob/user)
. = ..()
if(.)
@@ -33,12 +37,15 @@
if(user.mind in linked_minds)
user.visible_message("[user] reaches out and pinches the flame of [src].", "You sever the connection between yourself and [src].")
linked_minds -= user.mind
+ if(!linked_minds.len)
+ REMOVE_TRAIT(src, TRAIT_MOVE_FLOATING, LIFECANDLE_TRAIT)
else
+ if(!linked_minds.len)
+ ADD_TRAIT(src, TRAIT_MOVE_FLOATING, LIFECANDLE_TRAIT)
user.visible_message("[user] touches [src]. It seems to respond to [user.p_their()] presence!", "You create a connection between you and [src].")
linked_minds |= user.mind
update_icon()
- float(linked_minds.len)
if(linked_minds.len)
START_PROCESSING(SSobj, src)
set_light(lit_luminosity)
diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm
index 990e84ba1ba..d3d472c6c71 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -1261,6 +1261,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/source = "adminabuse"
switch(add_or_remove)
if("Add") //Not doing source choosing here intentionally to make this bit faster to use, you can always vv it.
+ if(GLOB.movement_type_trait_to_flag[chosen_trait]) //include the required element.
+ D.AddElement(/datum/element/movetype_handler)
ADD_TRAIT(D,chosen_trait,source)
if("Remove")
var/specific = input("All or specific source ?", "Trait Remove/Add") as null|anything in list("All","Specific")
diff --git a/code/modules/antagonists/blob/blob_mobs.dm b/code/modules/antagonists/blob/blob_mobs.dm
index 28aa034eba1..7f5f29de816 100644
--- a/code/modules/antagonists/blob/blob_mobs.dm
+++ b/code/modules/antagonists/blob/blob_mobs.dm
@@ -105,7 +105,7 @@
attack_verb_continuous = "hits"
attack_verb_simple = "hit"
attack_sound = 'sound/weapons/genhit1.ogg'
- movement_type = FLYING
+ is_flying_animal = TRUE
del_on_death = TRUE
deathmessage = "explodes into a cloud of gas!"
gold_core_spawnable = NO_SPAWN //gold slime cores should only spawn the independent subtype
diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm
index 4cd679e1fd1..32535d228f2 100644
--- a/code/modules/antagonists/revenant/revenant.dm
+++ b/code/modules/antagonists/revenant/revenant.dm
@@ -45,7 +45,7 @@
status_flags = 0
wander = FALSE
density = FALSE
- movement_type = FLYING
+ is_flying_animal = TRUE
move_resist = MOVE_FORCE_OVERPOWERING
mob_size = MOB_SIZE_TINY
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index 13ae1e4f2fe..243ee3edc60 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -376,7 +376,6 @@
custom_premium_price = PAYCHECK_EASY * 1.6
custom_price = PAYCHECK_EASY * 1.6
-
/obj/item/clothing/shoes/kindle_kicks
name = "Kindle Kicks"
desc = "They'll sure kindle something in you, and it's not childhood nostalgia..."
diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
index 6c004bbc074..de9b8968e08 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
@@ -86,9 +86,3 @@
visible_message("[src] smashes into [hit_atom]!", "[src] smashes into [hit_atom]!")
Paralyze(40, ignore_canstun = TRUE)
-/mob/living/carbon/alien/humanoid/float(on)
- if(leaping)
- return
- ..()
-
-
diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm
index 84b6b3b7ac3..f0c669b718f 100644
--- a/code/modules/mob/living/carbon/carbon_defense.dm
+++ b/code/modules/mob/living/carbon/carbon_defense.dm
@@ -529,7 +529,7 @@
// Shake animation
if (incapacitated())
var/direction = prob(50) ? -1 : 1
- animate(src, pixel_x = pixel_x + SHAKE_ANIMATION_OFFSET * direction, time = 1, easing = QUAD_EASING | EASE_OUT)
+ animate(src, pixel_x = pixel_x + SHAKE_ANIMATION_OFFSET * direction, time = 1, easing = QUAD_EASING | EASE_OUT, flags = ANIMATION_PARALLEL)
animate(pixel_x = pixel_x - (SHAKE_ANIMATION_OFFSET * 2 * direction), time = 1)
animate(pixel_x = pixel_x + SHAKE_ANIMATION_OFFSET * direction, time = 1, easing = QUAD_EASING | EASE_IN)
diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm
index 7f65b79ddca..584e74d72c4 100644
--- a/code/modules/mob/living/carbon/carbon_movement.dm
+++ b/code/modules/mob/living/carbon/carbon_movement.dm
@@ -59,17 +59,17 @@
if(!usable_legs && !(movement_type & (FLYING | FLOATING)))
ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
-
-/mob/living/carbon/setMovetype(newval)
+/mob/living/carbon/on_movement_type_flag_enabled(datum/source, flag)
+ var/old_movetype = movement_type
. = ..()
- if(isnull(.))
- return
- if(!(. & (FLYING | FLOATING)))
- if(movement_type & (FLYING | FLOATING)) //From not flying to flying.
- remove_movespeed_modifier(/datum/movespeed_modifier/limbless)
- REMOVE_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
- REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
- else if(!(movement_type & (FLYING | FLOATING))) //From flying to no longer flying.
+ if(flag & (FLYING | FLOATING) && !(old_movetype & (FLYING | FLOATING)))
+ remove_movespeed_modifier(/datum/movespeed_modifier/limbless)
+ REMOVE_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
+ REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
+
+/mob/living/carbon/on_movement_type_flag_disabled(datum/source, flag)
+ . = ..()
+ if(flag & (FLYING | FLOATING) && !(movement_type & (FLYING | FLOATING)))
var/limbless_slowdown = 0
if(usable_legs < default_num_legs)
limbless_slowdown += (default_num_legs - usable_legs) * 3
diff --git a/code/modules/mob/living/carbon/carbon_update_icons.dm b/code/modules/mob/living/carbon/carbon_update_icons.dm
index b44b7ed2683..e9f8d044acc 100644
--- a/code/modules/mob/living/carbon/carbon_update_icons.dm
+++ b/code/modules/mob/living/carbon/carbon_update_icons.dm
@@ -1,4 +1,4 @@
-//IMPORTANT: Multiple animate() calls do not stack well, so try to do them all at once if you can.
+sues//IMPORTANT: Multiple animate() calls do not stack well, so try to do them all at once if you can.
/mob/living/carbon/update_transform()
var/matrix/ntransform = matrix(transform) //aka transform.Copy()
var/final_pixel_y = pixel_y
@@ -21,8 +21,8 @@
resize = RESIZE_DEFAULT_SIZE
if(changed)
+ SEND_SIGNAL(src, COMSIG_PAUSE_FLOATING_ANIM, 0.3 SECONDS)
animate(src, transform = ntransform, time = (lying_prev == 0 || lying_angle == 0) ? 2 : 0, pixel_y = final_pixel_y, dir = final_dir, easing = (EASE_IN|EASE_OUT))
- setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life().
/mob/living/carbon
var/list/overlays_standing[TOTAL_LAYERS]
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 7a58c2eff01..0cc52bea95a 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -902,11 +902,6 @@
/mob/living/carbon/human/is_literate()
return TRUE
-/mob/living/carbon/human/update_gravity(has_gravity,override = 0)
- if(dna?.species) //prevents a runtime while a human is being monkeyfied
- override = dna.species.override_float
- ..()
-
/mob/living/carbon/human/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, vomit_type = VOMIT_TOXIC, harm = TRUE, force = FALSE, purge_ratio = 0.1)
if(blood && (NOBLOOD in dna.species.species_traits) && !HAS_TRAIT(src, TRAIT_TOXINLOVER))
if(message)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index ecb8de37840..e06232bcaf5 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -168,8 +168,6 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/obj/item/organ/appendix/mutantappendix = /obj/item/organ/appendix
///Forces an item into this species' hands. Only an honorary mutantthing because this is not an organ and not loaded in the same way, you've been warned to do your research.
var/obj/item/mutanthands
- ///Allows the species to not give a single F about gravity. Used by wings.
- var/override_float = FALSE
///Bitflag that controls what in game ways something can select this species as a spawnable source, such as magic mirrors. See [mob defines][code/__DEFINES/mobs.dm] for possible sources.
var/changesource_flags = NONE
@@ -2080,18 +2078,18 @@ GLOBAL_LIST_EMPTY(roundstart_races)
//UNSAFE PROC, should only be called through the Activate or other sources that check for CanFly
/datum/species/proc/ToggleFlight(mob/living/carbon/human/H)
- if(!(H.movement_type & FLYING))
+ if(!HAS_TRAIT_FROM(H, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT))
stunmod *= 2
speedmod -= 0.35
- H.setMovetype(H.movement_type | FLYING)
- override_float = TRUE
+ ADD_TRAIT(H, TRAIT_NO_FLOATING_ANIM, SPECIES_FLIGHT_TRAIT)
+ ADD_TRAIT(H, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT)
passtable_on(H, SPECIES_TRAIT)
H.OpenWings()
else
stunmod *= 0.5
speedmod += 0.35
- H.setMovetype(H.movement_type & ~FLYING)
- override_float = FALSE
+ REMOVE_TRAIT(H, TRAIT_NO_FLOATING_ANIM, SPECIES_FLIGHT_TRAIT)
+ REMOVE_TRAIT(H, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT)
passtable_off(H, SPECIES_TRAIT)
H.CloseWings()
diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm
index 4da10947019..6eba736084f 100644
--- a/code/modules/mob/living/init_signals.dm
+++ b/code/modules/mob/living/init_signals.dm
@@ -38,6 +38,8 @@
SIGNAL_REMOVETRAIT(TRAIT_NODEATH),
), .proc/update_succumb_action)
+ RegisterSignal(src, COMSIG_MOVETYPE_FLAG_ENABLED, .proc/on_movement_type_flag_enabled)
+ RegisterSignal(src, COMSIG_MOVETYPE_FLAG_DISABLED, .proc/on_movement_type_flag_disabled)
/// Called when [TRAIT_KNOCKEDOUT] is added to the mob.
/mob/living/proc/on_knockedout_trait_gain(datum/source)
@@ -180,3 +182,13 @@
throw_alert("succumb", /atom/movable/screen/alert/succumb)
else
clear_alert("succumb")
+
+///From [element/movetype_handler/on_movement_type_trait_gain()]
+/mob/living/proc/on_movement_type_flag_enabled(datum/source, trait)
+ SIGNAL_HANDLER
+ update_movespeed(FALSE)
+
+///From [element/movetype_handler/on_movement_type_trait_loss()]
+/mob/living/proc/on_movement_type_flag_disabled(datum/source, trait)
+ SIGNAL_HANDLER
+ update_movespeed(FALSE)
diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm
index da74b491ebc..0a99e840305 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -4,9 +4,6 @@
/mob/living/proc/Life(times_fired)
set waitfor = FALSE
- if((movement_type & FLYING) && !(movement_type & FLOATING)) //TODO: Better floating
- float(on = TRUE)
-
if (client)
var/turf/T = get_turf(src)
if(!T)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 14d205c6372..30832332226 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -10,6 +10,10 @@
faction += "[REF(src)]"
GLOB.mob_living_list += src
+/mob/living/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/movetype_handler)
+
/mob/living/prepare_huds()
..()
prepare_data_huds()
@@ -942,10 +946,11 @@
/mob/living/proc/get_visible_name()
return name
-/mob/living/update_gravity(has_gravity, override)
+/mob/living/update_gravity(has_gravity)
. = ..()
if(!SSticker.HasRoundStarted())
return
+ var/was_weightless = alerts["gravity"] && istype(alerts["gravity"], /atom/movable/screen/alert/weightless)
if(has_gravity)
if(has_gravity == 1)
clear_alert("gravity")
@@ -954,24 +959,12 @@
throw_alert("gravity", /atom/movable/screen/alert/veryhighgravity)
else
throw_alert("gravity", /atom/movable/screen/alert/highgravity)
+ if(was_weightless)
+ REMOVE_TRAIT(src, TRAIT_MOVE_FLOATING, NO_GRAVITY_TRAIT)
else
throw_alert("gravity", /atom/movable/screen/alert/weightless)
- if(!override && !is_flying())
- float(!has_gravity)
-
-/mob/living/float(on)
- if(throwing)
- return
- var/fixed = 0
- if(anchored || (buckled?.anchored))
- fixed = 1
- if(on && !(movement_type & FLOATING) && !fixed)
- animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
- animate(pixel_y = -2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
- setMovetype(movement_type | FLOATING)
- else if(((!on || fixed) && (movement_type & FLOATING)))
- animate(src, pixel_y = base_pixel_y + body_position_pixel_y_offset, time = 1 SECONDS)
- setMovetype(movement_type & ~FLOATING)
+ if(!was_weightless)
+ ADD_TRAIT(src, TRAIT_MOVE_FLOATING, NO_GRAVITY_TRAIT)
// The src mob is trying to strip an item from someone
// Override if a certain type of mob should be behave differently when stripping items (can't, for example)
@@ -1065,11 +1058,8 @@
var/amplitude = min(4, (jitteriness/100) + 1)
var/pixel_x_diff = rand(-amplitude, amplitude)
var/pixel_y_diff = rand(-amplitude/3, amplitude/3)
- var/final_pixel_x = base_pixel_x + body_position_pixel_x_offset
- var/final_pixel_y = base_pixel_y + body_position_pixel_y_offset
- animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 2, loop = 6)
- animate(pixel_x = final_pixel_x , pixel_y = final_pixel_y , time = 2)
- setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure to restart it in next life().
+ animate(src, pixel_x = pixel_x_diff, pixel_y = pixel_y_diff , time = 2, loop = 6, flags = ANIMATION_RELATIVE|ANIMATION_PARALLEL)
+ animate(pixel_x = -pixel_x_diff , pixel_y = -pixel_y_diff , time = 2, flags = ANIMATION_RELATIVE)
/mob/living/proc/get_temperature(datum/gas_mixture/environment)
var/loc_temp = environment ? environment.temperature : T0C
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 4624c76a75f..91b32fe3695 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -401,7 +401,6 @@
if(!used_item)
used_item = get_active_held_item()
..()
- setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
/**
* Does a slap animation on an atom
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index ac2ed39bba7..e45e590ac4d 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -26,7 +26,7 @@
maxbodytemp = INFINITY
healable = 0
faction = list("cult")
- movement_type = FLYING
+ is_flying_animal = TRUE
pressure_resistance = 100
unique_name = 1
AIStatus = AI_OFF //normal constructs don't have AI
diff --git a/code/modules/mob/living/simple_animal/friendly/butterfly.dm b/code/modules/mob/living/simple_animal/friendly/butterfly.dm
index bf4f45e2832..c31165b5183 100644
--- a/code/modules/mob/living/simple_animal/friendly/butterfly.dm
+++ b/code/modules/mob/living/simple_animal/friendly/butterfly.dm
@@ -18,7 +18,7 @@
friendly_verb_continuous = "nudges"
friendly_verb_simple = "nudge"
density = FALSE
- movement_type = FLYING
+ is_flying_animal = TRUE
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
ventcrawler = VENTCRAWLER_ALWAYS
mob_size = MOB_SIZE_TINY
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index 8cfc140d6c3..43d75e0eb80 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -25,7 +25,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
speed = 0
a_intent = INTENT_HARM
stop_automated_movement = 1
- movement_type = FLYING // Immunity to chasms and landmines, etc.
+ is_flying_animal = TRUE // Immunity to chasms and landmines, etc.
attack_sound = 'sound/weapons/punch1.ogg'
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm
index 89a0feb404e..151ff34052e 100644
--- a/code/modules/mob/living/simple_animal/hostile/bees.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bees.dm
@@ -42,7 +42,7 @@
density = FALSE
mob_size = MOB_SIZE_TINY
mob_biotypes = MOB_ORGANIC|MOB_BUG
- movement_type = FLYING
+ is_flying_animal = TRUE
gold_core_spawnable = FRIENDLY_SPAWN
search_objects = 1 //have to find those plant trays!
can_be_held = TRUE
diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm
index c0fe9b5d0a3..adf79b52680 100644
--- a/code/modules/mob/living/simple_animal/hostile/carp.dm
+++ b/code/modules/mob/living/simple_animal/hostile/carp.dm
@@ -41,7 +41,7 @@
minbodytemp = 0
maxbodytemp = 1500
faction = list("carp")
- movement_type = FLYING
+ is_flying_animal = TRUE
pressure_resistance = 200
gold_core_spawnable = HOSTILE_SPAWN
diff --git a/code/modules/mob/living/simple_animal/hostile/eyeballs.dm b/code/modules/mob/living/simple_animal/hostile/eyeballs.dm
index 57a33c2ee02..771d5841223 100644
--- a/code/modules/mob/living/simple_animal/hostile/eyeballs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/eyeballs.dm
@@ -25,7 +25,7 @@
attack_verb_continuous = "blinks at"
attack_verb_simple = "blink at"
attack_sound = 'sound/weapons/pierce.ogg'
- movement_type = FLYING
+ is_flying_animal = TRUE
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 1500
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
index cb5d9e39b82..59689523481 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
@@ -81,9 +81,13 @@
/obj/structure/leaper_bubble/Initialize()
. = ..()
- INVOKE_ASYNC(src, /atom/movable.proc/float, TRUE)
QDEL_IN(src, 100)
+/obj/structure/leaper_bubble/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/movetype_handler)
+ ADD_TRAIT(src, TRAIT_MOVE_FLOATING, LEAPER_BUBBLE_TRAIT)
+
/obj/structure/leaper_bubble/Destroy()
new /obj/effect/temp_visual/leaper_projectile_impact(get_turf(src))
playsound(src,'sound/effects/snap.ogg',50, TRUE, -1)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index 67402b5ce79..35e647f676d 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -57,6 +57,10 @@
/datum/action/innate/megafauna_attack/alternating_cardinals)
small_sprite_type = /datum/action/small_sprite/megafauna/colossus
+/mob/living/simple_animal/hostile/megafauna/colossus/Initialize()
+ . = ..()
+ ADD_TRAIT(src, TRAIT_NO_FLOATING_ANIM, ROUNDSTART_TRAIT) //we don't want this guy to float, messes up his animations.
+
/datum/action/innate/megafauna_attack/spiral_attack
name = "Spiral Shots"
icon_icon = 'icons/mob/actions/actions_items.dmi'
@@ -250,14 +254,6 @@
AT.pixel_y += random_y
return ..()
-/mob/living/simple_animal/hostile/megafauna/colossus/float(on) //we don't want this guy to float, messes up his animations
- if(throwing)
- return
- if(on && !(movement_type & FLOATING))
- setMovetype(movement_type | FLOATING)
- else if(!on && (movement_type & FLOATING))
- setMovetype(movement_type & ~FLOATING)
-
/obj/projectile/colossus
name ="death bolt"
icon_state= "chronobolt"
@@ -661,7 +657,7 @@
friendly_verb_continuous = "taps"
friendly_verb_simple = "tap"
density = FALSE
- movement_type = FLYING
+ is_flying_animal = TRUE
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
ventcrawler = VENTCRAWLER_ALWAYS
mob_size = MOB_SIZE_TINY
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm
index 9166ced81c2..1ff98608b79 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm
@@ -256,7 +256,7 @@ Difficulty: Extremely Hard
for(var/mob/living/L in viewers(src))
shake_camera(L, 3, 2)
playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE)
- setMovetype(movement_type | FLYING)
+ ADD_TRAIT(src, TRAIT_MOVE_FLYING, FROSTMINER_ENRAGE_TRAIT)
enraging = FALSE
adjustHealth(-maxHealth)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
index ada95a6c53c..9740b011bf6 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -11,7 +11,7 @@
light_range = 3
faction = list("mining", "boss")
weather_immunities = list("lava","ash")
- movement_type = FLYING
+ is_flying_animal = TRUE
robust_searching = TRUE
ranged_ignores_vision = TRUE
stat_attack = DEAD
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
index b13f01854b3..0b8205c6da1 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
@@ -110,7 +110,7 @@
speak_emote = list("telepathically cries")
attack_sound = 'sound/weapons/bladeslice.ogg'
stat_attack = HARD_CRIT
- movement_type = FLYING
+ is_flying_animal = TRUE
robust_searching = 1
crusher_loot = /obj/item/crusher_trophy/watcher_wing
gold_core_spawnable = NO_SPAWN
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm
index b24f055d3bb..6f0e8349699 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm
@@ -6,7 +6,7 @@
icon_living = "curseblob"
icon_aggro = "curseblob"
mob_biotypes = MOB_SPIRIT
- movement_type = FLYING
+ is_flying_animal = TRUE
move_to_delay = 5
vision_range = 20
aggro_vision_range = 20
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm
index e99911f2aec..59513ced480 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm
@@ -201,7 +201,7 @@
icon_aggro = "herald_mirror"
deathmessage = "shatters violently!"
deathsound = 'sound/effects/glassbr1.ogg'
- movement_type = FLYING
+ is_flying_animal = TRUE
del_on_death = TRUE
is_mirror = TRUE
var/mob/living/simple_animal/hostile/asteroid/elite/herald/my_master = null
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
index 87bae1f76f0..8290617c0ac 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm
@@ -73,7 +73,7 @@
speed = 3
maxHealth = 1
health = 1
- movement_type = FLYING
+ is_flying_animal = TRUE
harm_intent_damage = 5
melee_damage_lower = 2
melee_damage_upper = 2
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice demon.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice demon.dm
index 35fab076a96..109a82734c6 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice demon.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/ice demon.dm
@@ -37,7 +37,7 @@
deathmessage = "fades as the energies that tied it to this world dissipate."
deathsound = 'sound/magic/demon_dies.ogg'
stat_attack = HARD_CRIT
- movement_type = FLYING
+ is_flying_animal = TRUE
robust_searching = TRUE
footstep_type = FOOTSTEP_MOB_CLAW
/// Distance the demon will teleport from the target
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm
index 77044787129..fa0967ff873 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm
@@ -28,7 +28,7 @@
environment_smash = ENVIRONMENT_SMASH_NONE
ventcrawler = VENTCRAWLER_ALWAYS
mob_size = MOB_SIZE_TINY
- movement_type = FLYING
+ is_flying_animal = TRUE
speak_emote = list("squeaks")
var/max_co2 = 0 //to be removed once metastation map no longer use those for Sgt Araneus
var/min_oxy = 0
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm
index 8b9d0d666bf..17301c463f8 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm
@@ -28,7 +28,7 @@
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 1500
- movement_type = FLYING
+ is_flying_animal = TRUE
pressure_resistance = 300
gold_core_spawnable = NO_SPAWN //too spooky for science
light_system = MOVABLE_LIGHT
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index 24ef084847b..65a9e813b1a 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -306,7 +306,7 @@
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
mob_size = MOB_SIZE_TINY
- movement_type = FLYING
+ is_flying_animal = TRUE
limb_destroyer = 1
speak_emote = list("states")
bubble_icon = "syndibot"
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
index 77455dd683a..76e54ed17c2 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -63,7 +63,7 @@
friendly_verb_continuous = "grooms"
friendly_verb_simple = "groom"
mob_size = MOB_SIZE_SMALL
- movement_type = FLYING
+ is_flying_animal = TRUE
gold_core_spawnable = FRIENDLY_SPAWN
var/parrot_damage_upper = 10
diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm
index 227aff99cc9..1b2b51a494a 100644
--- a/code/modules/mob/living/simple_animal/shade.dm
+++ b/code/modules/mob/living/simple_animal/shade.dm
@@ -30,7 +30,7 @@
stop_automated_movement = 1
faction = list("cult")
status_flags = CANPUSH
- movement_type = FLYING
+ is_flying_animal = TRUE
loot = list(/obj/item/ectoplasm)
del_on_death = TRUE
initial_language_holder = /datum/language_holder/construct
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index cb8a01a78fd..89dcd554235 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -128,6 +128,9 @@
var/dextrous = FALSE
var/dextrous_hud_type = /datum/hud/dextrous
+ ///If the creature should have an innate TRAIT_MOVE_FLYING trait added on init that is also toggled off/on on death/revival.
+ var/is_flying_animal = FALSE
+
///The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever), AI_Z_OFF (Temporarily off due to nonpresence of players).
var/AIStatus = AI_ON
///once we have become sentient, we can never go back.
@@ -178,6 +181,8 @@
if(dextrous)
AddComponent(/datum/component/personal_crafting)
ADD_TRAIT(src, TRAIT_ADVANCEDTOOLUSER, ROUNDSTART_TRAIT)
+ if(is_flying_animal)
+ ADD_TRAIT(src, TRAIT_MOVE_FLYING, ROUNDSTART_TRAIT)
if(speak)
speak = string_list(speak)
@@ -214,6 +219,15 @@
return ..()
+/mob/living/simple_animal/vv_edit_var(var_name, var_value)
+ . = ..()
+ switch(var_name)
+ if(NAMEOF(src, is_flying_animal))
+ if(stat != DEAD)
+ if(!is_flying_animal)
+ REMOVE_TRAIT(src, TRAIT_MOVE_FLYING, ROUNDSTART_TRAIT)
+ else
+ ADD_TRAIT(src, TRAIT_MOVE_FLYING, ROUNDSTART_TRAIT)
/mob/living/simple_animal/attackby(obj/item/O, mob/user, params)
if(!is_type_in_list(O, food_type))
@@ -449,7 +463,6 @@
new i(loc)
/mob/living/simple_animal/death(gibbed)
- movement_type &= ~FLYING
if(nest)
nest.spawned_mobs -= src
nest = null
@@ -466,6 +479,8 @@
del_on_death = FALSE
qdel(src)
else
+ if(is_flying_animal)
+ REMOVE_TRAIT(src, TRAIT_MOVE_FLYING, ROUNDSTART_TRAIT)
health = 0
icon_state = icon_dead
if(flip_on_death)
@@ -499,7 +514,6 @@
/mob/living/simple_animal/extinguish_mob()
return
-
/mob/living/simple_animal/revive(full_heal = FALSE, admin_revive = FALSE)
. = ..()
if(!.)
@@ -507,8 +521,8 @@
icon = initial(icon)
icon_state = icon_living
density = initial(density)
- setMovetype(initial(movement_type))
-
+ if(is_flying_animal)
+ ADD_TRAIT(src, TRAIT_MOVE_FLYING, ROUNDSTART_TRAIT)
/mob/living/simple_animal/proc/make_babies() // <3 <3 <3
if(gender != FEMALE || stat || next_scan_time > world.time || !childtype || !animal_species || !SSticker.IsRoundInProgress())
diff --git a/code/modules/mob/living/ventcrawling.dm b/code/modules/mob/living/ventcrawling.dm
index 4585247d389..a27e352fc15 100644
--- a/code/modules/mob/living/ventcrawling.dm
+++ b/code/modules/mob/living/ventcrawling.dm
@@ -93,15 +93,14 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
A.pipe_vision_img.plane = ABOVE_HUD_PLANE
client.images += A.pipe_vision_img
pipes_shown += A.pipe_vision_img
- setMovetype(movement_type | VENTCRAWLING)
-
+ ADD_TRAIT(src, TRAIT_MOVE_VENTCRAWLING, VENTCRAWLING_TRAIT)
/mob/living/proc/remove_ventcrawl()
if(client)
for(var/image/current_image in pipes_shown)
client.images -= current_image
pipes_shown.len = 0
- setMovetype(movement_type & ~VENTCRAWLING)
+ REMOVE_TRAIT(src, TRAIT_MOVE_VENTCRAWLING, VENTCRAWLING_TRAIT)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index be1b71ee873..973aea0d70a 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1289,14 +1289,6 @@
/mob/proc/set_nutrition(change) //Seriously fuck you oldcoders.
nutrition = max(0, change)
-
-/mob/setMovetype(newval) //Set the movement type of the mob and update it's movespeed
- . = ..()
- if(isnull(.))
- return
- update_movespeed(FALSE)
-
-
/mob/proc/update_equipment_speed_mods()
var/speedies = equipped_speed_mods()
if(!speedies)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index a7b9fd7ba3d..6ffc07dd260 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -447,14 +447,6 @@
message_admins("No ghosts were willing to take control of [ADMIN_LOOKUPFLW(M)])")
return FALSE
-///Is the mob a flying mob
-/mob/proc/is_flying()
- return (movement_type & FLYING)
-
-///Is the mob a floating mob
-/mob/proc/is_floating()
- return (movement_type & FLOATING)
-
///Clicks a random nearby mob with the source from this mob
/mob/proc/click_random_mob()
var/list/nearby_mobs = list()
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 18c3de41d3f..22381cf5b11 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -940,7 +940,7 @@
if(!isliving(AM))
return
var/mob/living/L = AM
- if(istype(L) && !(L.is_flying() || L.is_floating() || L.buckled))
+ if(!(L.movement_type & (FLYING|FLOATING)) || L.buckled)
playsound(src, 'sound/effects/glass_step.ogg', HAS_TRAIT(L, TRAIT_LIGHT_STEP) ? 30 : 50, TRUE)
if(status == LIGHT_BURNED || status == LIGHT_OK)
shatter()
diff --git a/code/modules/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm
index f2f2b1ec6ed..67175891ff1 100644
--- a/code/modules/surgery/organs/augments_chest.dm
+++ b/code/modules/surgery/organs/augments_chest.dm
@@ -181,7 +181,7 @@
return
if(!isturf(owner.loc))//You can't use jet in nowhere or in mecha/closet
return
- if(!(owner.is_flying() || owner.is_floating()) || owner.buckled)//You don't want use jet in gravity or while buckled.
+ if(!(owner.movement_type & FLOATING) || owner.buckled)//You don't want use jet in gravity or while buckled.
return
if(owner.pulledby)//You don't must use jet if someone pull you
return
diff --git a/tgstation.dme b/tgstation.dme
index 15bbfffee0f..c29fcbba8fb 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -614,6 +614,7 @@
#include "code\datums\elements\firestacker.dm"
#include "code\datums\elements\forced_gravity.dm"
#include "code\datums\elements\light_blocking.dm"
+#include "code\datums\elements\movetype_handler.dm"
#include "code\datums\elements\obj_regen.dm"
#include "code\datums\elements\point_of_interest.dm"
#include "code\datums\elements\rad_insulation.dm"