diff --git a/beestation.dme b/beestation.dme
index 0eba7be95547f..01cc550d0e2cf 100644
--- a/beestation.dme
+++ b/beestation.dme
@@ -825,6 +825,7 @@
#include "code\datums\elements\light_blocking.dm"
#include "code\datums\elements\mechanical_repair.dm"
#include "code\datums\elements\mirage_border.dm"
+#include "code\datums\elements\movetype_handler.dm"
#include "code\datums\elements\obj_regen.dm"
#include "code\datums\elements\openspace_item_click_handler.dm"
#include "code\datums\elements\pet_bonus.dm"
diff --git a/code/__DEFINES/dcs/signals/signals_movable.dm b/code/__DEFINES/dcs/signals/signals_movable.dm
index 077ef19d0b78d..f89b79dad4d27 100644
--- a/code/__DEFINES/dcs/signals/signals_movable.dm
+++ b/code/__DEFINES/dcs/signals/signals_movable.dm
@@ -63,3 +63,12 @@
#define COMSIG_STORAGE_ENTERED "storage_entered"
///from base of atom/movable/on_exit_storage(): (datum/component/storage/concrete/master_storage)
#define COMSIG_STORAGE_EXITED "storage_exited"
+
+// /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"
+
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 5f17209e041d1..338abf737e3ab 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -523,3 +523,18 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
/// Trait for psyphoza, flag for examine logic
#define TRAIT_PSYCHIC_SENSE "psychic_sense"
+
+///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"
+
+#define VENTCRAWLING_TRAIT "ventcrawling"
+#define SPECIES_FLIGHT_TRAIT "species-flight"
+#define NO_GRAVITY_TRAIT "no-gravity"
+#define LIFECANDLE_TRAIT "lifecandle"
+#define LEAPER_BUBBLE_TRAIT "leaper-bubble"
diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm
index de8e170d4db26..bd77f0b85bb23 100644
--- a/code/_globalvars/traits.dm
+++ b/code/_globalvars/traits.dm
@@ -139,6 +139,13 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_DOOR_PRYER" = TRAIT_DOOR_PRYER,
"TRAIT_FISH_SAFE_STORAGE" = TRAIT_FISH_SAFE_STORAGE,
"TRAIT_FISH_CASE_COMPATIBILE" = TRAIT_FISH_CASE_COMPATIBILE
+ ),
+ /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
)
))
@@ -151,3 +158,25 @@ 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 4c0b708a0be17..b884e4ab248b9 100644
--- a/code/datums/components/caltrop.dm
+++ b/code/datums/components/caltrop.dm
@@ -55,7 +55,7 @@
if(!(flags & CALTROP_BYPASS_SHOES) && (H.shoes || feetCover))
return
- if((H.movement_type & FLYING) || (H.body_position == LYING_DOWN)|| H.buckled)
+ if((H.movement_type & (FLYING|FLOATING)) || (H.body_position == LYING_DOWN)|| H.buckled)
return
var/damage = rand(min_damage, max_damage)
diff --git a/code/datums/components/chasm.dm b/code/datums/components/chasm.dm
index 2838e70c19450..f0423eab57bbd 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/elements/movetype_handler.dm b/code/datums/elements/movetype_handler.dm
new file mode 100644
index 0000000000000..4c3cdec336e14
--- /dev/null
+++ b/code/datums/elements/movetype_handler.dm
@@ -0,0 +1,107 @@
+/**
+ * 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
+ RegisterSignals(movable_target, GLOB.movement_type_addtrait_signals, .proc/on_movement_type_trait_gain)
+ RegisterSignals(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, GLOB.movement_type_addtrait_signals)
+ UnregisterSignal(source, GLOB.movement_type_removetrait_signals)
+ UnregisterSignal(source, SIGNAL_ADDTRAIT(TRAIT_NO_FLOATING_ANIM))
+ UnregisterSignal(source, SIGNAL_REMOVETRAIT(TRAIT_NO_FLOATING_ANIM))
+ UnregisterSignal(source, 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)
+ 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 ef28dc34e9189..0b5be56586805 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -38,8 +38,13 @@
var/datum/movement_packet/move_packet
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
@@ -665,14 +670,6 @@
Moved(oldloc, NONE, TRUE)
-///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() below
//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting
@@ -908,8 +905,8 @@
var/matrix/initial_transform = matrix(transform)
var/matrix/rotated_transform = transform.Turn(rand(13,17) * 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
@@ -1008,17 +1005,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 72188002f4287..c67151e3a4ccc 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
@@ -153,10 +157,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)
+
/atom/movable/proc/unbuckle_all_mobs(force=FALSE)
if(!has_buckled_mobs())
diff --git a/code/game/objects/structures/life_candle.dm b/code/game/objects/structures/life_candle.dm
index 83a562ace450b..40a7079e5a7de 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
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
+ if(!linked_minds.len)
+ ADD_TRAIT(src, TRAIT_MOVE_FLOATING, LIFECANDLE_TRAIT)
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 c77f6d58ce261..b4cac583e2998 100644
--- a/code/modules/admin/verbs/randomverbs.dm
+++ b/code/modules/admin/verbs/randomverbs.dm
@@ -1213,6 +1213,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 d2e8650552041..7007f73a83b67 100644
--- a/code/modules/antagonists/blob/blob_mobs.dm
+++ b/code/modules/antagonists/blob/blob_mobs.dm
@@ -107,7 +107,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 = HOSTILE_SPAWN
diff --git a/code/modules/antagonists/clock_cult/mobs/clockwork_marauder.dm b/code/modules/antagonists/clock_cult/mobs/clockwork_marauder.dm
index 3e0490b4b8b51..de535c8d1b666 100644
--- a/code/modules/antagonists/clock_cult/mobs/clockwork_marauder.dm
+++ b/code/modules/antagonists/clock_cult/mobs/clockwork_marauder.dm
@@ -16,7 +16,7 @@ GLOBAL_LIST_EMPTY(clockwork_marauders)
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 = INFINITY
- movement_type = FLYING
+ is_flying_animal = TRUE
move_resist = MOVE_FORCE_OVERPOWERING
mob_size = MOB_SIZE_LARGE
pass_flags = PASSTABLE
diff --git a/code/modules/antagonists/clock_cult/mobs/eminence.dm b/code/modules/antagonists/clock_cult/mobs/eminence.dm
index 5dbc2d84ff6ce..da36f6bc44349 100644
--- a/code/modules/antagonists/clock_cult/mobs/eminence.dm
+++ b/code/modules/antagonists/clock_cult/mobs/eminence.dm
@@ -24,7 +24,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/antagonists/clock_cult/traps/receivers/skewer.dm b/code/modules/antagonists/clock_cult/traps/receivers/skewer.dm
index d951eb4e22e5f..d9d66ea55c9f4 100644
--- a/code/modules/antagonists/clock_cult/traps/receivers/skewer.dm
+++ b/code/modules/antagonists/clock_cult/traps/receivers/skewer.dm
@@ -27,7 +27,7 @@
var/target_stabbed = FALSE
density = TRUE
for(var/mob/living/M in get_turf(src))
- if(M.incorporeal_move || M.is_flying())
+ if(M.incorporeal_move || M.movement_type & (FLOATING|FLYING))
continue
if(buckle_mob(M, TRUE))
target_stabbed = TRUE
diff --git a/code/modules/antagonists/clock_cult/traps/senders/pressure_sensor.dm b/code/modules/antagonists/clock_cult/traps/senders/pressure_sensor.dm
index 159afb8ace32e..e4b55981a9328 100644
--- a/code/modules/antagonists/clock_cult/traps/senders/pressure_sensor.dm
+++ b/code/modules/antagonists/clock_cult/traps/senders/pressure_sensor.dm
@@ -34,7 +34,7 @@
if(istype(M))
if(is_servant_of_ratvar(M))
return
- if(M.incorporeal_move || M.is_flying())
+ if(M.incorporeal_move || M.movement_type & (FLOATING|FLYING))
return
else
return
diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm
index 4dcd3d8d278b0..eabcfff265400 100644
--- a/code/modules/antagonists/revenant/revenant.dm
+++ b/code/modules/antagonists/revenant/revenant.dm
@@ -43,7 +43,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 | PASSMOB
diff --git a/code/modules/holoparasite/_holoparasite.dm b/code/modules/holoparasite/_holoparasite.dm
index 30c7e5f0eb9bf..1872d2191de10 100644
--- a/code/modules/holoparasite/_holoparasite.dm
+++ b/code/modules/holoparasite/_holoparasite.dm
@@ -25,7 +25,7 @@ GLOBAL_LIST_EMPTY_TYPED(holoparasites, /mob/living/simple_animal/hostile/holopar
light_on = FALSE
a_intent = INTENT_HARM
stop_automated_movement = TRUE
- movement_type = FLYING // Immunity to chasms and landmines, etc.
+ is_flying_animal = TRUE // Immunity to chasms and landmines, etc.
attack_sound = "punch"
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/mining/equipment/wormhole_jaunter.dm b/code/modules/mining/equipment/wormhole_jaunter.dm
index 2b01cd25a1ddd..5d06cca10e6b6 100644
--- a/code/modules/mining/equipment/wormhole_jaunter.dm
+++ b/code/modules/mining/equipment/wormhole_jaunter.dm
@@ -50,7 +50,7 @@
try_move_adjacent(J)
else
user.Paralyze(2 SECONDS, TRUE, TRUE) //Ignore stun immunity here, for their own good
- user.setMovetype(user.movement_type | FLOATING) //Prevents falling into chasm during delay, automatically removed upon movement
+ ADD_TRAIT(user, TRAIT_MOVE_FLOATING, "jaunter") //Prevents falling into chasm during delay, automatically removed upon movement
addtimer(CALLBACK(J, TYPE_PROC_REF(/atom, attackby), null, user), 1 SECONDS) //Forcibly teleport them away from the chasm after a brief dramatic delay
playsound(src,'sound/effects/sparks4.ogg',50,1)
qdel(src)
diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm
index e853c16df621a..2101a9406c67f 100644
--- a/code/modules/mob/living/basic/basic.dm
+++ b/code/modules/mob/living/basic/basic.dm
@@ -140,7 +140,6 @@
icon = initial(icon)
icon_state = icon_living
density = initial(density)
- setMovetype(initial(movement_type))
/mob/living/basic/proc/melee_attack(atom/target)
src.face_atom(target)
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 1b024ec6aa2b5..96cb3c54cc149 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
@@ -87,8 +87,3 @@
if(leaping) //check that toggles out of leaping mode if the alien gets hit or otherwise interrupted
leaping = FALSE
update_icons()
-
-/mob/living/carbon/alien/humanoid/float(on)
- if(leaping)
- return
- return ..()
diff --git a/code/modules/mob/living/carbon/carbon_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm
index 33b556e736336..dcf4439f0018a 100644
--- a/code/modules/mob/living/carbon/carbon_movement.dm
+++ b/code/modules/mob/living/carbon/carbon_movement.dm
@@ -56,17 +56,17 @@
if(!usable_legs && !(movement_type & (FLYING | FLOATING)))
ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
+/mob/living/carbon/on_movement_type_flag_enabled(datum/source, flag)
+ var/old_movetype = movement_type
+ . = ..()
+ 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/setMovetype(newval)
+/mob/living/carbon/on_movement_type_flag_disabled(datum/source, flag)
. = ..()
- 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) && !(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/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 7372fb37f1ef1..090928d713575 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -811,11 +811,6 @@
/mob/living/carbon/human/can_hold_items()
return TRUE
-/mob/living/carbon/human/update_gravity(has_gravity,override = 0)
- if(dna && 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 = 0, stun = 1, distance = 0, message = 1, toxic = 0)
if(blood && (NOBLOOD in dna.species.species_traits))
if(message)
diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm
index 8874bad02caff..ec07a513434e7 100644
--- a/code/modules/mob/living/carbon/human/species.dm
+++ b/code/modules/mob/living/carbon/human/species.dm
@@ -101,7 +101,6 @@ GLOBAL_LIST_EMPTY(features_by_species)
var/obj/item/organ/liver/mutantliver
var/obj/item/organ/stomach/mutantstomach
- var/override_float = FALSE
//Bitflag that controls what in game ways can select this species as a spawnable source
//Think magic mirror and pride mirror, slime extract, ERT etc, see defines
@@ -2346,19 +2345,17 @@ GLOBAL_LIST_EMPTY(features_by_species)
//UNSAFE PROC, should only be called through the Activate or other sources that check for CanFly
/datum/species/proc/toggle_flight(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_MOVE_FLYING, SPECIES_FLIGHT_TRAIT)
H.pass_flags |= PASSTABLE
if(("wings" in H.dna.species.mutant_bodyparts) || ("moth_wings" in H.dna.species.mutant_bodyparts))
H.Togglewings()
else
stunmod *= 0.5
speedmod += 0.35
- H.setMovetype(H.movement_type & ~FLYING)
- override_float = FALSE
+ REMOVE_TRAIT(H, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT)
H.pass_flags &= ~PASSTABLE
if(("wingsopen" in H.dna.species.mutant_bodyparts) || ("moth_wingsopen" in H.dna.species.mutant_bodyparts))
H.Togglewings()
diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm
index 505201504141c..a02ae4866236f 100644
--- a/code/modules/mob/living/carbon/update_icons.dm
+++ b/code/modules/mob/living/carbon/update_icons.dm
@@ -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().
UPDATE_OO_IF_PRESENT
/mob/living/carbon
diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm
index 108570a584da3..87efcb9654173 100644
--- a/code/modules/mob/living/init_signals.dm
+++ b/code/modules/mob/living/init_signals.dm
@@ -38,6 +38,9 @@
SIGNAL_REMOVETRAIT(TRAIT_NODEATH),
), PROC_REF(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)
SIGNAL_HANDLER
@@ -173,3 +176,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 f3e618c29e544..b98d460e29a1f 100644
--- a/code/modules/mob/living/life.dm
+++ b/code/modules/mob/living/life.dm
@@ -7,9 +7,6 @@
SEND_SIGNAL(src, COMSIG_LIVING_LIFE, delta_time, times_fired)
- if((movement_type & FLYING) && !(movement_type & FLOATING)) //TODO: Better floating
- float(on = TRUE)
-
if (notransform)
return
if(!loc)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index caf4b857864ca..6b0b1c9268d8b 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -25,6 +25,10 @@
//color correction
RegisterSignal(src, COMSIG_MOVABLE_ENTERED_AREA, PROC_REF(apply_color_correction))
+/mob/living/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/movetype_handler)
+
/mob/living/prepare_huds()
..()
prepare_data_huds()
@@ -932,10 +936,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")
@@ -944,24 +949,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 && buckled.anchored))
- fixed = 1
- if(on && !(movement_type & FLOATING) && !fixed)
- animate(src, pixel_y = base_pixel_y + 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
- animate(pixel_y = base_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)
@@ -1030,7 +1023,7 @@
var/matrix/reset_matrix = matrix()
reset_matrix.Turn(-5)
// Offset animation
- animate(src, time = 1, pixel_x = rand(-2, 2), pixel_y = rand(-1, 1), easing = ELASTIC_EASING, flags = ANIMATION_RELATIVE)
+ animate(src, time = 1, pixel_x = rand(-2, 2), pixel_y = rand(-1, 1), easing = ELASTIC_EASING, flags = ANIMATION_RELATIVE|ANIMATION_PARALLEL)
for (var/i in 1 to 4)
var/dx = rand(-4, 2)
var/dy = rand(-4, 2)
@@ -1048,11 +1041,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.return_temperature() : T0C
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index a34ecf210817b..3e02d5a4e4875 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -450,7 +450,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.
/mob/living/extrapolator_act(mob/living/user, obj/item/extrapolator/extrapolator, dry_run = FALSE)
. = ..()
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index 0517752446447..fff6e77656b29 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -27,7 +27,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 fe890e42c6f3e..841c87de1c948 100644
--- a/code/modules/mob/living/simple_animal/friendly/butterfly.dm
+++ b/code/modules/mob/living/simple_animal/friendly/butterfly.dm
@@ -17,7 +17,7 @@
friendly_verb_continuous = "nudges"
friendly_verb_simple = "nudge"
density = FALSE
- movement_type = FLYING
+ is_flying_animal = TRUE
pass_flags = PASSTABLE | PASSMOB
ventcrawler = VENTCRAWLER_ALWAYS
mob_size = MOB_SIZE_TINY
diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm
index f83fc638d85e9..57fecbb17cdd1 100644
--- a/code/modules/mob/living/simple_animal/hostile/bees.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bees.dm
@@ -44,7 +44,7 @@
density = FALSE
mob_size = MOB_SIZE_TINY
mob_biotypes = list(MOB_ORGANIC, MOB_BUG)
- movement_type = FLYING
+ is_flying_animal = TRUE
gold_core_spawnable = HOSTILE_SPAWN
search_objects = 1 //have to find those plant trays!
ventcrawler = VENTCRAWLER_ALWAYS
diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm
index a88869e9eedac..b6679739954fb 100644
--- a/code/modules/mob/living/simple_animal/hostile/carp.dm
+++ b/code/modules/mob/living/simple_animal/hostile/carp.dm
@@ -38,7 +38,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 38eff231950a5..152b4e66c8109 100644
--- a/code/modules/mob/living/simple_animal/hostile/eyeballs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/eyeballs.dm
@@ -23,7 +23,7 @@
attack_verb_continuous = "blinks at"
attack_verb_simple = "blink at"
attack_sound = 'sound/weapons/pierce.ogg'
- movement_type = FLYING
+ is_flying_animal = TRUE
faction = list("spooky")
del_on_death = TRUE
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 e12c6e9011f98..185508e1af543 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm
@@ -81,13 +81,17 @@
/obj/structure/leaper_bubble/Initialize(mapload)
. = ..()
- float(on = TRUE)
QDEL_IN(src, 100)
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
)
AddElement(/datum/element/connect_loc, loc_connections)
+/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, 1, -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 1ae92cf7d81dc..fb555e75d5c83 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -58,6 +58,10 @@ Difficulty: Very Hard
small_sprite_type = /datum/action/small_sprite/megafauna/colossus
var/invulnerable_finale = FALSE
+/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'
@@ -709,7 +713,7 @@ GLOBAL_DATUM(blackbox, /obj/machinery/smartfridge/black_box)
friendly_verb_continuous = "mends"
friendly_verb_simple = "mend"
density = FALSE
- movement_type = FLYING
+ is_flying_animal = TRUE
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
ventcrawler = VENTCRAWLER_ALWAYS
mob_size = MOB_SIZE_TINY
@@ -724,7 +728,6 @@ GLOBAL_DATUM(blackbox, /obj/machinery/smartfridge/black_box)
faction = list("neutral")
del_on_death = TRUE
unsuitable_atmos_damage = 0
- movement_type = FLYING
minbodytemp = 0
maxbodytemp = 1500
obj_damage = 0
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 90b948f3e0d15..8cfeb02215ed7 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm
@@ -12,7 +12,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 = HARD_CRIT
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 2617d977807f9..a7731786fb78a 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
@@ -79,7 +79,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
loot = list()
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 a2d214b92fa6d..483fad157364a 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 = list(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 1f2e7a54654fb..6f0bdfcf37f7e 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
@@ -195,7 +195,7 @@
icon_state = "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 f0af72f7c10dc..674fba7ba4458 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
@@ -72,7 +72,7 @@
speed = 3
maxHealth = 1
health = 1
- movement_type = FLYING
+ is_flying_animal = TRUE
melee_damage = 2
attack_verb_continuous = "slashes"
attack_verb_simple = "slash"
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 2e7f3ee0990d8..73c3c5bc50c8b 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/bat.dm
@@ -27,7 +27,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 f5149af8826f2..597842e87db3a 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm
@@ -30,7 +30,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
var/ghost_hair_style
diff --git a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
index 661717fe758a5..327937ca85e11 100644
--- a/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
+++ b/code/modules/mob/living/simple_animal/hostile/space_dragon.dm
@@ -55,7 +55,7 @@
maxbodytemp = 1500
faction = list("carp")
pressure_resistance = 200
- movement_type = FLYING | FLOATING // fly so you can move without gravity, float so no animation applies
+ is_flying_animal = TRUE | FLOATING // fly so you can move without gravity, float so no animation applies
/// How much endlag using Wing Gust should apply. Each use of wing gust increments this, and it decreases over time.
var/tiredness = 0
/// A multiplier to how much each use of wing gust should add to the tiredness variable. Set to 5 if the current rift is destroyed.
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index 19ff51965dd2b..dcc80d8464af9 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -292,7 +292,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 = TRUE
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 fb9041a2c67f3..6b88ae9f0c990 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -67,7 +67,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
chat_color = "#A6E398"
mobchatspan = "curator"
diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm
index 8bc330969caaf..fc0933635fbed 100644
--- a/code/modules/mob/living/simple_animal/shade.dm
+++ b/code/modules/mob/living/simple_animal/shade.dm
@@ -30,7 +30,7 @@
status_flags = 0
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 89fab3bd63b31..bc89221e8e418 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -99,6 +99,9 @@
var/dextrous = FALSE //If the creature has, and can use, hands
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
+
var/AIStatus = AI_ON //The Status of our AI, can be changed via toggle_ai(togglestatus) 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/can_have_ai = TRUE //once we have become sentient, we can never go back
@@ -141,6 +144,8 @@
. = ..()
if(dextrous)
AddComponent(/datum/component/personal_crafting)
+ if(is_flying_animal)
+ ADD_TRAIT(src, TRAIT_MOVE_FLYING, ROUNDSTART_TRAIT)
if(discovery_points)
AddComponent(/datum/component/discoverable, discovery_points, get_discover_id = CALLBACK(src, PROC_REF(get_discovery_id)))
@@ -159,6 +164,16 @@
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/examine(mob/user)
. = ..()
if(stat == DEAD)
@@ -379,7 +394,6 @@
new i(loc)
/mob/living/simple_animal/death(gibbed)
- movement_type &= ~FLYING
if(nest)
nest.spawned_mobs -= src
nest = null
@@ -396,6 +410,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)
@@ -437,7 +453,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
set waitfor = 0
diff --git a/code/modules/mob/living/ventcrawling.dm b/code/modules/mob/living/ventcrawling.dm
index 0fd5f65ae1d0e..34a30f59b160a 100644
--- a/code/modules/mob/living/ventcrawling.dm
+++ b/code/modules/mob/living/ventcrawling.dm
@@ -102,7 +102,7 @@ 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()
@@ -110,7 +110,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
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 db43fd25105f0..b272ad7106b3e 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1249,12 +1249,6 @@
/mob/proc/set_nutrition(var/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 f9c46bdedf7c4..209d811c6726c 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -520,13 +520,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(mob/M = src)
- if(M.movement_type & FLYING)
- return 1
- else
- return 0
-
///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/surgery/organs/augments_chest.dm b/code/modules/surgery/organs/augments_chest.dm
index eca93f0723ede..5edb0bbf147ad 100644
--- a/code/modules/surgery/organs/augments_chest.dm
+++ b/code/modules/surgery/organs/augments_chest.dm
@@ -182,7 +182,7 @@
var/turf/T = get_turf(owner)
if(!T) // No more runtimes from being stuck in nullspace.
return 0
- if(owner.is_flying() && owner.has_gravity())
+ if((owner.movement_type & (FLOATING|FLYING)) && owner.has_gravity())
return 0
// Priority 1: use air from environment.
var/datum/gas_mixture/environment = T.return_air()