[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>
This commit is contained in:
SkyratBot
2020-12-09 23:43:42 +01:00
committed by GitHub
co-authored by Ghom
parent e976e1345e
commit 2ee5d422ae
31 changed files with 226 additions and 111 deletions
+11
View File
@@ -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
+39 -4
View File
@@ -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"
+17
View File
@@ -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)
+1
View File
@@ -85,6 +85,7 @@ SUBSYSTEM_DEF(throwing)
/datum/thrownthing/Destroy()
SSthrowing.processing -= thrownthing
thrownthing.floating_anim_check()
thrownthing.throwing = null
thrownthing = null
target = null
+1 -1
View File
@@ -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
+1 -3
View File
@@ -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))
+1 -1
View File
@@ -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)
+77 -19
View File
@@ -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.
+4
View File
@@ -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(.)
@@ -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 ..()
+1 -1
View File
@@ -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
+5 -1
View File
@@ -30,15 +30,19 @@
return
if(!user.mind)
return
var/old_len = linked_minds.len
if(user.mind in linked_minds)
user.visible_message("<span class='notice'>[user] reaches out and pinches the flame of [src].</span>", "<span class='warning'>You sever the connection between yourself and [src].</span>")
linked_minds -= user.mind
if(old_len)
REMOVE_TRAIT(src, TRAIT_MOVE_FLOATING, LIFECANDLE_TRAIT)
else
user.visible_message("<span class='notice'>[user] touches [src]. It seems to respond to [user.p_their()] presence!</span>", "<span class='warning'>You create a connection between you and [src].</span>")
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)
+5 -1
View File
@@ -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)
@@ -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..."
@@ -86,9 +86,3 @@
visible_message("<span class='danger'>[src] smashes into [hit_atom]!</span>", "<span class='alertalien'>[src] smashes into [hit_atom]!</span>")
Paralyze(40, ignore_canstun = TRUE)
/mob/living/carbon/alien/humanoid/float(on)
if(leaping)
return
..()
@@ -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
@@ -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]
@@ -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)
@@ -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()
-3
View File
@@ -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)
+27 -16
View File
@@ -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
@@ -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
@@ -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))
@@ -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"
@@ -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)
@@ -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
+2 -3
View File
@@ -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)
+4 -4
View File
@@ -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()
-8
View File
@@ -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()
+1 -1
View File
@@ -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()
@@ -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