From 2ee5d422ae079ee62747e5ace1118d4bf02ebf20 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Wed, 9 Dec 2020 23:43:42 +0100 Subject: [PATCH] [MIRROR] Refactors how movetype flags are added and removed and the floating animation (#2096) * Refactors how movetype flags are added and removed and the floating animation (#54963) I wanted to refactor how movetype flags are added and removed into traits to prevent multiple sources of specific movement types from conflicting one other. I ended up also having to refactor the floating animation loop (the one that bobs up and down) code in the process. Why It's Good For The Game A way to avoid conflict from multiple sources of movement types. This also stops melee attacks, jitteriness and update_transform() from temporarily disabling the floating movetype bitflag altogether until the next life tick. Tested, but i'm pretty sure improvements could be made. Changelog cl fix: jitteriness, melee attack animations and resting/standing up should no longer momentarily remove the floating movement type. /cl * Refactors how movetype flags are added and removed and the floating animation Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com> --- code/__DEFINES/misc.dm | 11 +++ code/__DEFINES/traits.dm | 43 ++++++++- code/_globalvars/traits.dm | 17 ++++ code/controllers/subsystem/throwing.dm | 1 + code/datums/components/caltrop.dm | 2 +- code/datums/components/chasm.dm | 4 +- code/datums/components/slippery.dm | 2 +- code/game/atoms_movable.dm | 96 +++++++++++++++---- code/game/objects/buckling.dm | 4 + .../game/objects/items/stacks/sheets/glass.dm | 2 +- code/game/objects/items/tanks/jetpack.dm | 2 +- code/game/objects/structures/life_candle.dm | 6 +- code/modules/admin/verbs/randomverbs.dm | 6 +- code/modules/clothing/shoes/miscellaneous.dm | 1 - .../carbon/alien/humanoid/caste/hunter.dm | 6 -- .../mob/living/carbon/carbon_movement.dm | 21 ++-- .../mob/living/carbon/carbon_update_icons.dm | 2 +- code/modules/mob/living/carbon/human/human.dm | 5 - .../mob/living/carbon/human/species.dm | 13 ++- code/modules/mob/living/life.dm | 3 - code/modules/mob/living/living.dm | 43 +++++---- code/modules/mob/living/living_defense.dm | 1 - .../simple_animal/hostile/jungle/leaper.dm | 2 +- .../hostile/megafauna/colossus.dm | 9 +- .../hostile/megafauna/demonic_frost_miner.dm | 2 +- .../mob/living/simple_animal/simple_animal.dm | 8 +- 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 +- 31 files changed, 226 insertions(+), 111 deletions(-) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index d6f110b0d38..aedaa972ab4 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -540,3 +540,14 @@ GLOBAL_LIST_INIT(pda_styles, sortList(list(MONO, VT, ORBITRON, SHARE))) #define IGNORE_TARGET_LOC_CHANGE (1<<1) #define IGNORE_HELD_ITEM (1<<2) #define IGNORE_INCAPACITATED (1<<3) + +// Floating status defines. Used for the floating animation loop code. +///The mob will never ever bob up and down when floating. (eg. Colossus, winged flying humanoids) +#define NEVER_FLOATING_ANIM -1 +///Isn't currently bobbing. +#define NO_FLOATING_ANIM 0 +///Is currently bobbing. +#define HAS_FLOATING_ANIM 1 +///The bobbing animation has been halted and will be updated by a timed callback. +#define UPDATE_FLOATING_ANIM 2 + diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 3a89453eee9..3621d0c0a8d 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)) { \ @@ -219,6 +219,35 @@ 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. + +/** + * Registers movement trait signals on the movable the first time the macro is used on it, + * These are necessary to add and remove bit flags, as well as the floating animation. + * Overall it's a better alternative than doing so on init for every movable. + */ +#define ADD_MOVE_TRAIT(AM, trait, source)\ + if(!AM.has_movement_type_signals){\ + if(!GLOB.movement_type_trait_add_signals){\ + GLOB.movement_type_trait_add_signals = list();\ + GLOB.movement_type_trait_remove_signals = list();\ + for(var/_trait in GLOB.movement_type_trait_to_flag){\ + GLOB.movement_type_trait_add_signals += SIGNAL_ADDTRAIT(_trait);\ + GLOB.movement_type_trait_remove_signals += SIGNAL_REMOVETRAIT(_trait)\ + };\ + };\ + AM.RegisterSignal(AM, GLOB.movement_type_trait_add_signals, /atom/movable/.proc/on_movement_type_trait_gain);\ + AM.RegisterSignal(AM, GLOB.movement_type_trait_remove_signals, /atom/movable/.proc/on_movement_type_trait_loss);\ + AM.has_movement_type_signals = TRUE\ + };\ + ADD_TRAIT(AM, trait, source) + +#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_UNSTOPPABLE "move_unstoppable" + //non-mob traits /// Used for limb-based paralysis, where replacing the limb will fix it. #define TRAIT_PARALYSIS "paralysis" @@ -357,6 +386,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 b502cfdaa6b..c40146daba9 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -168,6 +168,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_UNSTOPPABLE" = TRAIT_MOVE_UNSTOPPABLE ) )) @@ -180,3 +187,13 @@ 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_UNSTOPPABLE = UNSTOPPABLE + )) +GLOBAL_LIST(movement_type_trait_add_signals) +GLOBAL_LIST(movement_type_trait_remove_signals) diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm index e5d6b0bbd08..ee6cb105451 100644 --- a/code/controllers/subsystem/throwing.dm +++ b/code/controllers/subsystem/throwing.dm @@ -85,6 +85,7 @@ SUBSYSTEM_DEF(throwing) /datum/thrownthing/Destroy() SSthrowing.processing -= thrownthing + thrownthing.floating_anim_check() thrownthing.throwing = null thrownthing = null target = null diff --git a/code/datums/components/caltrop.dm b/code/datums/components/caltrop.dm index b6275ac7393..bd00761fea8 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/game/atoms_movable.dm b/code/game/atoms_movable.dm index 6c83bc2000e..3d5a3f20f28 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -34,8 +34,25 @@ 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. + * Should be added/removed through the ADD_MOVE_TRAIT and REMOVE_TRAIT (and variant) macros. + */ var/movement_type = GROUND + /// Whether the movable has movement_type signals registered or not. See the ADD_MOVE_TRAIT macro on __DEFINES/traits.dm + var/has_movement_type_signals = FALSE + /// Whether the movable is floating, not floating or is queued for update. + var/floating_anim_status = NO_FLOATING_ANIM + /** + * Stores the timer id for the floating anim update. + * Used to avoid the timed event from being overridden by others that would run sooner. + */ + var/floating_halt_timerid + /// Stores the timer id for the next half of the floating anim loop + var/floating_anim_timerid + var/atom/movable/pulling var/grab_state = 0 var/throwforce = 0 @@ -210,6 +227,15 @@ if(NAMEOF(src, glide_size)) set_glide_size(var_value) . = TRUE + if(NAMEOF(src, floating_anim_status)) + if(var_value != floating_anim_status) + switch(var_value) + if(HAS_FLOATING_ANIM) + floating_anim_status = HAS_FLOATING_ANIM + do_floating_anim() + else + halt_floating_anim(var_value) + . = TRUE if(!isnull(.)) datum_flags |= DF_VAR_EDITED @@ -593,14 +619,22 @@ var/atom/movable/AM = item AM.onTransitZ(old_z,new_z) +/// Called when movement_type trait is added to the mob. +/atom/movable/proc/on_movement_type_trait_gain(datum/source, trait) + SIGNAL_HANDLER + var/old_movement_type = movement_type + movement_type |= GLOB.movement_type_trait_to_flag[trait] + if(!(old_movement_type & (FLOATING|FLYING)) && (trait == TRAIT_MOVE_FLYING || trait == TRAIT_MOVE_FLOATING)) + floating_anim_check() -///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 when a movement_type trait is removed from the mob. +/atom/movable/proc/on_movement_type_trait_loss(datum/source, trait) + SIGNAL_HANDLER + var/flag = GLOB.movement_type_trait_to_flag[trait] + if(!(initial(movement_type) & flag)) + movement_type &= ~(GLOB.movement_type_trait_to_flag[trait]) + if(trait == TRAIT_MOVE_FLYING || trait == TRAIT_MOVE_FLOATING && !(movement_type & (FLOATING|FLYING))) + halt_floating_anim(NO_FLOATING_ANIM) /** * Called whenever an object moves and by mobs when they attempt to move themselves through space @@ -740,6 +774,7 @@ if(pulledby) pulledby.stop_pulling() + halt_floating_anim(NO_FLOATING_ANIM, animate = !spin) throwing = TT if(spin) SpinAnimation(5, 1) @@ -827,6 +862,7 @@ if(A == src) return //don't do an animation if attacking self + halt_floating_anim(animate = FALSE) var/pixel_x_diff = 0 var/pixel_y_diff = 0 var/turn_dir = 1 @@ -902,18 +938,40 @@ 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) +///The bouncing animation loop that stops once halt_floating_anim is called. +/atom/movable/proc/do_floating_anim(shift = 2) + if(floating_anim_status == HAS_FLOATING_ANIM) + animate(src, pixel_y = pixel_y + shift, time = 1 SECONDS) + floating_anim_timerid = addtimer(CALLBACK(src, .proc/do_floating_anim, -shift), 1.1 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE) +///Restarts the floating animation if conditions are met. +/atom/movable/proc/floating_anim_check(timed = FALSE) + if(timed) + floating_halt_timerid = null + if(floating_anim_status == HAS_FLOATING_ANIM || floating_anim_status == NEVER_FLOATING_ANIM || floating_halt_timerid) + return + if(throwing || !(movement_type & (FLOATING|FLYING))) + floating_anim_status = NO_FLOATING_ANIM + else + floating_anim_status = HAS_FLOATING_ANIM + do_floating_anim() + +/// Stops the floating anim. If the update arg is TRUE, floating_anim_check(TRUE) will be a invoked after a set time indicated by the timer arg. +/atom/movable/proc/halt_floating_anim(new_status = UPDATE_FLOATING_ANIM, timer = 1 SECONDS, animate = TRUE) + if(floating_anim_status == HAS_FLOATING_ANIM) + if(animate) + animate(src, pixel_y = base_pixel_y, time = 1 SECONDS) + else + pixel_y = base_pixel_y + if(new_status == UPDATE_FLOATING_ANIM) + if(!floating_halt_timerid || timeleft(floating_halt_timerid) < timer) + floating_halt_timerid = addtimer(CALLBACK(src, .proc/floating_anim_check, TRUE), timer, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_STOPPABLE|TIMER_NO_HASH_WAIT) + else if(floating_anim_timerid) + deltimer(floating_anim_timerid) + floating_anim_timerid = null + + if(floating_anim_status != NEVER_FLOATING_ANIM) + floating_anim_status = new_status /* 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 5187ca21789..10029c7318a 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -100,6 +100,8 @@ if(!check_loc && M.loc != loc) M.forceMove(loc) + if(anchored) + M.halt_floating_anim(NO_FLOATING_ANIM) M.set_buckled(src) M.setDir(dir) buckled_mobs |= M @@ -138,6 +140,8 @@ 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) + buckled_mob.floating_anim_check() SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force) post_unbuckle_mob(.) 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..d4ef0b6c3e3 100644 --- a/code/game/objects/structures/life_candle.dm +++ b/code/game/objects/structures/life_candle.dm @@ -30,15 +30,19 @@ return if(!user.mind) return + var/old_len = linked_minds.len 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(old_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(!old_len) + ADD_MOVE_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 2a89c6c2342..97d09c63d9b 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1475,7 +1475,11 @@ 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. - ADD_TRAIT(D,chosen_trait,source) + if(GLOB.movement_type_trait_to_flag[chosen_trait]) //big damn exception. + var/atom/movable/AM = D + ADD_MOVE_TRAIT(AM, chosen_trait,source) + else + 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") if(!specific) diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 3c8e4fc0f57..8c5543d05e5 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -375,7 +375,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_movement.dm b/code/modules/mob/living/carbon/carbon_movement.dm index 7f65b79ddca..a4c53b77053 100644 --- a/code/modules/mob/living/carbon/carbon_movement.dm +++ b/code/modules/mob/living/carbon/carbon_movement.dm @@ -59,17 +59,18 @@ if(!usable_legs && !(movement_type & (FLYING | FLOATING))) ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT) - -/mob/living/carbon/setMovetype(newval) +/// Called when movement_type trait is added to the mob. +/mob/living/carbon/on_movement_type_trait_gain(datum/source, trait) + 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((trait == TRAIT_MOVE_FLOATING || trait == TRAIT_MOVE_FLYING) && !(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_trait_loss(datum/source, trait) + . = ..() + if((trait == TRAIT_MOVE_FLOATING || trait == TRAIT_MOVE_FLYING) && !(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..859b5432b87 100644 --- a/code/modules/mob/living/carbon/carbon_update_icons.dm +++ b/code/modules/mob/living/carbon/carbon_update_icons.dm @@ -21,8 +21,8 @@ resize = RESIZE_DEFAULT_SIZE if(changed) + halt_floating_anim(animate = FALSE) 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 c0f4a19ac18..53cd91f3c8c 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -901,11 +901,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 3de8c9d5fed..459b0f2de1e 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,19 @@ 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 + H.halt_floating_anim(NEVER_FLOATING_ANIM) + ADD_MOVE_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 + H.floating_anim_status = initial(H.floating_anim_status) + H.floating_anim_check() + REMOVE_TRAIT(H, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT) passtable_off(H, SPECIES_TRAIT) H.CloseWings() 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 50168b3b8a5..4a71393d5ba 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -9,6 +9,8 @@ diag_hud.add_to_hud(src) faction += "[REF(src)]" GLOB.mob_living_list += src + if(movement_type & (FLYING|FLOATING) && floating_anim_status != NEVER_FLOATING_ANIM) + floating_anim_check() /mob/living/prepare_huds() ..() @@ -942,10 +944,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 +957,32 @@ 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) + if(!was_weightless) + ADD_MOVE_TRAIT(src, TRAIT_MOVE_FLOATING, NO_GRAVITY_TRAIT) -/mob/living/float(on) - if(throwing) +/mob/living/floating_anim_check(timed = FALSE) + if(timed) + floating_halt_timerid = null + if(floating_anim_status == HAS_FLOATING_ANIM || floating_anim_status == NEVER_FLOATING_ANIM || floating_halt_timerid) 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(throwing || !(movement_type & (FLOATING|FLYING)) || buckled?.anchored) + floating_anim_status = NO_FLOATING_ANIM + else + floating_anim_status = HAS_FLOATING_ANIM + do_floating_anim() + +/mob/living/halt_floating_anim(new_status = UPDATE_FLOATING_ANIM, timer = 1 SECONDS, animate = TRUE) + if(floating_anim_status == HAS_FLOATING_ANIM) + if(animate) + animate(src, pixel_y = base_pixel_y + body_position_pixel_y_offset, time = 1 SECONDS) + else + pixel_y = base_pixel_y + body_position_pixel_y_offset + floating_anim_status = NO_FLOATING_ANIM //only stops the parent call from affecting nullifying our pixel y offset. + ..() // 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) @@ -1062,6 +1073,7 @@ step_towards(src,S) /mob/living/proc/do_jitter_animation(jitteriness) + halt_floating_anim(TRUE, 1.5 SECONDS, FALSE) //the time of the jitter animation plus 0.1 var/amplitude = min(4, (jitteriness/100) + 1) var/pixel_x_diff = rand(-amplitude, amplitude) var/pixel_y_diff = rand(-amplitude/3, amplitude/3) @@ -1069,7 +1081,6 @@ 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(). /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 bdde3a402ee..afa1058ee8c 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/hostile/jungle/leaper.dm b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm index cb5d9e39b82..dc0ce6b72b9 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm @@ -81,8 +81,8 @@ /obj/structure/leaper_bubble/Initialize() . = ..() - INVOKE_ASYNC(src, /atom/movable.proc/float, TRUE) QDEL_IN(src, 100) + ADD_MOVE_TRAIT(src, TRAIT_MOVE_FLOATING, LEAPER_BUBBLE_TRAIT) /obj/structure/leaper_bubble/Destroy() new /obj/effect/temp_visual/leaper_projectile_impact(get_turf(src)) 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 1d86c07b2c3..5ef26fb72fd 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -42,6 +42,7 @@ ranged = TRUE pixel_x = -32 base_pixel_x = -32 + floating_anim_status = NEVER_FLOATING_ANIM //we don't want this guy to float, messes up his animations del_on_death = TRUE gps_name = "Angelic Signal" achievement_type = /datum/award/achievement/boss/colossus_kill @@ -250,14 +251,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" 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 ad6d89ee28d..4dd2f2d0174 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_MOVE_TRAIT(src, TRAIT_MOVE_FLYING, FROSTMINER_ENRAGE_TRAIT) enraging = FALSE adjustHealth(-maxHealth) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index e4f244777ef..397808a0849 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -449,7 +449,9 @@ new i(loc) /mob/living/simple_animal/death(gibbed) - movement_type &= ~FLYING + if(!HAS_TRAIT(src, TRAIT_MOVE_FLYING)) //Has no extrinsic source of flight + movement_type &= ~FLYING + halt_floating_anim(NO_FLOATING_ANIM) if(nest) nest.spawned_mobs -= src nest = null @@ -507,7 +509,9 @@ icon = initial(icon) icon_state = icon_living density = initial(density) - setMovetype(initial(movement_type)) + if(initial(movement_type) & (FLYING)) //regain its intrisic flight + movement_type |= FLYING + floating_anim_check() /mob/living/simple_animal/proc/make_babies() // <3 <3 <3 diff --git a/code/modules/mob/living/ventcrawling.dm b/code/modules/mob/living/ventcrawling.dm index 4585247d389..60dfe364c50 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_MOVE_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 550e57e4051..35b8e591ba6 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1291,13 +1291,13 @@ /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 +/mob/on_movement_type_trait_gain(datum/source, trait) . = ..() - if(isnull(.)) - return update_movespeed(FALSE) +/mob/on_movement_type_trait_loss(datum/source, trait) + . = ..() + update_movespeed(FALSE) /mob/proc/update_equipment_speed_mods() var/speedies = equipped_speed_mods() diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 12fb1279b47..4402ea86c5c 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -441,14 +441,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 564173d14ee..1de54cdea32 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -898,7 +898,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