[MIRROR] Refactors how movetypes are added and removed, No timers this time. (#2358)

* Refactors how movetypes are added and removed, No timers this time. (#55444)

* Refactors how movetypes are added and removed, No timers this time.

Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
This commit is contained in:
SkyratBot
2020-12-29 02:39:03 +00:00
committed by GitHub
co-authored by Ghom
parent b7f50181ca
commit 94ed7ed0f1
53 changed files with 302 additions and 150 deletions
+8
View File
@@ -887,6 +887,14 @@
///from base of datum/component/two_handed/proc/unwield(mob/living/carbon/user): (/mob/user)
#define COMSIG_TWOHANDED_UNWIELD "twohanded_unwield"
// /datum/element/movetype_handler signals
/// Called when the floating anim has to be temporarily stopped and restarted later: (timer)
#define COMSIG_PAUSE_FLOATING_ANIM "pause_floating_anim"
/// From base of datum/element/movetype_handler/on_movement_type_trait_gain: (flag)
#define COMSIG_MOVETYPE_FLAG_ENABLED "movetype_flag_enabled"
/// From base of datum/element/movetype_handler/on_movement_type_trait_loss: (flag)
#define COMSIG_MOVETYPE_FLAG_DISABLED "movetype_flag_disabled"
// /datum/action signals
///from base of datum/action/proc/Trigger(): (datum/action)
+19 -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)) { \
@@ -228,6 +228,15 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_KNOW_CYBORG_WIRES "know_cyborg_wires"
#define TRAIT_KNOW_ENGI_WIRES "know_engi_wires"
///Movement type traits for movables. See elements/movetype_handler.dm
#define TRAIT_MOVE_GROUND "move_ground"
#define TRAIT_MOVE_FLYING "move_flying"
#define TRAIT_MOVE_VENTCRAWLING "move_ventcrawling"
#define TRAIT_MOVE_FLOATING "move_floating"
#define TRAIT_MOVE_PHASING "move_phasing"
/// Disables the floating animation. See above.
#define TRAIT_NO_FLOATING_ANIM "no-floating-animation"
//non-mob traits
/// Used for limb-based paralysis, where replacing the limb will fix it.
#define TRAIT_PARALYSIS "paralysis"
@@ -369,6 +378,12 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define SLEEPING_CARP_TRAIT "sleeping_carp"
#define MADE_UNCLONEABLE "made-uncloneable"
#define TIMESTOP_TRAIT "timestop"
#define LIFECANDLE_TRAIT "lifecandle"
#define VENTCRAWLING_TRAIT "ventcrawling"
#define SPECIES_FLIGHT_TRAIT "species-flight"
#define FROSTMINER_ENRAGE_TRAIT "frostminer-enrage"
#define NO_GRAVITY_TRAIT "no-gravity"
#define LEAPER_BUBBLE_TRAIT "leaper-bubble"
#define STICKY_NODROP "sticky-nodrop" //sticky nodrop sounds like a bad soundcloud rapper's name
#define SKILLCHIP_TRAIT "skillchip"
#define PULLED_WHILE_SOFTCRIT_TRAIT "pulled-while-softcrit"
+28
View File
@@ -167,6 +167,13 @@ GLOBAL_LIST_INIT(traits_by_type, list(
),
/atom = list(
"TRAIT_KEEP_TOGETHER" = TRAIT_KEEP_TOGETHER
),
/atom/movable = list(
"TRAIT_MOVE_GROUND" = TRAIT_MOVE_GROUND,
"TRAIT_MOVE_FLYING" = TRAIT_MOVE_FLYING,
"TRAIT_MOVE_VENTCRAWLING" = TRAIT_MOVE_VENTCRAWLING,
"TRAIT_MOVE_FLOATING" = TRAIT_MOVE_FLOATING,
"TRAIT_MOVE_PHASING" = TRAIT_MOVE_PHASING
)
))
@@ -179,3 +186,24 @@ GLOBAL_LIST(trait_name_map)
for(var/tname in GLOB.traits_by_type[key])
var/val = GLOB.traits_by_type[key][tname]
.[val] = tname
GLOBAL_LIST_INIT(movement_type_trait_to_flag, list(
TRAIT_MOVE_GROUND = GROUND,
TRAIT_MOVE_FLYING = FLYING,
TRAIT_MOVE_VENTCRAWLING = VENTCRAWLING,
TRAIT_MOVE_FLOATING = FLOATING,
TRAIT_MOVE_PHASING = PHASING
))
GLOBAL_LIST_INIT(movement_type_addtrait_signals, set_movement_type_addtrait_signals())
GLOBAL_LIST_INIT(movement_type_removetrait_signals, set_movement_type_removetrait_signals())
/proc/set_movement_type_addtrait_signals(signal_prefix)
. = list()
for(var/trait in GLOB.movement_type_trait_to_flag)
. += SIGNAL_ADDTRAIT(trait)
/proc/set_movement_type_removetrait_signals(signal_prefix)
. = list()
for(var/trait in GLOB.movement_type_trait_to_flag)
. += SIGNAL_REMOVETRAIT(trait)
+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)
+109
View File
@@ -0,0 +1,109 @@
/**
* An element that enables and disables movetype bitflags as movetype traits are added and removed.
* It also handles the +2/-2 pixel y anim loop typical of mobs possessing the FLYING or FLOATING movetypes.
* This element is necessary for the TRAIT_MOVE_ traits to work correctly. So make sure to include it when
* manipulating those traits on non-living movables.
*/
/datum/element/movetype_handler
element_flags = ELEMENT_DETACH
var/list/attached_atoms = list()
var/list/paused_floating_anim_atoms = list()
/datum/element/movetype_handler/Attach(datum/target)
. = ..()
if(!ismovable(target))
return ELEMENT_INCOMPATIBLE
if(attached_atoms[target]) //Already attached.
return
var/atom/movable/movable_target = target
RegisterSignal(movable_target, GLOB.movement_type_addtrait_signals, .proc/on_movement_type_trait_gain)
RegisterSignal(movable_target, GLOB.movement_type_removetrait_signals, .proc/on_movement_type_trait_loss)
RegisterSignal(movable_target, SIGNAL_ADDTRAIT(TRAIT_NO_FLOATING_ANIM), .proc/on_no_floating_anim_trait_gain)
RegisterSignal(movable_target, SIGNAL_REMOVETRAIT(TRAIT_NO_FLOATING_ANIM), .proc/on_no_floating_anim_trait_loss)
RegisterSignal(movable_target, COMSIG_PAUSE_FLOATING_ANIM, .proc/pause_floating_anim)
attached_atoms[movable_target] = TRUE
if(movable_target.movement_type & (FLOATING|FLYING) && !HAS_TRAIT(movable_target, TRAIT_NO_FLOATING_ANIM))
float(movable_target)
/datum/element/movetype_handler/Detach(datum/source)
UnregisterSignal(source, list(
GLOB.movement_type_addtrait_signals,
GLOB.movement_type_removetrait_signals,
SIGNAL_ADDTRAIT(TRAIT_NO_FLOATING_ANIM),
SIGNAL_REMOVETRAIT(TRAIT_NO_FLOATING_ANIM),
COMSIG_PAUSE_FLOATING_ANIM
))
attached_atoms -= source
paused_floating_anim_atoms -= source
stop_floating(source)
return ..()
/// Called when a movement type trait is added to the movable. Enables the relative bitflag.
/datum/element/movetype_handler/proc/on_movement_type_trait_gain(atom/movable/source, trait)
SIGNAL_HANDLER
var/flag = GLOB.movement_type_trait_to_flag[trait]
if(source.movement_type & flag)
return
if(!(source.movement_type & (FLOATING|FLYING)) && (trait == TRAIT_MOVE_FLYING || trait == TRAIT_MOVE_FLOATING) && !paused_floating_anim_atoms[source] && !HAS_TRAIT(source, TRAIT_NO_FLOATING_ANIM))
float(source)
source.movement_type |= flag
SEND_SIGNAL(source, COMSIG_MOVETYPE_FLAG_ENABLED, flag)
/// Called when a movement type trait is removed from the movable. Disables the relative bitflag if it wasn't there in the compile-time bitfield.
/datum/element/movetype_handler/proc/on_movement_type_trait_loss(atom/movable/source, trait)
SIGNAL_HANDLER
var/flag = GLOB.movement_type_trait_to_flag[trait]
if(initial(source.movement_type) & flag)
return
source.movement_type &= ~flag
if((trait == TRAIT_MOVE_FLYING || trait == TRAIT_MOVE_FLOATING) && !(source.movement_type & (FLOATING|FLYING)))
stop_floating(source)
SEND_SIGNAL(source, COMSIG_MOVETYPE_FLAG_DISABLED, flag)
/// Called when the TRAIT_NO_FLOATING_ANIM trait is added to the movable. Stops it from bobbing up and down.
/datum/element/movetype_handler/proc/on_no_floating_anim_trait_gain(atom/movable/source, trait)
SIGNAL_HANDLER
stop_floating(source)
/// Called when the TRAIT_NO_FLOATING_ANIM trait is removed from the mob. Restarts the bobbing animation.
/datum/element/movetype_handler/proc/on_no_floating_anim_trait_loss(atom/movable/source, trait)
SIGNAL_HANDLER
if(source.movement_type & (FLOATING|FLYING) && !paused_floating_anim_atoms[source])
float(source)
///Pauses the floating animation for the duration of the timer... plus [tickrate - (world.time + timer) % tickrate] to be precise.
/datum/element/movetype_handler/proc/pause_floating_anim(atom/movable/source, timer)
SIGNAL_HANDLER
if(paused_floating_anim_atoms[source] < world.time + timer)
stop_floating(source)
if(!length(paused_floating_anim_atoms))
START_PROCESSING(SSdcs, src) //1 second tickrate.
paused_floating_anim_atoms[source] = world.time + timer
/datum/element/movetype_handler/process()
for(var/_paused in paused_floating_anim_atoms)
var/atom/movable/paused = _paused
if(!paused)
paused_floating_anim_atoms -= paused
else if(paused_floating_anim_atoms[paused] < world.time)
if(paused.movement_type & (FLOATING|FLYING) && !HAS_TRAIT(paused, TRAIT_NO_FLOATING_ANIM))
float(paused)
paused_floating_anim_atoms -= paused
if(!length(paused_floating_anim_atoms))
STOP_PROCESSING(SSdcs, src)
///Floats the movable up and down. Not a comsig proc.
/datum/element/movetype_handler/proc/float(atom/movable/target)
animate(target, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE|ANIMATION_PARALLEL)
animate(pixel_y = -2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
/// Stops the above. Also not a comsig proc.
/datum/element/movetype_handler/proc/stop_floating(atom/movable/target)
var/final_pixel_y = target.base_pixel_y
if(isliving(target)) //Living mobs also have a 'body_position_pixel_y_offset' variable that has to be taken into account here.
var/mob/living/living_target = target
final_pixel_y += living_target.body_position_pixel_y_offset
animate(target, pixel_y = final_pixel_y, time = 1 SECONDS)
+9 -25
View File
@@ -35,8 +35,14 @@
var/list/client_mobs_in_contents // This contains all the client mobs within this container
var/list/acted_explosions //for explosion dodging
var/datum/forced_movement/force_moving = null //handled soley by forced_movement.dm
///In case you have multiple types, you automatically use the most useful one. IE: Skating on ice, flippers on water, flying over chasm/space, etc. Should only be changed through setMovetype()
/**
* In case you have multiple types, you automatically use the most useful one.
* IE: Skating on ice, flippers on water, flying over chasm/space, etc.
* I reccomend you use the movetype_handler system and not modify this directly, especially for living mobs.
*/
var/movement_type = GROUND
var/atom/movable/pulling
var/grab_state = 0
var/throwforce = 0
@@ -594,15 +600,6 @@
var/atom/movable/AM = item
AM.onTransitZ(old_z,new_z)
///Proc to modify the movement_type and hook behavior associated with it changing.
/atom/movable/proc/setMovetype(newval)
if(movement_type == newval)
return
. = movement_type
movement_type = newval
/**
* Called whenever an object moves and by mobs when they attempt to move themselves through space
* And when an object or action applies a force on src, see [newtonian_move][/atom/movable/proc/newtonian_move]
@@ -848,8 +845,8 @@
var/matrix/initial_transform = matrix(transform)
var/matrix/rotated_transform = transform.Turn(15 * turn_dir)
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform=rotated_transform, time = 1, easing=BACK_EASING|EASE_IN)
animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform=initial_transform, time = 2, easing=SINE_EASING)
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform=rotated_transform, time = 1, easing=BACK_EASING|EASE_IN, flags = ANIMATION_PARALLEL)
animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform=initial_transform, time = 2, easing=SINE_EASING, flags = ANIMATION_PARALLEL)
/atom/movable/proc/do_item_attack_animation(atom/A, visual_effect_icon, obj/item/used_item)
var/image/I
@@ -903,19 +900,6 @@
acted_explosions += ex_id
return TRUE
//TODO: Better floating
/atom/movable/proc/float(on)
if(throwing)
return
if(on && !(movement_type & FLOATING))
animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
animate(pixel_y = -2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
setMovetype(movement_type | FLOATING)
else if (!on && (movement_type & FLOATING))
animate(src, pixel_y = base_pixel_y, time = 10)
setMovetype(movement_type & ~FLOATING)
/* Language procs
* Unless you are doing something very specific, these are the ones you want to use.
*/
+19
View File
@@ -108,6 +108,10 @@
if(!check_loc && M.loc != loc)
M.forceMove(loc)
if(anchored)
ADD_TRAIT(M, TRAIT_NO_FLOATING_ANIM, BUCKLED_TRAIT)
if(!length(buckled_mobs))
RegisterSignal(src, COMSIG_MOVABLE_SET_ANCHORED, .proc/on_set_anchored)
M.set_buckled(src)
M.setDir(dir)
buckled_mobs |= M
@@ -146,10 +150,25 @@
buckled_mob.clear_alert("buckled")
buckled_mob.set_glide_size(DELAY_TO_GLIDE_SIZE(buckled_mob.total_multiplicative_slowdown()))
buckled_mobs -= buckled_mob
if(anchored)
REMOVE_TRAIT(buckled_mob, TRAIT_NO_FLOATING_ANIM, BUCKLED_TRAIT)
if(!length(buckled_mobs))
UnregisterSignal(src, COMSIG_MOVABLE_SET_ANCHORED, .proc/on_set_anchored)
SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force)
post_unbuckle_mob(.)
/atom/movable/proc/on_set_anchored(atom/movable/source, anchorvalue)
SIGNAL_HANDLER
for(var/_buckled_mob in buckled_mobs)
if(!_buckled_mob)
continue
var/mob/living/buckled_mob = _buckled_mob
if(anchored)
ADD_TRAIT(buckled_mob, TRAIT_NO_FLOATING_ANIM, BUCKLED_TRAIT)
else
REMOVE_TRAIT(buckled_mob, TRAIT_NO_FLOATING_ANIM, BUCKLED_TRAIT)
/**
* Call [/atom/movable/proc/unbuckle_mob] for all buckled mobs
*/
@@ -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
+8 -1
View File
@@ -24,6 +24,10 @@
var/respawn_time = 50
var/respawn_sound = 'sound/magic/staff_animation.ogg'
/obj/structure/life_candle/ComponentInitialize()
. = ..()
AddElement(/datum/element/movetype_handler)
/obj/structure/life_candle/attack_hand(mob/user)
. = ..()
if(.)
@@ -33,12 +37,15 @@
if(user.mind in linked_minds)
user.visible_message("<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(!linked_minds.len)
REMOVE_TRAIT(src, TRAIT_MOVE_FLOATING, LIFECANDLE_TRAIT)
else
if(!linked_minds.len)
ADD_TRAIT(src, TRAIT_MOVE_FLOATING, LIFECANDLE_TRAIT)
user.visible_message("<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
update_icon()
float(linked_minds.len)
if(linked_minds.len)
START_PROCESSING(SSobj, src)
set_light(lit_luminosity)
+2
View File
@@ -1261,6 +1261,8 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/source = "adminabuse"
switch(add_or_remove)
if("Add") //Not doing source choosing here intentionally to make this bit faster to use, you can always vv it.
if(GLOB.movement_type_trait_to_flag[chosen_trait]) //include the required element.
D.AddElement(/datum/element/movetype_handler)
ADD_TRAIT(D,chosen_trait,source)
if("Remove")
var/specific = input("All or specific source ?", "Trait Remove/Add") as null|anything in list("All","Specific")
+1 -1
View File
@@ -105,7 +105,7 @@
attack_verb_continuous = "hits"
attack_verb_simple = "hit"
attack_sound = 'sound/weapons/genhit1.ogg'
movement_type = FLYING
is_flying_animal = TRUE
del_on_death = TRUE
deathmessage = "explodes into a cloud of gas!"
gold_core_spawnable = NO_SPAWN //gold slime cores should only spawn the independent subtype
@@ -45,7 +45,7 @@
status_flags = 0
wander = FALSE
density = FALSE
movement_type = FLYING
is_flying_animal = TRUE
move_resist = MOVE_FORCE_OVERPOWERING
mob_size = MOB_SIZE_TINY
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
@@ -376,7 +376,6 @@
custom_premium_price = PAYCHECK_EASY * 1.6
custom_price = PAYCHECK_EASY * 1.6
/obj/item/clothing/shoes/kindle_kicks
name = "Kindle Kicks"
desc = "They'll sure kindle something in you, and it's not childhood nostalgia..."
@@ -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
..()
@@ -529,7 +529,7 @@
// Shake animation
if (incapacitated())
var/direction = prob(50) ? -1 : 1
animate(src, pixel_x = pixel_x + SHAKE_ANIMATION_OFFSET * direction, time = 1, easing = QUAD_EASING | EASE_OUT)
animate(src, pixel_x = pixel_x + SHAKE_ANIMATION_OFFSET * direction, time = 1, easing = QUAD_EASING | EASE_OUT, flags = ANIMATION_PARALLEL)
animate(pixel_x = pixel_x - (SHAKE_ANIMATION_OFFSET * 2 * direction), time = 1)
animate(pixel_x = pixel_x + SHAKE_ANIMATION_OFFSET * direction, time = 1, easing = QUAD_EASING | EASE_IN)
@@ -59,17 +59,17 @@
if(!usable_legs && !(movement_type & (FLYING | FLOATING)))
ADD_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
/mob/living/carbon/setMovetype(newval)
/mob/living/carbon/on_movement_type_flag_enabled(datum/source, flag)
var/old_movetype = movement_type
. = ..()
if(isnull(.))
return
if(!(. & (FLYING | FLOATING)))
if(movement_type & (FLYING | FLOATING)) //From not flying to flying.
remove_movespeed_modifier(/datum/movespeed_modifier/limbless)
REMOVE_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
else if(!(movement_type & (FLYING | FLOATING))) //From flying to no longer flying.
if(flag & (FLYING | FLOATING) && !(old_movetype & (FLYING | FLOATING)))
remove_movespeed_modifier(/datum/movespeed_modifier/limbless)
REMOVE_TRAIT(src, TRAIT_FLOORED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
REMOVE_TRAIT(src, TRAIT_IMMOBILIZED, LACKING_LOCOMOTION_APPENDAGES_TRAIT)
/mob/living/carbon/on_movement_type_flag_disabled(datum/source, flag)
. = ..()
if(flag & (FLYING | FLOATING) && !(movement_type & (FLYING | FLOATING)))
var/limbless_slowdown = 0
if(usable_legs < default_num_legs)
limbless_slowdown += (default_num_legs - usable_legs) * 3
@@ -1,4 +1,4 @@
//IMPORTANT: Multiple animate() calls do not stack well, so try to do them all at once if you can.
sues//IMPORTANT: Multiple animate() calls do not stack well, so try to do them all at once if you can.
/mob/living/carbon/update_transform()
var/matrix/ntransform = matrix(transform) //aka transform.Copy()
var/final_pixel_y = pixel_y
@@ -21,8 +21,8 @@
resize = RESIZE_DEFAULT_SIZE
if(changed)
SEND_SIGNAL(src, COMSIG_PAUSE_FLOATING_ANIM, 0.3 SECONDS)
animate(src, transform = ntransform, time = (lying_prev == 0 || lying_angle == 0) ? 2 : 0, pixel_y = final_pixel_y, dir = final_dir, easing = (EASE_IN|EASE_OUT))
setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life().
/mob/living/carbon
var/list/overlays_standing[TOTAL_LAYERS]
@@ -902,11 +902,6 @@
/mob/living/carbon/human/is_literate()
return TRUE
/mob/living/carbon/human/update_gravity(has_gravity,override = 0)
if(dna?.species) //prevents a runtime while a human is being monkeyfied
override = dna.species.override_float
..()
/mob/living/carbon/human/vomit(lost_nutrition = 10, blood = FALSE, stun = TRUE, distance = 1, message = TRUE, vomit_type = VOMIT_TOXIC, harm = TRUE, force = FALSE, purge_ratio = 0.1)
if(blood && (NOBLOOD in dna.species.species_traits) && !HAS_TRAIT(src, TRAIT_TOXINLOVER))
if(message)
@@ -168,8 +168,6 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/obj/item/organ/appendix/mutantappendix = /obj/item/organ/appendix
///Forces an item into this species' hands. Only an honorary mutantthing because this is not an organ and not loaded in the same way, you've been warned to do your research.
var/obj/item/mutanthands
///Allows the species to not give a single F about gravity. Used by wings.
var/override_float = FALSE
///Bitflag that controls what in game ways something can select this species as a spawnable source, such as magic mirrors. See [mob defines][code/__DEFINES/mobs.dm] for possible sources.
var/changesource_flags = NONE
@@ -2080,18 +2078,18 @@ GLOBAL_LIST_EMPTY(roundstart_races)
//UNSAFE PROC, should only be called through the Activate or other sources that check for CanFly
/datum/species/proc/ToggleFlight(mob/living/carbon/human/H)
if(!(H.movement_type & FLYING))
if(!HAS_TRAIT_FROM(H, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT))
stunmod *= 2
speedmod -= 0.35
H.setMovetype(H.movement_type | FLYING)
override_float = TRUE
ADD_TRAIT(H, TRAIT_NO_FLOATING_ANIM, SPECIES_FLIGHT_TRAIT)
ADD_TRAIT(H, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT)
passtable_on(H, SPECIES_TRAIT)
H.OpenWings()
else
stunmod *= 0.5
speedmod += 0.35
H.setMovetype(H.movement_type & ~FLYING)
override_float = FALSE
REMOVE_TRAIT(H, TRAIT_NO_FLOATING_ANIM, SPECIES_FLIGHT_TRAIT)
REMOVE_TRAIT(H, TRAIT_MOVE_FLYING, SPECIES_FLIGHT_TRAIT)
passtable_off(H, SPECIES_TRAIT)
H.CloseWings()
+12
View File
@@ -38,6 +38,8 @@
SIGNAL_REMOVETRAIT(TRAIT_NODEATH),
), .proc/update_succumb_action)
RegisterSignal(src, COMSIG_MOVETYPE_FLAG_ENABLED, .proc/on_movement_type_flag_enabled)
RegisterSignal(src, COMSIG_MOVETYPE_FLAG_DISABLED, .proc/on_movement_type_flag_disabled)
/// Called when [TRAIT_KNOCKEDOUT] is added to the mob.
/mob/living/proc/on_knockedout_trait_gain(datum/source)
@@ -180,3 +182,13 @@
throw_alert("succumb", /atom/movable/screen/alert/succumb)
else
clear_alert("succumb")
///From [element/movetype_handler/on_movement_type_trait_gain()]
/mob/living/proc/on_movement_type_flag_enabled(datum/source, trait)
SIGNAL_HANDLER
update_movespeed(FALSE)
///From [element/movetype_handler/on_movement_type_trait_loss()]
/mob/living/proc/on_movement_type_flag_disabled(datum/source, trait)
SIGNAL_HANDLER
update_movespeed(FALSE)
-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)
+12 -22
View File
@@ -10,6 +10,10 @@
faction += "[REF(src)]"
GLOB.mob_living_list += src
/mob/living/ComponentInitialize()
. = ..()
AddElement(/datum/element/movetype_handler)
/mob/living/prepare_huds()
..()
prepare_data_huds()
@@ -942,10 +946,11 @@
/mob/living/proc/get_visible_name()
return name
/mob/living/update_gravity(has_gravity, override)
/mob/living/update_gravity(has_gravity)
. = ..()
if(!SSticker.HasRoundStarted())
return
var/was_weightless = alerts["gravity"] && istype(alerts["gravity"], /atom/movable/screen/alert/weightless)
if(has_gravity)
if(has_gravity == 1)
clear_alert("gravity")
@@ -954,24 +959,12 @@
throw_alert("gravity", /atom/movable/screen/alert/veryhighgravity)
else
throw_alert("gravity", /atom/movable/screen/alert/highgravity)
if(was_weightless)
REMOVE_TRAIT(src, TRAIT_MOVE_FLOATING, NO_GRAVITY_TRAIT)
else
throw_alert("gravity", /atom/movable/screen/alert/weightless)
if(!override && !is_flying())
float(!has_gravity)
/mob/living/float(on)
if(throwing)
return
var/fixed = 0
if(anchored || (buckled?.anchored))
fixed = 1
if(on && !(movement_type & FLOATING) && !fixed)
animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
animate(pixel_y = -2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
setMovetype(movement_type | FLOATING)
else if(((!on || fixed) && (movement_type & FLOATING)))
animate(src, pixel_y = base_pixel_y + body_position_pixel_y_offset, time = 1 SECONDS)
setMovetype(movement_type & ~FLOATING)
if(!was_weightless)
ADD_TRAIT(src, TRAIT_MOVE_FLOATING, NO_GRAVITY_TRAIT)
// The src mob is trying to strip an item from someone
// Override if a certain type of mob should be behave differently when stripping items (can't, for example)
@@ -1065,11 +1058,8 @@
var/amplitude = min(4, (jitteriness/100) + 1)
var/pixel_x_diff = rand(-amplitude, amplitude)
var/pixel_y_diff = rand(-amplitude/3, amplitude/3)
var/final_pixel_x = base_pixel_x + body_position_pixel_x_offset
var/final_pixel_y = base_pixel_y + body_position_pixel_y_offset
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 2, loop = 6)
animate(pixel_x = final_pixel_x , pixel_y = final_pixel_y , time = 2)
setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure to restart it in next life().
animate(src, pixel_x = pixel_x_diff, pixel_y = pixel_y_diff , time = 2, loop = 6, flags = ANIMATION_RELATIVE|ANIMATION_PARALLEL)
animate(pixel_x = -pixel_x_diff , pixel_y = -pixel_y_diff , time = 2, flags = ANIMATION_RELATIVE)
/mob/living/proc/get_temperature(datum/gas_mixture/environment)
var/loc_temp = environment ? environment.temperature : T0C
@@ -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
@@ -26,7 +26,7 @@
maxbodytemp = INFINITY
healable = 0
faction = list("cult")
movement_type = FLYING
is_flying_animal = TRUE
pressure_resistance = 100
unique_name = 1
AIStatus = AI_OFF //normal constructs don't have AI
@@ -18,7 +18,7 @@
friendly_verb_continuous = "nudges"
friendly_verb_simple = "nudge"
density = FALSE
movement_type = FLYING
is_flying_animal = TRUE
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
ventcrawler = VENTCRAWLER_ALWAYS
mob_size = MOB_SIZE_TINY
@@ -25,7 +25,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
speed = 0
a_intent = INTENT_HARM
stop_automated_movement = 1
movement_type = FLYING // Immunity to chasms and landmines, etc.
is_flying_animal = TRUE // Immunity to chasms and landmines, etc.
attack_sound = 'sound/weapons/punch1.ogg'
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
@@ -42,7 +42,7 @@
density = FALSE
mob_size = MOB_SIZE_TINY
mob_biotypes = MOB_ORGANIC|MOB_BUG
movement_type = FLYING
is_flying_animal = TRUE
gold_core_spawnable = FRIENDLY_SPAWN
search_objects = 1 //have to find those plant trays!
can_be_held = TRUE
@@ -41,7 +41,7 @@
minbodytemp = 0
maxbodytemp = 1500
faction = list("carp")
movement_type = FLYING
is_flying_animal = TRUE
pressure_resistance = 200
gold_core_spawnable = HOSTILE_SPAWN
@@ -25,7 +25,7 @@
attack_verb_continuous = "blinks at"
attack_verb_simple = "blink at"
attack_sound = 'sound/weapons/pierce.ogg'
movement_type = FLYING
is_flying_animal = TRUE
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 1500
@@ -81,9 +81,13 @@
/obj/structure/leaper_bubble/Initialize()
. = ..()
INVOKE_ASYNC(src, /atom/movable.proc/float, TRUE)
QDEL_IN(src, 100)
/obj/structure/leaper_bubble/ComponentInitialize()
. = ..()
AddElement(/datum/element/movetype_handler)
ADD_TRAIT(src, TRAIT_MOVE_FLOATING, LEAPER_BUBBLE_TRAIT)
/obj/structure/leaper_bubble/Destroy()
new /obj/effect/temp_visual/leaper_projectile_impact(get_turf(src))
playsound(src,'sound/effects/snap.ogg',50, TRUE, -1)
@@ -57,6 +57,10 @@
/datum/action/innate/megafauna_attack/alternating_cardinals)
small_sprite_type = /datum/action/small_sprite/megafauna/colossus
/mob/living/simple_animal/hostile/megafauna/colossus/Initialize()
. = ..()
ADD_TRAIT(src, TRAIT_NO_FLOATING_ANIM, ROUNDSTART_TRAIT) //we don't want this guy to float, messes up his animations.
/datum/action/innate/megafauna_attack/spiral_attack
name = "Spiral Shots"
icon_icon = 'icons/mob/actions/actions_items.dmi'
@@ -250,14 +254,6 @@
AT.pixel_y += random_y
return ..()
/mob/living/simple_animal/hostile/megafauna/colossus/float(on) //we don't want this guy to float, messes up his animations
if(throwing)
return
if(on && !(movement_type & FLOATING))
setMovetype(movement_type | FLOATING)
else if(!on && (movement_type & FLOATING))
setMovetype(movement_type & ~FLOATING)
/obj/projectile/colossus
name ="death bolt"
icon_state= "chronobolt"
@@ -661,7 +657,7 @@
friendly_verb_continuous = "taps"
friendly_verb_simple = "tap"
density = FALSE
movement_type = FLYING
is_flying_animal = TRUE
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
ventcrawler = VENTCRAWLER_ALWAYS
mob_size = MOB_SIZE_TINY
@@ -256,7 +256,7 @@ Difficulty: Extremely Hard
for(var/mob/living/L in viewers(src))
shake_camera(L, 3, 2)
playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE)
setMovetype(movement_type | FLYING)
ADD_TRAIT(src, TRAIT_MOVE_FLYING, FROSTMINER_ENRAGE_TRAIT)
enraging = FALSE
adjustHealth(-maxHealth)
@@ -11,7 +11,7 @@
light_range = 3
faction = list("mining", "boss")
weather_immunities = list("lava","ash")
movement_type = FLYING
is_flying_animal = TRUE
robust_searching = TRUE
ranged_ignores_vision = TRUE
stat_attack = DEAD
@@ -110,7 +110,7 @@
speak_emote = list("telepathically cries")
attack_sound = 'sound/weapons/bladeslice.ogg'
stat_attack = HARD_CRIT
movement_type = FLYING
is_flying_animal = TRUE
robust_searching = 1
crusher_loot = /obj/item/crusher_trophy/watcher_wing
gold_core_spawnable = NO_SPAWN
@@ -6,7 +6,7 @@
icon_living = "curseblob"
icon_aggro = "curseblob"
mob_biotypes = MOB_SPIRIT
movement_type = FLYING
is_flying_animal = TRUE
move_to_delay = 5
vision_range = 20
aggro_vision_range = 20
@@ -201,7 +201,7 @@
icon_aggro = "herald_mirror"
deathmessage = "shatters violently!"
deathsound = 'sound/effects/glassbr1.ogg'
movement_type = FLYING
is_flying_animal = TRUE
del_on_death = TRUE
is_mirror = TRUE
var/mob/living/simple_animal/hostile/asteroid/elite/herald/my_master = null
@@ -73,7 +73,7 @@
speed = 3
maxHealth = 1
health = 1
movement_type = FLYING
is_flying_animal = TRUE
harm_intent_damage = 5
melee_damage_lower = 2
melee_damage_upper = 2
@@ -37,7 +37,7 @@
deathmessage = "fades as the energies that tied it to this world dissipate."
deathsound = 'sound/magic/demon_dies.ogg'
stat_attack = HARD_CRIT
movement_type = FLYING
is_flying_animal = TRUE
robust_searching = TRUE
footstep_type = FOOTSTEP_MOB_CLAW
/// Distance the demon will teleport from the target
@@ -28,7 +28,7 @@
environment_smash = ENVIRONMENT_SMASH_NONE
ventcrawler = VENTCRAWLER_ALWAYS
mob_size = MOB_SIZE_TINY
movement_type = FLYING
is_flying_animal = TRUE
speak_emote = list("squeaks")
var/max_co2 = 0 //to be removed once metastation map no longer use those for Sgt Araneus
var/min_oxy = 0
@@ -28,7 +28,7 @@
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 1500
movement_type = FLYING
is_flying_animal = TRUE
pressure_resistance = 300
gold_core_spawnable = NO_SPAWN //too spooky for science
light_system = MOVABLE_LIGHT
@@ -306,7 +306,7 @@
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
mob_size = MOB_SIZE_TINY
movement_type = FLYING
is_flying_animal = TRUE
limb_destroyer = 1
speak_emote = list("states")
bubble_icon = "syndibot"
@@ -63,7 +63,7 @@
friendly_verb_continuous = "grooms"
friendly_verb_simple = "groom"
mob_size = MOB_SIZE_SMALL
movement_type = FLYING
is_flying_animal = TRUE
gold_core_spawnable = FRIENDLY_SPAWN
var/parrot_damage_upper = 10
@@ -30,7 +30,7 @@
stop_automated_movement = 1
faction = list("cult")
status_flags = CANPUSH
movement_type = FLYING
is_flying_animal = TRUE
loot = list(/obj/item/ectoplasm)
del_on_death = TRUE
initial_language_holder = /datum/language_holder/construct
@@ -128,6 +128,9 @@
var/dextrous = FALSE
var/dextrous_hud_type = /datum/hud/dextrous
///If the creature should have an innate TRAIT_MOVE_FLYING trait added on init that is also toggled off/on on death/revival.
var/is_flying_animal = FALSE
///The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever), AI_Z_OFF (Temporarily off due to nonpresence of players).
var/AIStatus = AI_ON
///once we have become sentient, we can never go back.
@@ -178,6 +181,8 @@
if(dextrous)
AddComponent(/datum/component/personal_crafting)
ADD_TRAIT(src, TRAIT_ADVANCEDTOOLUSER, ROUNDSTART_TRAIT)
if(is_flying_animal)
ADD_TRAIT(src, TRAIT_MOVE_FLYING, ROUNDSTART_TRAIT)
if(speak)
speak = string_list(speak)
@@ -214,6 +219,15 @@
return ..()
/mob/living/simple_animal/vv_edit_var(var_name, var_value)
. = ..()
switch(var_name)
if(NAMEOF(src, is_flying_animal))
if(stat != DEAD)
if(!is_flying_animal)
REMOVE_TRAIT(src, TRAIT_MOVE_FLYING, ROUNDSTART_TRAIT)
else
ADD_TRAIT(src, TRAIT_MOVE_FLYING, ROUNDSTART_TRAIT)
/mob/living/simple_animal/attackby(obj/item/O, mob/user, params)
if(!is_type_in_list(O, food_type))
@@ -449,7 +463,6 @@
new i(loc)
/mob/living/simple_animal/death(gibbed)
movement_type &= ~FLYING
if(nest)
nest.spawned_mobs -= src
nest = null
@@ -466,6 +479,8 @@
del_on_death = FALSE
qdel(src)
else
if(is_flying_animal)
REMOVE_TRAIT(src, TRAIT_MOVE_FLYING, ROUNDSTART_TRAIT)
health = 0
icon_state = icon_dead
if(flip_on_death)
@@ -499,7 +514,6 @@
/mob/living/simple_animal/extinguish_mob()
return
/mob/living/simple_animal/revive(full_heal = FALSE, admin_revive = FALSE)
. = ..()
if(!.)
@@ -507,8 +521,8 @@
icon = initial(icon)
icon_state = icon_living
density = initial(density)
setMovetype(initial(movement_type))
if(is_flying_animal)
ADD_TRAIT(src, TRAIT_MOVE_FLYING, ROUNDSTART_TRAIT)
/mob/living/simple_animal/proc/make_babies() // <3 <3 <3
if(gender != FEMALE || stat || next_scan_time > world.time || !childtype || !animal_species || !SSticker.IsRoundInProgress())
+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_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)
-8
View File
@@ -1289,14 +1289,6 @@
/mob/proc/set_nutrition(change) //Seriously fuck you oldcoders.
nutrition = max(0, change)
/mob/setMovetype(newval) //Set the movement type of the mob and update it's movespeed
. = ..()
if(isnull(.))
return
update_movespeed(FALSE)
/mob/proc/update_equipment_speed_mods()
var/speedies = equipped_speed_mods()
if(!speedies)
-8
View File
@@ -447,14 +447,6 @@
message_admins("No ghosts were willing to take control of [ADMIN_LOOKUPFLW(M)])")
return FALSE
///Is the mob a flying mob
/mob/proc/is_flying()
return (movement_type & FLYING)
///Is the mob a floating mob
/mob/proc/is_floating()
return (movement_type & FLOATING)
///Clicks a random nearby mob with the source from this mob
/mob/proc/click_random_mob()
var/list/nearby_mobs = list()
+1 -1
View File
@@ -940,7 +940,7 @@
if(!isliving(AM))
return
var/mob/living/L = AM
if(istype(L) && !(L.is_flying() || L.is_floating() || L.buckled))
if(!(L.movement_type & (FLYING|FLOATING)) || L.buckled)
playsound(src, 'sound/effects/glass_step.ogg', HAS_TRAIT(L, TRAIT_LIGHT_STEP) ? 30 : 50, TRUE)
if(status == LIGHT_BURNED || status == LIGHT_OK)
shatter()
@@ -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
+1
View File
@@ -614,6 +614,7 @@
#include "code\datums\elements\firestacker.dm"
#include "code\datums\elements\forced_gravity.dm"
#include "code\datums\elements\light_blocking.dm"
#include "code\datums\elements\movetype_handler.dm"
#include "code\datums\elements\obj_regen.dm"
#include "code\datums\elements\point_of_interest.dm"
#include "code\datums\elements\rad_insulation.dm"