mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 04:30:44 +01:00
[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:
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -85,6 +85,7 @@ SUBSYSTEM_DEF(throwing)
|
||||
|
||||
/datum/thrownthing/Destroy()
|
||||
SSthrowing.processing -= thrownthing
|
||||
thrownthing.floating_anim_check()
|
||||
thrownthing.throwing = null
|
||||
thrownthing = null
|
||||
target = null
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user