diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 0c463bd3985..dbbae797365 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -289,6 +289,13 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_TRUE_NIGHT_VISION "true_night_vision" /// Negates our gravity, letting us move normally on floors in 0-g #define TRAIT_NEGATES_GRAVITY "negates_gravity" +/// We are ignoring gravity +#define TRAIT_IGNORING_GRAVITY "ignores_gravity" +/// Sources for TRAIT_IGNORING_GRAVITY +#define IGNORING_GRAVITY_NEGATION "ignoring_gravity_negation" +/// We have some form of forced gravity acting on us +#define TRAIT_FORCED_GRAVITY "forced_gravity" + /// Lets us scan reagents #define TRAIT_REAGENT_SCANNER "reagent_scanner" /// Lets us scan machine parts and tech unlocks diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 5c48ae25166..84ef7086c7d 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -80,7 +80,7 @@ SUBSYSTEM_DEF(mapping) var/adding_new_zlevel = FALSE ///shows the default gravity value for each z level. recalculated when gravity generators change. - ///associative list of the form: list("[z level num]" = max generator gravity in that z level OR the gravity level trait) + ///List in the form: list(z level num = max generator gravity in that z level OR the gravity level trait) var/list/gravity_by_z_level = list() /// list of traits and their associated z leves @@ -222,7 +222,7 @@ SUBSYSTEM_DEF(mapping) max_gravity = max(grav_gen.setting, max_gravity) max_gravity = max_gravity || level_trait(z_level_number, ZTRAIT_GRAVITY) || 0//just to make sure no nulls - gravity_by_z_level["[z_level_number]"] = max_gravity + gravity_by_z_level[z_level_number] = max_gravity return max_gravity @@ -764,6 +764,7 @@ GLOBAL_LIST_EMPTY(the_station_areas) // Suck it jannies z_level_to_plane_offset.len += 1 z_level_to_lowest_plane_offset += 1 + gravity_by_z_level.len += 1 // 0's the default value, we'll update it later if required z_level_to_plane_offset[z_value] = 0 z_level_to_lowest_plane_offset[z_value] = 0 diff --git a/code/datums/elements/forced_gravity.dm b/code/datums/elements/forced_gravity.dm index dfe01c10fb7..ab71be0aa31 100644 --- a/code/datums/elements/forced_gravity.dm +++ b/code/datums/elements/forced_gravity.dm @@ -13,6 +13,7 @@ src.gravity = gravity src.ignore_turf_gravity = ignore_turf_gravity + ADD_TRAIT(target, TRAIT_FORCED_GRAVITY, REF(src)) RegisterSignal(target, COMSIG_ATOM_HAS_GRAVITY, PROC_REF(gravity_check)) if(isturf(target)) @@ -22,6 +23,7 @@ . = ..() var/static/list/signals_b_gone = list(COMSIG_ATOM_HAS_GRAVITY, COMSIG_TURF_HAS_GRAVITY) UnregisterSignal(source, signals_b_gone) + REMOVE_TRAIT(source, TRAIT_FORCED_GRAVITY, REF(src)) /datum/element/forced_gravity/proc/gravity_check(datum/source, turf/location, list/gravs) SIGNAL_HANDLER diff --git a/code/game/atoms.dm b/code/game/atoms.dm index a9ef302f7e7..993ac4f4779 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1789,6 +1789,11 @@ * * micro-optimized to hell because this proc is very hot, being called several times per movement every movement. * + * HEY JACKASS, LISTEN + * IF YOU ADD SOMETHING TO THIS PROC, MAKE SURE /mob/living ACCOUNTS FOR IT + * Living mobs treat gravity in an event based manner. We've decomposed this proc into different checks + * for them to use. If you add more to it, make sure you do that, or things will behave strangely + * * Gravity situations: * * No gravity if you're not in a turf * * No gravity if this atom is in is a space turf @@ -1819,7 +1824,7 @@ var/area/turf_area = gravity_turf.loc - return !gravity_turf.force_no_gravity && (SSmapping.gravity_by_z_level["[gravity_turf.z]"] || turf_area.has_gravity) + return !gravity_turf.force_no_gravity && (SSmapping.gravity_by_z_level[gravity_turf.z] || turf_area.has_gravity) /** * Causes effects when the atom gets hit by a rust effect from heretics diff --git a/code/modules/mob/living/init_signals.dm b/code/modules/mob/living/init_signals.dm index 4ed321a6b54..6c4d59f93df 100644 --- a/code/modules/mob/living/init_signals.dm +++ b/code/modules/mob/living/init_signals.dm @@ -45,6 +45,14 @@ RegisterSignal(src, SIGNAL_REMOVETRAIT(TRAIT_SKITTISH), PROC_REF(on_skittish_trait_loss)) RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_NEGATES_GRAVITY), SIGNAL_REMOVETRAIT(TRAIT_NEGATES_GRAVITY)), PROC_REF(on_negate_gravity)) + RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_IGNORING_GRAVITY), SIGNAL_REMOVETRAIT(TRAIT_IGNORING_GRAVITY)), PROC_REF(on_ignore_gravity)) + RegisterSignals(src, list(SIGNAL_ADDTRAIT(TRAIT_FORCED_GRAVITY), SIGNAL_REMOVETRAIT(TRAIT_FORCED_GRAVITY)), PROC_REF(on_force_gravity)) + // We hook for forced grav changes from our turf and ourselves + var/static/list/loc_connections = list( + SIGNAL_ADDTRAIT(TRAIT_FORCED_GRAVITY) = PROC_REF(on_loc_force_gravity), + SIGNAL_REMOVETRAIT(TRAIT_FORCED_GRAVITY) = PROC_REF(on_loc_force_gravity), + ) + AddElement(/datum/element/connect_loc, loc_connections) /// Called when [TRAIT_KNOCKEDOUT] is added to the mob. /mob/living/proc/on_knockedout_trait_gain(datum/source) @@ -214,7 +222,26 @@ SIGNAL_HANDLER RemoveElement(/datum/element/skittish) -/// Called with [TRAIT_NEGATES_GRAVITY] is gained or lost +/// Called when [TRAIT_NEGATES_GRAVITY] is gained or lost /mob/living/proc/on_negate_gravity(datum/source) SIGNAL_HANDLER - update_gravity(has_gravity()) + if(!isgroundlessturf(loc)) + if(HAS_TRAIT(src, TRAIT_NEGATES_GRAVITY)) + ADD_TRAIT(src, TRAIT_IGNORING_GRAVITY, IGNORING_GRAVITY_NEGATION) + else + REMOVE_TRAIT(src, TRAIT_IGNORING_GRAVITY, IGNORING_GRAVITY_NEGATION) + +/// Called when [TRAIT_IGNORING_GRAVITY] is gained or lost +/mob/living/proc/on_ignore_gravity(datum/source) + SIGNAL_HANDLER + refresh_gravity() + +/// Called when [TRAIT_FORCED_GRAVITY] is gained or lost +/mob/living/proc/on_force_gravity(datum/source) + SIGNAL_HANDLER + refresh_gravity() + +/// Called when our loc's [TRAIT_FORCED_GRAVITY] is gained or lost +/mob/living/proc/on_loc_force_gravity(datum/source) + SIGNAL_HANDLER + refresh_gravity() diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 18dd38adcd6..b16cd783fe1 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -137,24 +137,14 @@ return /mob/living/proc/handle_gravity(delta_time, times_fired) - var/gravity = has_gravity() - update_gravity(gravity) - - if(gravity > STANDARD_GRAVITY) - gravity_animate() - handle_high_gravity(gravity, delta_time, times_fired) - else if(get_filter("gravity")) - remove_filter("gravity") + if(gravity_state > STANDARD_GRAVITY) + handle_high_gravity(gravity_state, delta_time, times_fired) /mob/living/proc/gravity_animate() if(!get_filter("gravity")) add_filter("gravity",1,list("type"="motion_blur", "x"=0, "y"=0)) - INVOKE_ASYNC(src, PROC_REF(gravity_pulse_animation)) - -/mob/living/proc/gravity_pulse_animation() - animate(get_filter("gravity"), y = 1, time = 10) - sleep(1 SECONDS) - animate(get_filter("gravity"), y = 0, time = 10) + animate(get_filter("gravity"), y = 1, time = 10, loop = -1) + animate(y = 0, time = 10) /mob/living/proc/handle_high_gravity(gravity, delta_time, times_fired) if(gravity < GRAVITY_DAMAGE_THRESHOLD) //Aka gravity values of 3 or more diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 4ea8d3d3fa9..b476a8af529 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -12,6 +12,7 @@ GLOB.mob_living_list += src SSpoints_of_interest.make_point_of_interest(src) update_fov() + gravity_setup() /mob/living/prepare_huds() ..() @@ -1103,10 +1104,15 @@ /mob/living/proc/get_visible_name() return name -/mob/living/update_gravity(gravity) - . = ..() - if(!SSticker.HasRoundStarted()) - return +/mob/living/proc/update_gravity(gravity) + // Handle movespeed stuff + var/speed_change = max(0, gravity - STANDARD_GRAVITY) + if(speed_change) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/gravity, multiplicative_slowdown=speed_change) + else + remove_movespeed_modifier(/datum/movespeed_modifier/gravity) + + // Time to add/remove gravity alerts. sorry for the mess it's gotta be fast var/atom/movable/screen/alert/gravity_alert = alerts[ALERT_GRAVITY] switch(gravity) if(-INFINITY to NEGATIVE_GRAVITY) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 0e32adb1aae..c7fc2990f6b 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -222,3 +222,6 @@ // Multiple imaginary friends! /// Contains the owner and all imaginary friend mobs if they exist, otherwise null var/list/imaginary_group = null + + /// What our current gravity state is. Used to avoid duplicate animates and such + var/gravity_state = 0 diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index f5a2f9fb8bf..8351c66a245 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -1,7 +1,58 @@ /mob/living/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) . = ..() update_turf_movespeed(loc) + if(HAS_TRAIT(src, TRAIT_NEGATES_GRAVITY)) + if(!isgroundlessturf(loc)) + ADD_TRAIT(src, TRAIT_IGNORING_GRAVITY, IGNORING_GRAVITY_NEGATION) + else + REMOVE_TRAIT(src, TRAIT_IGNORING_GRAVITY, IGNORING_GRAVITY_NEGATION) + var/turf/old_turf = get_turf(old_loc) + var/turf/new_turf = get_turf(src) + // If we're moving to/from nullspace, refresh + // Easier then adding nullchecks to all this shit, and technically right since a null turf means nograv + if(isnull(old_turf) || isnull(new_turf)) + refresh_gravity() + return + // If the turf gravity has changed, then it's possible that our state has changed, so update + if(HAS_TRAIT(old_turf, TRAIT_FORCED_GRAVITY) != HAS_TRAIT(new_turf, TRAIT_FORCED_GRAVITY) || new_turf.force_no_gravity != old_turf.force_no_gravity) + refresh_gravity() + + // Going to do area gravity checking here + var/area/old_area = old_turf.loc + var/area/new_area = new_turf.loc + // If the area gravity has changed, then it's possible that our state has changed, so update + if(old_area.has_gravity != new_area.has_gravity) + refresh_gravity() + +/mob/living/on_changed_z_level(turf/old_turf, turf/new_turf, same_z_layer, notify_contents) + . = ..() + + if(!old_turf || !new_turf || SSmapping.gravity_by_z_level[old_turf.z] != SSmapping.gravity_by_z_level[new_turf.z]) + refresh_gravity() + +/// Living Mob use event based gravity +/// We check here to ensure we haven't dropped any gravity changes +/mob/living/proc/gravity_setup() + on_negate_gravity(src) + refresh_gravity() + +/// Handles gravity effects. Call if something about our gravity has potentially changed! +/mob/living/proc/refresh_gravity() + var/old_grav_state = gravity_state + gravity_state = has_gravity() + if(gravity_state == old_grav_state) + return + + update_gravity(gravity_state) + + if(gravity_state > STANDARD_GRAVITY) + gravity_animate() + else if(old_grav_state > STANDARD_GRAVITY) + remove_filter("gravity") + +/mob/living/mob_negates_gravity() + return HAS_TRAIT_FROM(src, TRAIT_IGNORING_GRAVITY, IGNORING_GRAVITY_NEGATION) /mob/living/CanAllowThrough(atom/movable/mover, border_dir) . = ..() diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index 4f3b6d3feeb..b7e64d59622 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -3,8 +3,6 @@ return //Being dead doesn't mean your temperature never changes - update_gravity(has_gravity()) - if(malfhack?.aidisabled) deltimer(malfhacking) // This proc handles cleanup of screen notifications and diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index ea34cf4b701..98def711093 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -229,6 +229,3 @@ var/active_thinking_indicator /// User is thinking in character. Used to revert to thinking state after stop_typing var/thinking_IC = FALSE - - ///how much gravity is slowing us down - var/gravity_slowdown = 0 diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index d315fc1e154..1c6a3ef4f6e 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -352,8 +352,7 @@ * Does this mob ignore gravity */ /mob/proc/mob_negates_gravity() - var/turf/turf = get_turf(src) - return !isgroundlessturf(turf) && HAS_TRAIT(src, TRAIT_NEGATES_GRAVITY) + return FALSE /** * Called when this mob slips over, override as needed @@ -367,16 +366,6 @@ /mob/proc/slip(knockdown_amount, obj/slipped_on, lube_flags, paralyze, force_drop = FALSE) add_mob_memory(/datum/memory/was_slipped, antagonist = slipped_on) -/// Update the gravity status of this mob -/mob/proc/update_gravity(has_gravity, override=FALSE) - var/speed_change = max(0, has_gravity - STANDARD_GRAVITY) - if(!speed_change && gravity_slowdown) - remove_movespeed_modifier(/datum/movespeed_modifier/gravity) - gravity_slowdown = 0 - else if(gravity_slowdown != speed_change) - add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/gravity, multiplicative_slowdown=speed_change) - gravity_slowdown = speed_change - //bodypart selection verbs - Cyberboss //8: repeated presses toggles through head - eyes - mouth //9: eyes 8: head 7: mouth diff --git a/code/modules/mod/modules/modules_maint.dm b/code/modules/mod/modules/modules_maint.dm index 03cf69049fa..3efc046ee38 100644 --- a/code/modules/mod/modules/modules_maint.dm +++ b/code/modules/mod/modules/modules_maint.dm @@ -287,7 +287,6 @@ playsound(src, 'sound/effects/curseattack.ogg', 50) mod.wearer.AddElement(/datum/element/forced_gravity, NEGATIVE_GRAVITY) RegisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, PROC_REF(check_upstairs)) - mod.wearer.update_gravity(mod.wearer.has_gravity()) ADD_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, MOD_TRAIT) check_upstairs() //todo at some point flip your screen around @@ -303,7 +302,6 @@ qdel(mod.wearer.RemoveElement(/datum/element/forced_gravity, NEGATIVE_GRAVITY)) UnregisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED) step_count = 0 - mod.wearer.update_gravity(mod.wearer.has_gravity()) REMOVE_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, MOD_TRAIT) var/turf/open/openspace/current_turf = get_turf(mod.wearer) if(istype(current_turf)) diff --git a/code/modules/mod/modules/modules_science.dm b/code/modules/mod/modules/modules_science.dm index 0d1b8065aab..af0d43a1275 100644 --- a/code/modules/mod/modules/modules_science.dm +++ b/code/modules/mod/modules/modules_science.dm @@ -74,7 +74,6 @@ if(mod.wearer.has_gravity()) new /obj/effect/temp_visual/mook_dust(get_turf(src)) mod.wearer.AddElement(/datum/element/forced_gravity, 0) - mod.wearer.update_gravity(mod.wearer.has_gravity()) playsound(src, 'sound/effects/gravhit.ogg', 50) /obj/item/mod/module/anomaly_locked/antigrav/on_deactivation(display_message = TRUE, deleting = FALSE) @@ -82,7 +81,6 @@ if(!.) return mod.wearer.RemoveElement(/datum/element/forced_gravity, 0) - mod.wearer.update_gravity(mod.wearer.has_gravity()) if(deleting) return if(mod.wearer.has_gravity()) diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index 8c31b6b1bfb..10098d570f1 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -388,7 +388,9 @@ GLOBAL_LIST_EMPTY(gravity_generators) continue if(!is_valid_z_level(T, mob_turf)) continue - mobs.update_gravity(mobs.has_gravity()) + if(isliving(mobs)) + var/mob/living/grav_update = mobs + grav_update.refresh_gravity() if(mobs.client) shake_camera(mobs, 15, 1) mobs.playsound_local(T, null, 100, 1, 0.5, sound_to_use = alert_sound)