From 92c3ec6caf1778db827bca3bc51e05645d2b439a Mon Sep 17 00:00:00 2001
From: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>
Date: Tue, 18 Jun 2024 21:32:06 +0200
Subject: [PATCH] SSthrowing (#19421)
Ported SSThrowing from TG, to handle throwings.
Updated movement system to the latest iteration, made it a datum as per
latest iteration.
Updated pass/hit handling of atoms, introduced pass_flag_self to
determine what atoms allow to pass.
Moved procs and defines around to make them more organized.
---
aurorastation.dme | 6 +-
code/ZAS/Atom.dm | 9 -
code/__DEFINES/_flags.dm | 41 +++
.../signals_atom/signals_atom_movable.dm | 20 ++
.../signals/signals_mob/signals_mob_main.dm | 9 +
code/__DEFINES/dcs/signals/signals_turf.dm | 3 +
code/__DEFINES/items_clothing.dm | 9 -
code/__DEFINES/move_force.dm | 20 ++
code/__DEFINES/subsystems.dm | 2 +
code/controllers/subsystems/mob_ai.dm | 2 +-
.../subsystems/movement/movement_types.dm | 140 +++++-----
.../subsystems/movement/spacedrift.dm | 5 +
code/controllers/subsystems/throwing.dm | 242 ++++++++++++++++++
code/datums/components/drift.dm | 195 ++++++++++++++
.../move_manager.dm} | 13 +-
code/game/atom/_atom.dm | 22 +-
code/game/atoms.dm | 5 -
code/game/atoms_movable.dm | 223 +++++++++-------
code/game/machinery/OpTable.dm | 7 +-
code/game/machinery/chem_heater.dm | 1 +
code/game/machinery/computer/computer.dm | 2 +-
code/game/machinery/constructable_frame.dm | 2 +-
code/game/machinery/deployable.dm | 4 +-
code/game/machinery/doors/airlock.dm | 3 +-
code/game/machinery/doors/blast_door.dm | 1 +
code/game/machinery/doors/door.dm | 4 +-
code/game/machinery/doors/firedoor.dm | 4 +-
code/game/machinery/doors/windowdoor.dm | 5 +-
code/game/machinery/iv_drip.dm | 3 +-
code/game/machinery/machinery.dm | 1 +
code/game/objects/effects/chem/chemsmoke.dm | 4 +-
code/game/objects/effects/chem/foam.dm | 2 +-
code/game/objects/effects/spiders.dm | 6 +-
code/game/objects/items.dm | 4 +-
.../objects/items/weapons/cigs_lighters.dm | 3 +-
.../items/weapons/material/twohanded.dm | 2 +-
code/game/objects/items/weapons/policetape.dm | 1 +
.../structures/barricades/_barricade.dm | 2 +-
code/game/objects/structures/bonfire.dm | 4 +-
.../structures/crates_lockers/closets.dm | 5 +-
.../structures/crates_lockers/crates.dm | 4 +-
.../objects/structures/full_window_frame.dm | 2 +-
code/game/objects/structures/girders.dm | 4 +-
code/game/objects/structures/gore/core.dm | 2 +-
code/game/objects/structures/grille.dm | 2 +-
code/game/objects/structures/janicart.dm | 2 +-
code/game/objects/structures/kitchen_spike.dm | 4 +-
code/game/objects/structures/plasticflaps.dm | 2 +-
code/game/objects/structures/railing.dm | 3 +-
.../structures/stool_bed_chair_nest/bed.dm | 6 +-
code/game/objects/structures/urban.dm | 8 +-
.../objects/structures/windoor_assembly.dm | 4 +-
code/game/objects/structures/window.dm | 4 +-
code/game/turfs/flooring/urban.dm | 2 +-
code/game/turfs/simulated/shuttle_turfs.dm | 6 -
code/game/turfs/simulated/walls.dm | 2 +-
.../spacesuits/rig/modules/utility.dm | 2 +-
.../modules/heavy_vehicle/mech_interaction.dm | 4 +-
code/modules/heavy_vehicle/mech_life.dm | 4 +-
code/modules/heavy_vehicle/mecha.dm | 1 +
code/modules/hydroponics/trays/tray.dm | 2 +-
code/modules/mob/death.dm | 2 +-
.../mob/living/carbon/alien/diona/life.dm | 4 +-
.../mob/living/carbon/human/human_defense.dm | 22 +-
.../mob/living/carbon/human/human_powers.dm | 2 +-
code/modules/mob/living/carbon/slime/slime.dm | 2 +-
code/modules/mob/living/living.dm | 193 +++++++-------
code/modules/mob/living/living_defense.dm | 14 +-
.../mob/living/maneuvers/maneuver_leap.dm | 4 +-
.../mob/living/simple_animal/friendly/carp.dm | 10 +-
.../mob/living/simple_animal/friendly/cat.dm | 14 +-
.../mob/living/simple_animal/hostile/bear.dm | 4 +-
.../hostile/commanded/commanded.dm | 4 +-
.../simple_animal/hostile/giant_spider.dm | 10 +-
.../hostile/hivebots/hivebot_beacon.dm | 2 +-
.../living/simple_animal/hostile/hostile.dm | 14 +-
.../simple_animal/hostile/icarus_drone.dm | 6 +-
.../simple_animal/hostile/retaliate/cavern.dm | 2 +-
.../simple_animal/hostile/space_fauna.dm | 2 +-
.../mob/living/simple_animal/parrot.dm | 20 +-
.../mob/living/simple_animal/simple_animal.dm | 10 +-
code/modules/mob/mob.dm | 2 +-
code/modules/mob/mob_movement.dm | 57 +++--
.../computers/subtypes/dev_console.dm | 1 +
.../computers/subtypes/preset_console.dm | 3 -
code/modules/multiz/structures.dm | 4 +-
.../projectiles/guns/launcher/syringe_gun.dm | 6 +-
.../modules/projectiles/projectile/special.dm | 3 -
code/modules/reagents/reagent_containers.dm | 6 +-
.../reagent_containers/food/drinks/bottle.dm | 8 +-
code/modules/shieldgen/shieldwallgen.dm | 2 +-
code/modules/tables/interactions.dm | 4 +-
code/modules/tables/presets.dm | 8 +-
code/modules/tables/rack.dm | 1 +
code/modules/tables/tables.dm | 8 +
html/changelogs/fluffyghost-ssthrowing.yml | 61 +++++
96 files changed, 1125 insertions(+), 496 deletions(-)
create mode 100644 code/__DEFINES/move_force.dm
create mode 100644 code/controllers/subsystems/movement/spacedrift.dm
create mode 100644 code/controllers/subsystems/throwing.dm
create mode 100644 code/datums/components/drift.dm
rename code/{controllers/subsystems/movement/move_handler.dm => datums/move_manager.dm} (91%)
create mode 100644 html/changelogs/fluffyghost-ssthrowing.yml
diff --git a/aurorastation.dme b/aurorastation.dme
index 02bab0af34e..380e739331b 100644
--- a/aurorastation.dme
+++ b/aurorastation.dme
@@ -88,6 +88,7 @@
#include "code\__DEFINES\misc.dm"
#include "code\__DEFINES\mobs.dm"
#include "code\__DEFINES\modular_guns.dm"
+#include "code\__DEFINES\move_force.dm"
#include "code\__DEFINES\movement.dm"
#include "code\__DEFINES\obj.dm"
#include "code\__DEFINES\organs.dm"
@@ -354,6 +355,7 @@
#include "code\controllers\subsystems\stickyban.dm"
#include "code\controllers\subsystems\sun.dm"
#include "code\controllers\subsystems\sunlight.dm"
+#include "code\controllers\subsystems\throwing.dm"
#include "code\controllers\subsystems\ticker.dm"
#include "code\controllers\subsystems\timer.dm"
#include "code\controllers\subsystems\trade.dm"
@@ -378,9 +380,9 @@
#include "code\controllers\subsystems\initialization\misc_late.dm"
#include "code\controllers\subsystems\initialization\persistent_configuration.dm"
#include "code\controllers\subsystems\initialization\xenoarch.dm"
-#include "code\controllers\subsystems\movement\move_handler.dm"
#include "code\controllers\subsystems\movement\movement.dm"
#include "code\controllers\subsystems\movement\movement_types.dm"
+#include "code\controllers\subsystems\movement\spacedrift.dm"
#include "code\controllers\subsystems\processing\airflow.dm"
#include "code\controllers\subsystems\processing\calamity.dm"
#include "code\controllers\subsystems\processing\dcs.dm"
@@ -414,6 +416,7 @@
#include "code\datums\mind.dm"
#include "code\datums\mixed.dm"
#include "code\datums\modules.dm"
+#include "code\datums\move_manager.dm"
#include "code\datums\position_point_vector.dm"
#include "code\datums\progressbar.dm"
#include "code\datums\records.dm"
@@ -427,6 +430,7 @@
#include "code\datums\changelog\changelog.dm"
#include "code\datums\components\_component.dm"
#include "code\datums\components\connect_mob_behalf.dm"
+#include "code\datums\components\drift.dm"
#include "code\datums\components\local_network.dm"
#include "code\datums\components\armor\armor.dm"
#include "code\datums\components\base_name\base_name.dm"
diff --git a/code/ZAS/Atom.dm b/code/ZAS/Atom.dm
index 34a8756beb3..ef3768ad985 100644
--- a/code/ZAS/Atom.dm
+++ b/code/ZAS/Atom.dm
@@ -1,12 +1,3 @@
-
-/atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
- //Purpose: Determines if the object (or airflow) can pass this atom.
- //Called by: Movement, airflow.
- //Inputs: The moving atom (optional), target turf, "height" and air group
- //Outputs: Boolean if can pass.
-
- return (!density || !height || air_group)
-
/turf/CanPass(atom/movable/mover, turf/target, height=1.5,air_group=0)
if(!target) return 0
diff --git a/code/__DEFINES/_flags.dm b/code/__DEFINES/_flags.dm
index 2dfb225b529..070bde8c683 100644
--- a/code/__DEFINES/_flags.dm
+++ b/code/__DEFINES/_flags.dm
@@ -9,3 +9,44 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
///Whether /atom/Initialize() has already run for the object
#define INITIALIZED_1 (1<<5)
+
+/*
+ These defines are used specifically with the atom/pass_flags bitmask
+ the atom/checkpass() proc uses them (tables will call movable atom checkpass(PASSTABLE) for example)
+*/
+//flags for pass_flags
+/// Allows you to pass over tables.
+#define PASSTABLE (1<<0)
+/// Allows you to pass over glass(this generally includes anything see-through that's glass-adjacent, ie. windows, windoors, airlocks with glass, etc.)
+#define PASSGLASS (1<<1)
+/// Allows you to pass over grilles.
+#define PASSGRILLE (1<<2)
+/// Allows you to pass over blob tiles.
+#define PASSBLOB (1<<3)
+/// Allows you to pass over mobs.
+#define PASSMOB (1<<4)
+/// Allows you to pass over closed turfs, ie. walls.
+#define PASSCLOSEDTURF (1<<5)
+/// Let thrown things past us. **ONLY MEANINGFUL ON pass_flags_self!**
+#define LETPASSTHROW (1<<6)
+/// Allows you to pass over machinery, ie. vending machines, computers, protolathes, etc.
+#define PASSMACHINE (1<<7)
+/// Allows you to pass over structures, ie. racks, tables(if you don't already have PASSTABLE), etc.
+#define PASSSTRUCTURE (1<<8)
+/// Allows you to pass over plastic flaps, often found at cargo or MULE dropoffs.
+#define PASSFLAPS (1<<9)
+/// Allows you to pass over airlocks and mineral doors.
+#define PASSDOORS (1<<10)
+/// Allows you to pass over vehicles, ie. mecha
+#define PASSVEHICLE (1<<11)
+/// Allows you to pass over dense items.
+#define PASSITEM (1<<12)
+/// Do not intercept click attempts during Adjacent() checks. See [turf/proc/ClickCross]. **ONLY MEANINGFUL ON pass_flags_self!**
+#define LETPASSCLICKS (1<<13)
+/// Allows you to pass over windows and window-adjacent stuff, like windows and windoors. Does not include airlocks with glass in them.
+#define PASSWINDOW (1<<14)
+
+/* AURORA SNOWFLAKE CODE */
+#define PASSDOORHATCH (1<<15)
+#define PASSTRACE (1<<16) //Used by turrets in the check_trajectory proc to target mobs hiding behind certain things (such as closets)
+#define PASSRAILING (1<<17)
diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm
index ed9a684578a..f1e3f19de2e 100644
--- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm
+++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movable.dm
@@ -5,3 +5,23 @@
///from base of atom/movable/Moved(): (/atom)
#define COMSIG_MOVABLE_PRE_MOVE "movable_pre_move"
#define COMPONENT_MOVABLE_BLOCK_PRE_MOVE (1<<0)
+
+///from base of atom/movable/newtonian_move(): (inertia_direction, start_delay)
+#define COMSIG_MOVABLE_NEWTONIAN_MOVE "movable_newtonian_move"
+ #define COMPONENT_MOVABLE_NEWTONIAN_BLOCK (1<<0)
+
+///from datum/component/drift/allow_final_movement(): ()
+#define COMSIG_MOVABLE_DRIFT_BLOCK_INPUT "movable_drift_block_input"
+ #define DRIFT_ALLOW_INPUT (1<<0)
+
+///from base of atom/movable/throw_at(): (list/args)
+#define COMSIG_MOVABLE_PRE_THROW "movable_pre_throw"
+ #define COMPONENT_CANCEL_THROW (1<<0)
+///from base of atom/movable/throw_at(): (datum/thrownthing, spin)
+#define COMSIG_MOVABLE_POST_THROW "movable_post_throw"
+///from base of datum/thrownthing/finalize(): (obj/thrown_object, datum/thrownthing) used for when a throw is finished
+#define COMSIG_MOVABLE_THROW_LANDED "movable_throw_landed"
+
+/// from base of atom/movable/Process_Spacemove(): (movement_dir, continuous_move)
+#define COMSIG_MOVABLE_SPACEMOVE "spacemove"
+ #define COMSIG_MOVABLE_STOP_SPACEMOVE (1<<0)
diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm
index a4d09cc7e91..055e35bb49a 100644
--- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm
+++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm
@@ -2,3 +2,12 @@
#define COMSIG_MOB_CLIENT_PRE_LIVING_MOVE "mob_client_pre_living_move"
/// Should we stop the current living movement attempt
#define COMSIG_MOB_CLIENT_BLOCK_PRE_LIVING_MOVE COMPONENT_MOVABLE_BLOCK_PRE_MOVE
+
+/// From base of /client/Move(): (new_loc, direction)
+#define COMSIG_MOB_CLIENT_PRE_MOVE "mob_client_pre_move"
+ /// Should always match COMPONENT_MOVABLE_BLOCK_PRE_MOVE as these are interchangeable and used to block movement.
+ #define COMSIG_MOB_CLIENT_BLOCK_PRE_MOVE COMPONENT_MOVABLE_BLOCK_PRE_MOVE
+ /// The argument of move_args which corresponds to the loc we're moving to
+ #define MOVE_ARG_NEW_LOC 1
+ /// The arugment of move_args which dictates our movement direction
+ #define MOVE_ARG_DIRECTION 2
diff --git a/code/__DEFINES/dcs/signals/signals_turf.dm b/code/__DEFINES/dcs/signals/signals_turf.dm
index 71737d4eb0a..d1d7148268c 100644
--- a/code/__DEFINES/dcs/signals/signals_turf.dm
+++ b/code/__DEFINES/dcs/signals/signals_turf.dm
@@ -4,3 +4,6 @@
///from base of atom/has_gravity(): (atom/asker, list/forced_gravities)
#define COMSIG_TURF_HAS_GRAVITY "turf_has_gravity"
+
+///from base of datum/thrownthing/finalize(): (turf/turf, atom/movable/thrownthing) when something is thrown and lands on us
+#define COMSIG_TURF_MOVABLE_THROW_LANDED "turf_movable_throw_landed"
diff --git a/code/__DEFINES/items_clothing.dm b/code/__DEFINES/items_clothing.dm
index 01ef8e810df..cada25e2f5a 100644
--- a/code/__DEFINES/items_clothing.dm
+++ b/code/__DEFINES/items_clothing.dm
@@ -21,15 +21,6 @@
#define SLOT_WRISTS BITFLAG(15)
#define SLOT_S_STORE BITFLAG(16)
-// Flags for pass_flags.
-#define PASSTABLE 0x1
-#define PASSGLASS 0x2
-#define PASSGRILLE 0x4
-#define PASSDOORHATCH 0x8
-#define PASSMOB 0x10
-#define PASSTRACE 0x20 //Used by turrets in the check_trajectory proc to target mobs hiding behind certain things (such as closets)
-#define PASSRAILING 0x40
-
// Bitmasks for the flags_inv variable. These determine when a piece of clothing hides another, i.e. a helmet hiding glasses.
#define HIDEGLOVES 0x1
#define HIDESUITSTORAGE 0x2
diff --git a/code/__DEFINES/move_force.dm b/code/__DEFINES/move_force.dm
new file mode 100644
index 00000000000..d291e95579d
--- /dev/null
+++ b/code/__DEFINES/move_force.dm
@@ -0,0 +1,20 @@
+//Defaults
+#define MOVE_FORCE_DEFAULT 1000
+#define MOVE_RESIST_DEFAULT 1000
+#define PULL_FORCE_DEFAULT 1000
+
+//Factors/modifiers
+#define MOVE_FORCE_PULL_RATIO 1 //Same move force to pull objects
+#define MOVE_FORCE_PUSH_RATIO 1 //Same move force to normally push
+#define MOVE_FORCE_FORCEPUSH_RATIO 2 //2x move force to forcefully push
+#define MOVE_FORCE_CRUSH_RATIO 3 //3x move force to do things like crush objects
+#define MOVE_FORCE_THROW_RATIO 1 //Same force throw as resist to throw objects
+
+#define MOVE_FORCE_OVERPOWERING (MOVE_FORCE_DEFAULT * MOVE_FORCE_CRUSH_RATIO * 10)
+#define MOVE_FORCE_EXTREMELY_STRONG (MOVE_FORCE_DEFAULT * MOVE_FORCE_CRUSH_RATIO * 3)
+#define MOVE_FORCE_VERY_STRONG ((MOVE_FORCE_DEFAULT * MOVE_FORCE_CRUSH_RATIO) - 1)
+#define MOVE_FORCE_STRONG (MOVE_FORCE_DEFAULT * 2)
+#define MOVE_FORCE_NORMAL MOVE_FORCE_DEFAULT
+#define MOVE_FORCE_WEAK (MOVE_FORCE_DEFAULT / 2)
+#define MOVE_FORCE_VERY_WEAK ((MOVE_FORCE_DEFAULT / MOVE_FORCE_CRUSH_RATIO) + 1)
+#define MOVE_FORCE_EXTREMELY_WEAK (MOVE_FORCE_DEFAULT / (MOVE_FORCE_CRUSH_RATIO * 3))
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index ef9f46ee067..e82fda2684d 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -254,6 +254,8 @@
#define FIRE_PRIORITY_ASSETS 20
#define FIRE_PRIORITY_PATHFINDING 23
#define FIRE_PRIORITY_PROCESS 25
+#define FIRE_PRIORITY_THROWING 25
+#define FIRE_PRIORITY_SPACEDRIFT 30
#define FIRE_PRIORITY_DEFAULT 50
#define FIRE_PRIORITY_STATPANEL 390
#define FIRE_PRIORITY_CHAT 400
diff --git a/code/controllers/subsystems/mob_ai.dm b/code/controllers/subsystems/mob_ai.dm
index 7e2c02d51d1..631380cad20 100644
--- a/code/controllers/subsystems/mob_ai.dm
+++ b/code/controllers/subsystems/mob_ai.dm
@@ -79,7 +79,7 @@ SUBSYSTEM_DEF(mob_ai)
/mob/proc/on_think_disabled()
walk_to(src, 0)
- SSmove_manager.stop_looping(src)
+ QDEL_NULL(move_packet)
/mob/proc/on_think_enabled()
return
diff --git a/code/controllers/subsystems/movement/movement_types.dm b/code/controllers/subsystems/movement/movement_types.dm
index 802ba3f4f3b..e9523b39ae1 100644
--- a/code/controllers/subsystems/movement/movement_types.dm
+++ b/code/controllers/subsystems/movement/movement_types.dm
@@ -135,9 +135,6 @@
if(flags & MOVEMENT_LOOP_IGNORE_GLIDE)
return
- //No gliding adjustment, for now
- //moving.set_glide_size(MOVEMENT_ADJUSTED_GLIDE_SIZE(delay, visual_delay))
-
///Handles the actual move, overriden by children
///Returns FALSE if nothing happen, TRUE otherwise
/datum/move_loop/proc/move()
@@ -163,7 +160,7 @@
status &= ~MOVELOOP_STATUS_PAUSED
///Removes the atom from some movement subsystem. Defaults to SSmovement
-/datum/controller/subsystem/move_manager/proc/stop_looping(atom/movable/moving, datum/controller/subsystem/movement/subsystem = SSmovement)
+/datum/move_manager/proc/stop_looping(atom/movable/moving, datum/controller/subsystem/movement/subsystem = SSmovement)
var/datum/movement_packet/our_info = moving.move_packet
if(!our_info)
return FALSE
@@ -184,7 +181,7 @@
* flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*
**/
-/datum/controller/subsystem/move_manager/proc/move(moving, direction, delay, timeout, subsystem, priority, flags, datum/extra_info)
+/datum/move_manager/proc/move(moving, direction, delay, timeout, subsystem, priority, flags, datum/extra_info)
return add_to_loop(moving, subsystem, /datum/move_loop/move, priority, flags, extra_info, delay, timeout, direction)
///Replacement for walk()
@@ -204,8 +201,7 @@
/datum/move_loop/move/move()
var/atom/old_loc = moving.loc
- //moving.Move(get_step(moving, direction), direction, FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
- moving.Move(get_step(moving, direction), direction)
+ moving.Move(get_step(moving, direction), direction, FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
// We cannot rely on the return value of Move(), we care about teleports and it doesn't
// Moving also can be null on occasion, if the move deleted it and therefor us
return old_loc != moving?.loc ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE
@@ -226,7 +222,7 @@
* flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*
**/
-/datum/controller/subsystem/move_manager/proc/force_move_dir(moving, direction, delay, timeout, subsystem, priority, flags, datum/extra_info)
+/datum/move_manager/proc/force_move_dir(moving, direction, delay, timeout, subsystem, priority, flags, datum/extra_info)
return add_to_loop(moving, subsystem, /datum/move_loop/move/force, priority, flags, extra_info, delay, timeout, direction)
/datum/move_loop/move/force
@@ -283,7 +279,7 @@
* flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*
**/
-/datum/controller/subsystem/move_manager/proc/force_move(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info)
+/datum/move_manager/proc/force_move(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info)
return add_to_loop(moving, subsystem, /datum/move_loop/has_target/force_move, priority, flags, extra_info, delay, timeout, chasing)
///Used for force-move loops
@@ -301,23 +297,23 @@
* Returns TRUE if the loop sucessfully started, or FALSE if it failed
*
* Arguments:
- * * moving - The atom we want to move
- * * chasing - The atom we want to move towards
- * * delay - How many deci-seconds to wait between fires. Defaults to the lowest value, 0.1
- * * repath_delay - How often we're allowed to recalculate our path
- * * max_path_length - The maximum number of steps we can take in a given path to search (default: 30, 0 = infinite)
- * * miminum_distance - Minimum distance to the target before path returns, could be used to get near a target, but not right to it - for an AI mob with a gun, for example
- * * access - A list representing what access we have and what doors we can open
- * * simulated_only - Whether we consider turfs without atmos simulation (AKA do we want to ignore space)
- * * avoid - If we want to avoid a specific turf, like if we're a mulebot who already got blocked by some turf
- * * skip_first - Whether or not to delete the first item in the path. This would be done because the first item is the starting tile, which can break things
- * * timeout - Time in deci-seconds until the moveloop self expires. Defaults to infinity
- * * subsystem - The movement subsystem to use. Defaults to SSmovement. Only one loop can exist for any one subsystem
- * * priority - Defines how different move loops override each other. Lower numbers beat higher numbers, equal defaults to what currently exists. Defaults to MOVEMENT_DEFAULT_PRIORITY
- * * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
+ * moving - The atom we want to move
+ * chasing - The atom we want to move towards
+ * delay - How many deci-seconds to wait between fires. Defaults to the lowest value, 0.1
+ * repath_delay - How often we're allowed to recalculate our path
+ * max_path_length - The maximum number of steps we can take in a given path to search (default: 30, 0 = infinite)
+ * miminum_distance - Minimum distance to the target before path returns, could be used to get near a target, but not right to it - for an AI mob with a gun, for example
+ * access - A list representing what access we have and what doors we can open
+ * simulated_only - Whether we consider turfs without atmos simulation (AKA do we want to ignore space)
+ * avoid - If we want to avoid a specific turf, like if we're a mulebot who already got blocked by some turf
+ * skip_first - Whether or not to delete the first item in the path. This would be done because the first item is the starting tile, which can break things
+ * timeout - Time in deci-seconds until the moveloop self expires. Defaults to infinity
+ * subsystem - The movement subsystem to use. Defaults to SSmovement. Only one loop can exist for any one subsystem
+ * priority - Defines how different move loops override each other. Lower numbers beat higher numbers, equal defaults to what currently exists. Defaults to MOVEMENT_DEFAULT_PRIORITY
+ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*
**/
-/datum/controller/subsystem/move_manager/proc/jps_move(moving,
+/datum/move_manager/proc/jps_move(moving,
chasing,
delay,
timeout,
@@ -441,8 +437,7 @@
var/turf/next_step = movement_path[1]
var/atom/old_loc = moving.loc
- //moving.Move(next_step, get_dir(moving, next_step), FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
- moving.Move(next_step, get_dir(moving, next_step))
+ moving.Move(next_step, get_dir(moving, next_step), FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
. = (old_loc != moving?.loc) ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE
// this check if we're on exactly the next tile may be overly brittle for dense objects who may get bumped slightly
@@ -486,17 +481,17 @@
* Returns TRUE if the loop sucessfully started, or FALSE if it failed
*
* Arguments:
- * * moving - The atom we want to move
- * * chasing - The atom we want to move towards
- * * min_dist - the closest we're allower to get to the target
- * * delay - How many deci-seconds to wait between fires. Defaults to the lowest value, 0.1
- * * timeout - Time in deci-seconds until the moveloop self expires. Defaults to infinity
- * * subsystem - The movement subsystem to use. Defaults to SSmovement. Only one loop can exist for any one subsystem
- * * priority - Defines how different move loops override each other. Lower numbers beat higher numbers, equal defaults to what currently exists. Defaults to MOVEMENT_DEFAULT_PRIORITY
- * * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
+ * moving - The atom we want to move
+ * chasing - The atom we want to move towards
+ * min_dist - the closest we're allower to get to the target
+ * delay - How many deci-seconds to wait between fires. Defaults to the lowest value, 0.1
+ * timeout - Time in deci-seconds until the moveloop self expires. Defaults to infinity
+ * subsystem - The movement subsystem to use. Defaults to SSmovement. Only one loop can exist for any one subsystem
+ * priority - Defines how different move loops override each other. Lower numbers beat higher numbers, equal defaults to what currently exists. Defaults to MOVEMENT_DEFAULT_PRIORITY
+ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*
**/
-/datum/controller/subsystem/move_manager/proc/move_to(moving, chasing, min_dist, delay, timeout, subsystem, priority, flags, datum/extra_info)
+/datum/move_manager/proc/move_to(moving, chasing, min_dist, delay, timeout, subsystem, priority, flags, datum/extra_info)
return add_to_loop(moving, subsystem, /datum/move_loop/has_target/dist_bound/move_to, priority, flags, extra_info, delay, timeout, chasing, min_dist)
///Wrapper around walk_to()
@@ -511,9 +506,7 @@
return
var/atom/old_loc = moving.loc
var/turf/next = get_step_to(moving, target)
- //This used to be `moving.Move(next, get_dir(moving, next), FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))` but our system is different and
- //putting a 4th or more parameters causes the gliding to catch fire, hence...
- moving.Move(next, get_dir(moving, next))
+ moving.Move(next, get_dir(moving, next), FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
return old_loc != moving?.loc ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE
/**
@@ -522,17 +515,17 @@
* Returns TRUE if the loop sucessfully started, or FALSE if it failed
*
* Arguments:
- * * moving - The atom we want to move
- * * chasing - The atom we want to move towards
- * * max_dist - the furthest away from the target we're allowed to get
- * * delay - How many deci-seconds to wait between fires. Defaults to the lowest value, 0.1
- * * timeout - Time in deci-seconds until the moveloop self expires. Defaults to infinity
- * * subsystem - The movement subsystem to use. Defaults to SSmovement. Only one loop can exist for any one subsystem
- * * priority - Defines how different move loops override each other. Lower numbers beat higher numbers, equal defaults to what currently exists. Defaults to MOVEMENT_DEFAULT_PRIORITY
- * * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
+ * moving - The atom we want to move
+ * chasing - The atom we want to move towards
+ * max_dist - the furthest away from the target we're allowed to get
+ * delay - How many deci-seconds to wait between fires. Defaults to the lowest value, 0.1
+ * timeout - Time in deci-seconds until the moveloop self expires. Defaults to infinity
+ * subsystem - The movement subsystem to use. Defaults to SSmovement. Only one loop can exist for any one subsystem
+ * priority - Defines how different move loops override each other. Lower numbers beat higher numbers, equal defaults to what currently exists. Defaults to MOVEMENT_DEFAULT_PRIORITY
+ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*
**/
-/datum/controller/subsystem/move_manager/proc/move_away(moving, chasing, max_dist, delay, timeout, subsystem, priority, flags, datum/extra_info)
+/datum/move_manager/proc/move_away(moving, chasing, max_dist, delay, timeout, subsystem, priority, flags, datum/extra_info)
return add_to_loop(moving, subsystem, /datum/move_loop/has_target/dist_bound/move_away, priority, flags, extra_info, delay, timeout, chasing, max_dist)
///Wrapper around walk_away()
@@ -547,8 +540,7 @@
return
var/atom/old_loc = moving.loc
var/turf/next = get_step_away(moving, target)
- //moving.Move(next, get_dir(moving, next), FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
- moving.Move(next, get_dir(moving, next))
+ moving.Move(next, get_dir(moving, next), FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
return old_loc != moving?.loc ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE
@@ -558,17 +550,17 @@
* Returns TRUE if the loop sucessfully started, or FALSE if it failed
*
* Arguments:
- * * moving - The atom we want to move
- * * chasing - The atom we want to move towards
- * * delay - How many deci-seconds to wait between fires. Defaults to the lowest value, 0.1
- * * home - Should we move towards the object at all times? Or launch towards them, but allow walls and such to take us off track. Defaults to FALSE
- * * timeout - Time in deci-seconds until the moveloop self expires. Defaults to INFINITY
- * * subsystem - The movement subsystem to use. Defaults to SSmovement. Only one loop can exist for any one subsystem
- * * priority - Defines how different move loops override each other. Lower numbers beat higher numbers, equal defaults to what currently exists. Defaults to MOVEMENT_DEFAULT_PRIORITY
- * * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
+ * moving - The atom we want to move
+ * chasing - The atom we want to move towards
+ * delay - How many deci-seconds to wait between fires. Defaults to the lowest value, 0.1
+ * home - Should we move towards the object at all times? Or launch towards them, but allow walls and such to take us off track. Defaults to FALSE
+ * timeout - Time in deci-seconds until the moveloop self expires. Defaults to INFINITY
+ * subsystem - The movement subsystem to use. Defaults to SSmovement. Only one loop can exist for any one subsystem
+ * priority - Defines how different move loops override each other. Lower numbers beat higher numbers, equal defaults to what currently exists. Defaults to MOVEMENT_DEFAULT_PRIORITY
+ * flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*
**/
-/datum/controller/subsystem/move_manager/proc/move_towards(atom/movable/moving, atom/chasing, delay, home, timeout, datum/controller/subsystem/movement/subsystem, priority, flags, datum/extra_info)
+/datum/move_manager/proc/move_towards(moving, chasing, delay, home, timeout, subsystem, priority, flags, datum/extra_info)
return add_to_loop(moving, subsystem, /datum/move_loop/has_target/move_towards, priority, flags, extra_info, delay, timeout, chasing, home)
/**
@@ -587,7 +579,7 @@
* flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*
**/
-/datum/controller/subsystem/move_manager/proc/home_onto(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info)
+/datum/move_manager/proc/home_onto(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info)
return move_towards(moving, chasing, delay, TRUE, timeout, subsystem, priority, flags, extra_info)
///Used as a alternative to walk_towards
@@ -650,8 +642,7 @@
if(y_ticker >= 1)
y_ticker = MODULUS(x_ticker, 1)
var/atom/old_loc = moving.loc
- //moving.Move(moving_towards, get_dir(moving, moving_towards), FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
- moving.Move(moving_towards, get_dir(moving, moving_towards))
+ moving.Move(moving_towards, get_dir(moving, moving_towards), FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
//YOU FOUND THEM! GOOD JOB
if(home && get_turf(moving) == get_turf(target))
@@ -724,7 +715,7 @@
* flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*
**/
-/datum/controller/subsystem/move_manager/proc/move_towards_legacy(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info)
+/datum/move_manager/proc/move_towards_legacy(moving, chasing, delay, timeout, subsystem, priority, flags, datum/extra_info)
return add_to_loop(moving, subsystem, /datum/move_loop/has_target/move_towards_budget, priority, flags, extra_info, delay, timeout, chasing)
///The actual implementation of walk_towards()
@@ -733,8 +724,7 @@
/datum/move_loop/has_target/move_towards_budget/move()
var/turf/target_turf = get_step_towards(moving, target)
var/atom/old_loc = moving.loc
- //moving.Move(target_turf, get_dir(moving, target_turf), FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
- moving.Move(target_turf, get_dir(moving, target_turf))
+ moving.Move(target_turf, get_dir(moving, target_turf), FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
return old_loc != moving?.loc ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE
/**
@@ -751,7 +741,7 @@
* priority - Defines how different move loops override each other. Lower numbers beat higher numbers, equal defaults to what currently exists. Defaults to MOVEMENT_DEFAULT_PRIORITY
* flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*/
-/datum/controller/subsystem/move_manager/proc/freeze(moving, halted_turf, delay, timeout, subsystem, priority, flags, datum/extra_info)
+/datum/move_manager/proc/freeze(moving, halted_turf, delay, timeout, subsystem, priority, flags, datum/extra_info)
return add_to_loop(moving, subsystem, /datum/move_loop/freeze, priority, flags, extra_info, delay, timeout, halted_turf)
/// As close as you can get to a "do-nothing" move loop, the pure intention of this is to absolutely resist all and any automated movement until the move loop times out.
@@ -775,7 +765,7 @@
* flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*
**/
-/datum/controller/subsystem/move_manager/proc/move_rand(moving, directions, delay, timeout, subsystem, priority, flags, datum/extra_info)
+/datum/move_manager/proc/move_rand(moving, directions, delay, timeout, subsystem, priority, flags, datum/extra_info)
if(!directions)
directions = GLOB.alldirs
return add_to_loop(moving, subsystem, /datum/move_loop/move_rand, priority, flags, extra_info, delay, timeout, directions)
@@ -807,8 +797,7 @@
var/testdir = pick(potential_dirs)
var/turf/moving_towards = get_step(moving, testdir)
var/atom/old_loc = moving.loc
- //moving.Move(moving_towards, testdir, FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
- moving.Move(moving_towards, testdir)
+ moving.Move(moving_towards, testdir, FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
if(old_loc != moving?.loc) //If it worked, we're done
return MOVELOOP_SUCCESS
potential_dirs -= testdir
@@ -828,7 +817,7 @@
* flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*
**/
-/datum/controller/subsystem/move_manager/proc/move_to_rand(moving, delay, timeout, subsystem, priority, flags, datum/extra_info)
+/datum/move_manager/proc/move_to_rand(moving, delay, timeout, subsystem, priority, flags, datum/extra_info)
return add_to_loop(moving, subsystem, /datum/move_loop/move_to_rand, priority, flags, extra_info, delay, timeout)
///Wrapper around step_rand
@@ -837,8 +826,7 @@
/datum/move_loop/move_to_rand/move()
var/atom/old_loc = moving.loc
var/turf/next = get_step_rand(moving)
- //moving.Move(next, get_dir(moving, next), FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
- moving.Move(next, get_dir(moving, next))
+ moving.Move(next, get_dir(moving, next), FALSE, !(flags & MOVEMENT_LOOP_NO_DIR_UPDATE))
return old_loc != moving?.loc ? MOVELOOP_SUCCESS : MOVELOOP_FAILURE
/**
@@ -855,13 +843,13 @@
* flags - Set of bitflags that effect move loop behavior in some way. Check _DEFINES/movement.dm
*
**/
-// /datum/controller/subsystem/move_manager/proc/move_disposals(moving, delay, timeout, subsystem, priority, flags, datum/extra_info)
+// /datum/move_manager/proc/move_disposals(moving, delay, timeout, subsystem, priority, flags, datum/extra_info)
// return add_to_loop(moving, subsystem, /datum/move_loop/disposal_holder, priority, flags, extra_info, delay, timeout)
-// /// Disposal holders need to move through a chain of pipes
-// /// Rather then through the world. This supports this
-// /// If this ever changes, get rid of this, add drift component like logic to the holder
-// /// And move them to move()
+/// Disposal holders need to move through a chain of pipes
+/// Rather then through the world. This supports this
+/// If this ever changes, get rid of this, add drift component like logic to the holder
+/// And move them to move()
// /datum/move_loop/disposal_holder
// /datum/move_loop/disposal_holder/setup(delay = 1, timeout = INFINITY)
diff --git a/code/controllers/subsystems/movement/spacedrift.dm b/code/controllers/subsystems/movement/spacedrift.dm
new file mode 100644
index 00000000000..4002b5eb555
--- /dev/null
+++ b/code/controllers/subsystems/movement/spacedrift.dm
@@ -0,0 +1,5 @@
+MOVEMENT_SUBSYSTEM_DEF(spacedrift)
+ name = "Space Drift"
+ priority = FIRE_PRIORITY_SPACEDRIFT
+ flags = SS_NO_INIT|SS_TICKER
+ runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
diff --git a/code/controllers/subsystems/throwing.dm b/code/controllers/subsystems/throwing.dm
new file mode 100644
index 00000000000..0bbbcaaf86a
--- /dev/null
+++ b/code/controllers/subsystems/throwing.dm
@@ -0,0 +1,242 @@
+#define MAX_THROWING_DIST 1280 // 5 z-levels on default width
+#define MAX_TICKS_TO_MAKE_UP 3 //how many missed ticks will we attempt to make up for this run.
+
+SUBSYSTEM_DEF(throwing)
+ name = "Throwing"
+ priority = FIRE_PRIORITY_THROWING
+ wait = 1
+ flags = SS_NO_INIT|SS_KEEP_TIMING|SS_TICKER
+ runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+
+ var/list/currentrun
+ var/list/processing = list()
+
+/datum/controller/subsystem/throwing/stat_entry(msg)
+ msg = "P:[length(processing)]"
+ return ..()
+
+
+/datum/controller/subsystem/throwing/fire(resumed = 0)
+ if (!resumed)
+ src.currentrun = processing.Copy()
+
+ //cache for sanic speed (lists are references anyways)
+ var/list/currentrun = src.currentrun
+
+ while(length(currentrun))
+ var/atom/movable/AM = currentrun[currentrun.len]
+ var/datum/thrownthing/TT = currentrun[AM]
+ currentrun.len--
+ if (QDELETED(AM) || QDELETED(TT))
+ processing -= AM
+ if (MC_TICK_CHECK)
+ return
+ continue
+
+ TT.tick()
+
+ if (MC_TICK_CHECK)
+ return
+
+ currentrun = null
+
+/datum/thrownthing
+ ///Defines the atom that has been thrown (Objects and Mobs, mostly.)
+ var/atom/movable/thrownthing
+ ///Weakref to the original intended target of the throw, to prevent hardDels
+ var/datum/weakref/initial_target
+ ///The turf that the target was on, if it's not a turf itself.
+ var/turf/target_turf
+ ///The turf that we were thrown from.
+ var/turf/starting_turf
+ ///If the target happens to be a carbon and that carbon has a body zone aimed at, this is carried on here.
+ var/target_zone
+ ///The initial direction of the thrower of the thrownthing for building the trajectory of the throw.
+ var/init_dir
+ ///The maximum number of turfs that the thrownthing will travel to reach it's target.
+ var/maxrange
+ ///Turfs to travel per tick
+ var/speed
+ ///If a mob is the one who has thrown the object, then it's moved here. This can be null and must be null checked before trying to use it.
+ var/datum/weakref/thrower
+ ///A variable that helps in describing objects thrown at an angle, if it should be moved diagonally first or last.
+ var/diagonals_first
+ ///Set to TRUE if the throw is exclusively diagonal (45 Degree angle throws for example)
+ var/pure_diagonal
+ ///Tracks how far a thrownthing has traveled mid-throw for the purposes of maxrange
+ var/dist_travelled = 0
+ ///The start_time obtained via world.time for the purposes of tiles moved/tick.
+ var/start_time
+ ///Distance to travel in the X axis/direction.
+ var/dist_x
+ ///Distance to travel in the y axis/direction.
+ var/dist_y
+ ///The Horizontal direction we're traveling (EAST or WEST)
+ var/dx
+ ///The VERTICAL direction we're traveling (NORTH or SOUTH)
+ var/dy
+ ///The movement force provided to a given object in transit. More info on these in move_force.dm
+ var/force = MOVE_FORCE_DEFAULT
+ ///If the throw is gentle, then the thrownthing is harmless on impact.
+ var/gentle = FALSE
+ ///How many tiles that need to be moved in order to travel to the target.
+ var/diagonal_error
+ ///If a thrown thing has a callback, it can be invoked here within thrownthing.
+ var/datum/callback/callback
+ ///Mainly exists for things that would freeze a thrown object in place, like a timestop'd tile. Or a Tractor Beam.
+ var/paused = FALSE
+ ///How long an object has been paused for, to be added to the travel time.
+ var/delayed_time = 0
+ ///The last world.time value stored when the thrownthing was moving.
+ var/last_move = 0
+
+/datum/thrownthing/New(thrownthing, target, init_dir, maxrange, speed, thrower, diagonals_first, force, gentle, callback, target_zone)
+ . = ..()
+ src.thrownthing = thrownthing
+ RegisterSignal(thrownthing, COMSIG_QDELETING, PROC_REF(on_thrownthing_qdel))
+ src.starting_turf = get_turf(thrownthing)
+ src.target_turf = get_turf(target)
+ if(target_turf != target)
+ src.initial_target = WEAKREF(target)
+ src.init_dir = init_dir
+ src.maxrange = maxrange
+ src.speed = speed
+ if(thrower)
+ src.thrower = WEAKREF(thrower)
+ src.diagonals_first = diagonals_first
+ src.force = force
+ src.gentle = gentle
+ src.callback = callback
+ src.target_zone = target_zone
+
+/datum/thrownthing/Destroy()
+ SSthrowing.processing -= thrownthing
+ SSthrowing.currentrun -= thrownthing
+ thrownthing.throwing = null
+ thrownthing = null
+ thrower = null
+ initial_target = null
+ callback = null
+ return ..()
+
+///Defines the datum behavior on the thrownthing's qdeletion event.
+/datum/thrownthing/proc/on_thrownthing_qdel(atom/movable/source, force)
+ SIGNAL_HANDLER
+
+ qdel(src)
+
+/// Returns the mob thrower, or null
+/datum/thrownthing/proc/get_thrower()
+ . = thrower?.resolve()
+ if(isnull(.))
+ thrower = null
+
+/datum/thrownthing/proc/tick()
+ var/atom/movable/AM = thrownthing
+ if (!isturf(AM.loc) || !AM.throwing)
+ finalize()
+ return
+
+ if(paused)
+ delayed_time += world.time - last_move
+ return
+
+ var/atom/movable/actual_target = initial_target?.resolve()
+ var/mob/mob_thrower = get_thrower()
+
+ if(dist_travelled) //to catch sneaky things moving on our tile while we slept
+ for(var/atom/movable/obstacle as anything in get_turf(thrownthing))
+ if (obstacle == thrownthing || (obstacle == mob_thrower && !ismob(thrownthing)))
+ continue
+ if(ismob(obstacle) && thrownthing.pass_flags & PASSMOB && (obstacle != actual_target))
+ continue
+ if(obstacle.pass_flags_self & LETPASSTHROW)
+ continue
+ if (obstacle == actual_target || (obstacle.density)) //Different from TG
+ finalize(TRUE, obstacle)
+ return
+
+ var/atom/step
+
+ last_move = world.time
+
+ //calculate how many tiles to move, making up for any missed ticks.
+ var/tilestomove = CEILING(min(((((world.time+world.tick_lag) - start_time + delayed_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait), 1)
+ while (tilestomove-- > 0)
+ if ((dist_travelled >= maxrange || AM.loc == target_turf) && AM.has_gravity(AM.loc))
+ finalize()
+ return
+
+ if (dist_travelled <= max(dist_x, dist_y)) //if we haven't reached the target yet we home in on it, otherwise we use the initial direction
+ step = get_step(AM, get_dir(AM, target_turf))
+ else
+ step = get_step(AM, init_dir)
+
+ if (!pure_diagonal && !diagonals_first) // not a purely diagonal trajectory and we don't want all diagonal moves to be done first
+ if (diagonal_error >= 0 && max(dist_x,dist_y) - dist_travelled != 1) //we do a step forward unless we're right before the target
+ step = get_step(AM, dx)
+ diagonal_error += (diagonal_error < 0) ? dist_x/2 : -dist_y
+
+ if (!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
+ finalize()
+ return
+
+ if(!AM.Move(step, get_dir(AM, step))) // we hit something during our move... //Different from TG
+ if(AM.throwing) // ...but finalize() wasn't called on Bump() because of a higher level definition that doesn't always call parent.
+ finalize()
+ return
+
+ dist_travelled++
+
+ if(actual_target && !(actual_target.pass_flags_self & LETPASSTHROW) && actual_target.loc == AM.loc) // we crossed a movable with no density (e.g. a mouse or APC) we intend to hit anyway.
+ finalize(TRUE, actual_target)
+ return
+
+ if (dist_travelled > MAX_THROWING_DIST)
+ finalize()
+ return
+
+/datum/thrownthing/proc/finalize(hit = FALSE, target=null)
+ set waitfor = FALSE
+ //done throwing, either because it hit something or it finished moving
+ if(!thrownthing)
+ return
+ thrownthing.throwing = null
+ if (!hit)
+ for (var/atom/movable/obstacle as anything in get_turf(thrownthing)) //looking for our target on the turf we land on.
+ if (obstacle == target)
+ hit = TRUE
+ thrownthing.throw_impact(obstacle, src)
+ if(QDELETED(thrownthing)) //throw_impact can delete things, such as glasses smashing
+ return //deletion should already be handled by on_thrownthing_qdel()
+ break
+ if (!hit)
+ thrownthing.throw_impact(get_turf(thrownthing), src) // we haven't hit something yet and we still must, let's hit the ground.
+ if(QDELETED(thrownthing)) //throw_impact can delete things, such as glasses smashing
+ return //deletion should already be handled by on_thrownthing_qdel()
+ thrownthing.newtonian_move(init_dir)
+ else
+ thrownthing.newtonian_move(init_dir)
+
+ if(target)
+ thrownthing.throw_impact(target, src)
+ if(QDELETED(thrownthing)) //throw_impact can delete things, such as glasses smashing
+ return //deletion should already be handled by on_thrownthing_qdel()
+
+ if (callback)
+ callback.Invoke()
+
+ // if(!thrownthing.currently_z_moving) // I don't think you can zfall while thrown but hey, just in case.
+ // var/turf/T = get_turf(thrownthing)
+ // T?.zFall(thrownthing)
+
+ if(thrownthing)
+ SEND_SIGNAL(thrownthing, COMSIG_MOVABLE_THROW_LANDED, src)
+ var/turf/landed_turf = get_turf(thrownthing)
+ if(landed_turf)
+ SEND_SIGNAL(landed_turf, COMSIG_TURF_MOVABLE_THROW_LANDED, thrownthing)
+
+ qdel(src)
+
+#undef MAX_THROWING_DIST
+#undef MAX_TICKS_TO_MAKE_UP
diff --git a/code/datums/components/drift.dm b/code/datums/components/drift.dm
new file mode 100644
index 00000000000..849a65ad0ed
--- /dev/null
+++ b/code/datums/components/drift.dm
@@ -0,0 +1,195 @@
+///Component that handles drifting
+///Manages a movement loop that actually does the legwork of moving someone
+///Alongside dealing with the post movement input blocking required to make things look nice
+/datum/component/drift
+ var/atom/inertia_last_loc
+ var/old_dir
+ var/datum/move_loop/move/drifting_loop
+ ///Should we ignore the next glide rate input we get?
+ ///This is to some extent a hack around the order of operations
+ ///Around COMSIG_MOVELOOP_POSTPROCESS. I'm sorry lad
+ var/ignore_next_glide = FALSE
+ ///Have we been delayed? IE: active, but not working right this second?
+ var/delayed = FALSE
+ var/block_inputs_until
+
+/// Accepts three args. The direction to drift in, if the drift is instant or not, and if it's not instant, the delay on the start
+/datum/component/drift/Initialize(direction, instant = FALSE, start_delay = 0)
+ if(!ismovable(parent))
+ return COMPONENT_INCOMPATIBLE
+ . = ..()
+
+ var/flags = MOVEMENT_LOOP_OUTSIDE_CONTROL
+ if(instant)
+ flags |= MOVEMENT_LOOP_START_FAST
+ var/atom/movable/movable_parent = parent
+ drifting_loop = GLOB.move_manager.move(moving = parent, direction = direction, delay = movable_parent.inertia_move_delay, subsystem = SSspacedrift, priority = MOVEMENT_SPACE_PRIORITY, flags = flags)
+
+ if(!drifting_loop) //Really want to qdel here but can't
+ return COMPONENT_INCOMPATIBLE
+
+ RegisterSignal(drifting_loop, COMSIG_MOVELOOP_START, PROC_REF(drifting_start))
+ RegisterSignal(drifting_loop, COMSIG_MOVELOOP_STOP, PROC_REF(drifting_stop))
+ RegisterSignal(drifting_loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(before_move))
+ RegisterSignal(drifting_loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(after_move))
+ RegisterSignal(drifting_loop, COMSIG_QDELETING, PROC_REF(loop_death))
+ RegisterSignal(movable_parent, COMSIG_MOVABLE_NEWTONIAN_MOVE, PROC_REF(newtonian_impulse))
+ if(drifting_loop.status & MOVELOOP_STATUS_RUNNING)
+ drifting_start(drifting_loop) // There's a good chance it'll autostart, gotta catch that
+
+ // var/visual_delay = movable_parent.inertia_move_delay
+
+ // Start delay is essentially a more granular version of instant
+ // Isn't used in the standard case, just for things that have odd wants
+ if(!instant && start_delay)
+ drifting_loop.pause_for(start_delay)
+ // visual_delay = start_delay
+
+ // apply_initial_visuals(visual_delay) // Used to have this proc in TG, but we don't use gliding
+
+/datum/component/drift/Destroy()
+ inertia_last_loc = null
+ if(!QDELETED(drifting_loop))
+ qdel(drifting_loop)
+ drifting_loop = null
+ var/atom/movable/movable_parent = parent
+ movable_parent.inertia_moving = FALSE
+ return ..()
+
+// Used to have this proc in TG, but we don't use gliding
+// /datum/component/drift/proc/apply_initial_visuals(visual_delay)
+ // If something "somewhere" doesn't want us to apply our glidesize delays, don't
+ // if(SEND_SIGNAL(parent, COMSIG_MOVABLE_DRIFT_VISUAL_ATTEMPT) & DRIFT_VISUAL_FAILED)
+ // return
+
+ // Ignore the next glide because it's literally just us
+ // ignore_next_glide = TRUE
+ // var/atom/movable/movable_parent = parent
+ // movable_parent.set_glide_size(MOVEMENT_ADJUSTED_GLIDE_SIZE(visual_delay, SSspacedrift.visual_delay))
+ // if(ismob(parent))
+ // var/mob/mob_parent = parent
+ // //Ok this is slightly weird, but basically, we need to force the client to glide at our rate
+ // //Make sure moving into a space move looks like a space move essentially
+ // //There is an inbuilt assumption that gliding will be added as a part of a move call, but eh
+ // //It's ok if it's not, it's just important if it is.
+ // mob_parent.client?.visual_delay = MOVEMENT_ADJUSTED_GLIDE_SIZE(visual_delay, SSspacedrift.visual_delay)
+
+/datum/component/drift/proc/newtonian_impulse(datum/source, inertia_direction)
+ SIGNAL_HANDLER
+ var/atom/movable/movable_parent = parent
+ inertia_last_loc = movable_parent.loc
+ if(drifting_loop)
+ drifting_loop.direction = inertia_direction
+ if(!inertia_direction)
+ qdel(src)
+ return COMPONENT_MOVABLE_NEWTONIAN_BLOCK
+
+/datum/component/drift/proc/drifting_start()
+ SIGNAL_HANDLER
+ var/atom/movable/movable_parent = parent
+ inertia_last_loc = movable_parent.loc
+ RegisterSignal(movable_parent, COMSIG_MOVABLE_MOVED, PROC_REF(handle_move))
+ // We will use glide size to intuit how long to delay our loop's next move for
+ // This way you can't ride two movements at once while drifting, since that'd be dumb as fuck
+ // RegisterSignal(movable_parent, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, PROC_REF(handle_glidesize_update))
+ // If you stop pulling something mid drift, I want it to retain that momentum
+ // RegisterSignal(movable_parent, COMSIG_ATOM_NO_LONGER_PULLING, PROC_REF(stopped_pulling))
+
+/datum/component/drift/proc/drifting_stop()
+ SIGNAL_HANDLER
+ var/atom/movable/movable_parent = parent
+ movable_parent.inertia_moving = FALSE
+ ignore_next_glide = FALSE
+ UnregisterSignal(movable_parent, list(COMSIG_MOVABLE_MOVED/*, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, COMSIG_ATOM_NO_LONGER_PULLING*/))
+
+/datum/component/drift/proc/before_move(datum/source)
+ SIGNAL_HANDLER
+ var/atom/movable/movable_parent = parent
+ movable_parent.inertia_moving = TRUE
+ old_dir = movable_parent.dir
+ delayed = FALSE
+
+/datum/component/drift/proc/after_move(datum/source, result, visual_delay)
+ SIGNAL_HANDLER
+ if(result == MOVELOOP_FAILURE)
+ qdel(src)
+ return
+
+ var/atom/movable/movable_parent = parent
+ movable_parent.set_dir(old_dir)
+ movable_parent.inertia_moving = FALSE
+ if(movable_parent.Process_Spacemove(drifting_loop.direction, continuous_move = TRUE))
+ glide_to_halt(visual_delay)
+ return
+
+ inertia_last_loc = movable_parent.loc
+ ignore_next_glide = TRUE
+
+/datum/component/drift/proc/loop_death(datum/source)
+ SIGNAL_HANDLER
+ drifting_loop = null
+ UnregisterSignal(parent, COMSIG_MOVABLE_NEWTONIAN_MOVE) // We won't block a component from replacing us anymore
+
+/datum/component/drift/proc/handle_move(datum/source, old_loc)
+ SIGNAL_HANDLER
+ // This can happen, because signals once sent cannot be stopped
+ if(QDELETED(src))
+ return
+ var/atom/movable/movable_parent = parent
+ if(!isturf(movable_parent.loc))
+ qdel(src)
+ return
+ if(movable_parent.inertia_moving)
+ return
+ if(!movable_parent.Process_Spacemove(drifting_loop.direction, continuous_move = TRUE))
+ return
+ qdel(src)
+
+/// We're going to take the passed in glide size
+/// and use it to manually delay our loop for that period
+/// to allow the other movement to complete
+/datum/component/drift/proc/handle_glidesize_update(datum/source, glide_size)
+ SIGNAL_HANDLER
+ // If we aren't drifting, or this is us, fuck off
+ var/atom/movable/movable_parent = parent
+ if(!drifting_loop || movable_parent.inertia_moving)
+ return
+ // If we are drifting, but this set came from the moveloop itself, drop the input
+ // I'm sorry man
+ if(ignore_next_glide)
+ ignore_next_glide = FALSE
+ return
+ var/glide_delay = round(world.icon_size / glide_size, 1) * world.tick_lag
+ drifting_loop.pause_for(glide_delay)
+ delayed = TRUE
+
+/// If we're pulling something and stop, we want it to continue at our rate and such
+/datum/component/drift/proc/stopped_pulling(datum/source, atom/movable/was_pulling)
+ SIGNAL_HANDLER
+ // This does mean it falls very slightly behind, but otherwise they'll potentially run into us
+ var/next_move_in = drifting_loop.timer - world.time + world.tick_lag
+ was_pulling.newtonian_move(drifting_loop.direction, start_delay = next_move_in)
+
+/datum/component/drift/proc/glide_to_halt(glide_for)
+ if(!ismob(parent))
+ qdel(src)
+ return
+
+ var/mob/mob_parent = parent
+ var/client/our_client = mob_parent.client
+ // If we're not active, don't do the glide because it'll look dumb as fuck
+ if(!our_client || delayed)
+ qdel(src)
+ return
+
+ block_inputs_until = world.time + glide_for
+ QDEL_IN(src, glide_for + 1)
+ qdel(drifting_loop)
+ RegisterSignal(parent, COMSIG_MOB_CLIENT_PRE_MOVE, PROC_REF(allow_final_movement))
+
+/datum/component/drift/proc/allow_final_movement(datum/source)
+ // Some things want to allow movement out of spacedrift, we should let them
+ if(SEND_SIGNAL(parent, COMSIG_MOVABLE_DRIFT_BLOCK_INPUT) & DRIFT_ALLOW_INPUT)
+ return
+ if(world.time < block_inputs_until)
+ return COMSIG_MOB_CLIENT_BLOCK_PRE_MOVE
diff --git a/code/controllers/subsystems/movement/move_handler.dm b/code/datums/move_manager.dm
similarity index 91%
rename from code/controllers/subsystems/movement/move_handler.dm
rename to code/datums/move_manager.dm
index fcc5c1c6504..23ddcbecdb7 100644
--- a/code/controllers/subsystems/movement/move_handler.dm
+++ b/code/datums/move_manager.dm
@@ -17,16 +17,15 @@
*
* You can find the logic for this control in this file
*
- * Specifics of how different loops operate can be found in the movement_types.dm file, alongside the [add to loop][/datum/controller/subsystem/move_manager/proc/add_to_loop] helper procs that use them
+ * Specifics of how different loops operate can be found in the movement_types.dm file, alongside the [add to loop][/datum/move_manager/proc/add_to_loop] helper procs that use them
*
**/
-SUBSYSTEM_DEF(move_manager)
- name = "Movement Handler"
- flags = SS_NO_INIT | SS_NO_FIRE
- runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
+/datum/move_manager
+
+GLOBAL_DATUM_INIT(move_manager, /datum/move_manager, new)
///Adds a movable thing to a movement subsystem. Returns TRUE if it all worked, FALSE if it failed somehow
-/datum/controller/subsystem/move_manager/proc/add_to_loop(atom/movable/thing_to_add, datum/controller/subsystem/movement/subsystem = SSmovement, datum/move_loop/loop_type, priority = MOVEMENT_DEFAULT_PRIORITY, flags, datum/extra_info)
+/datum/move_manager/proc/add_to_loop(atom/movable/thing_to_add, datum/controller/subsystem/movement/subsystem = SSmovement, datum/move_loop/loop_type, priority = MOVEMENT_DEFAULT_PRIORITY, flags, datum/extra_info)
var/datum/movement_packet/our_data = thing_to_add.move_packet
if(!our_data)
our_data = new(thing_to_add)
@@ -35,7 +34,7 @@ SUBSYSTEM_DEF(move_manager)
return our_data.add_loop(arglist(arguments))
///Returns the subsystem's loop if we're processing on it, null otherwise
-/datum/controller/subsystem/move_manager/proc/processing_on(atom/movable/packet_owner, datum/controller/subsystem/movement/subsystem)
+/datum/move_manager/proc/processing_on(atom/movable/packet_owner, datum/controller/subsystem/movement/subsystem)
var/datum/movement_packet/packet = packet_owner.move_packet
if(!packet)
return
diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm
index deaf2fdadc2..e27e7d88676 100644
--- a/code/game/atom/_atom.dm
+++ b/code/game/atom/_atom.dm
@@ -6,6 +6,10 @@
*/
/atom
+
+ /// pass_flags that we are. If any of this matches a pass_flag on a moving thing, by default, we let them through.
+ var/pass_flags_self = NONE
+
///First atom flags var
var/flags_1 = NONE
@@ -103,6 +107,22 @@
. = ..()
+
+///Purpose: Determines if the object (or airflow) can pass this atom.
+///Called by: Movement, airflow.
+///Inputs: The moving atom (optional), target turf, "height" and air group
+///Outputs: Boolean if can pass.
+///**Please stop using this proc, use the `pass_flags_self` flags to determine what can pass unless you literally have no other choice**
+/atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
+ //I have condensed TG's `CanAllowThrough()` into this proc
+ if(mover) //Because some procs send null as a mover
+ if(mover.pass_flags & pass_flags_self)
+ return TRUE
+ if(mover.throwing && (pass_flags_self & LETPASSTHROW))
+ return TRUE
+
+ return (!density || !height || air_group)
+
/**
* An atom has entered this atom's contents
*
@@ -193,6 +213,6 @@
* If this is NOT you, ensure you edit your can_astar_pass variable. Check __DEFINES/path.dm
**/
/atom/proc/CanAStarPass(to_dir, datum/can_pass_info/pass_info)
- if(pass_info.pass_flags & pass_flags)
+ if(pass_info.pass_flags & pass_flags_self)
return TRUE
. = !density
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 4ac5e9a6910..bcdf9dfb2ae 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -252,8 +252,6 @@
return
/atom/proc/hitby(atom/movable/AM as mob|obj, var/speed = THROWFORCE_SPEED_DIVISOR)
- if(density)
- AM.throwing = 0
return
/atom/proc/add_hiddenprint(mob/living/M)
@@ -485,9 +483,6 @@
else
return 0
-/atom/proc/checkpass(passflag)
- return pass_flags&passflag
-
/atom/proc/isinspace()
if(istype(get_turf(src), /turf/space))
return 1
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 560597d594c..cc96ac8baf4 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -19,9 +19,7 @@
var/move_speed = 10
var/l_move_time = 1
- var/throwing = 0
- var/thrower
- var/turf/throw_source = null
+ var/datum/thrownthing/throwing = null
var/throw_speed = 2
var/throw_range = 7
var/moved_recently = 0
@@ -39,6 +37,11 @@
var/can_hold_mob = FALSE
var/list/contained_mobs
+ ///Are we moving with inertia? Mostly used as an optimization
+ var/inertia_moving = FALSE
+ ///Delay in deciseconds between inertia based movement
+ var/inertia_move_delay = 5
+
///Holds information about any movement loops currently running/waiting to run on the movable. Lazy, will be null if nothing's going on
var/datum/movement_packet/move_packet
@@ -141,42 +144,43 @@
// This is called when this atom is prevented from moving by atom/A.
/atom/movable/proc/Collide(atom/A)
+ SHOULD_NOT_SLEEP(TRUE)
if(airflow_speed > 0 && airflow_dest)
airflow_hit(A)
else
airflow_speed = 0
airflow_time = 0
- if (throwing)
- throwing = FALSE
+ if(!QDELETED(throwing))
. = TRUE
- if (!QDELETED(A))
- throw_impact(A)
+ if(!QDELETED(A))
+ throw_impact(A, throwing)
A.CollidedWith(src)
+ throwing?.finalize(hit = TRUE, target = A)
else if (!QDELETED(A))
A.CollidedWith(src)
//called when src is thrown into hit_atom
-/atom/movable/proc/throw_impact(atom/hit_atom, var/speed)
+/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(isliving(hit_atom))
var/mob/living/M = hit_atom
- M.hitby(src,speed)
+ M.hitby(src, throwingdatum.speed)
else if(isobj(hit_atom))
var/obj/O = hit_atom
if(!O.anchored)
step(O, src.last_move)
- O.hitby(src,speed)
+ O.hitby(src, throwingdatum.speed)
else if(isturf(hit_atom))
- throwing = 0
+ throwing?.finalize(hit = FALSE)
var/turf/T = hit_atom
if(T.density)
step(src, turn(src.last_move, 180))
if(isliving(src))
var/mob/living/M = src
- M.turf_collision(T, speed)
+ M.turf_collision(T, throwingdatum.speed)
//decided whether a movable atom being thrown can pass through the turf it is in.
/atom/movable/proc/hit_check(var/speed, var/target)
@@ -206,90 +210,91 @@
return TRUE
-/atom/movable/proc/throw_at(atom/target, range, speed, thrower, var/do_throw_animation = TRUE)
- if(!target || !src) return 0
- //use a modified version of Bresenham's algorithm to get from the atom's current position to that of the target
+/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE, quickstart = TRUE)
+ . = FALSE
- src.throwing = 1
- src.thrower = thrower
- src.throw_source = get_turf(src) //store the origin turf
+ if(QDELETED(src))
+ CRASH("Qdeleted thing being thrown around.")
- if(usr && (usr.mutations & HULK))
- src.throwing = 2 // really strong throw!
+ if (!target || speed <= 0)
+ return
- var/dist_travelled = 0
- var/dist_since_sleep = 0
- var/area/a = get_area(src.loc)
+ if(SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_THROW, args) & COMPONENT_CANCEL_THROW)
+ return
+
+ // if (pulledby)
+ // pulledby.stop_pulling()
+
+ //They are moving! Wouldn't it be cool if we calculated their momentum and added it to the throw?
+ if (thrower && thrower.last_move && thrower.client && thrower.client.move_delay >= world.time + world.tick_lag*2)
+ var/user_momentum = world.tick_lag //Used to be thrower.cached_multiplicative_slowdown but we don't have this
+ if (!user_momentum) //no movement_delay, this means they move once per byond tick, lets calculate from that instead.
+ user_momentum = world.tick_lag
+
+ user_momentum = 1 / user_momentum // convert from ds to the tiles per ds that throw_at uses.
+
+ if (get_dir(thrower, target) & last_move)
+ user_momentum = user_momentum //basically a noop, but needed
+ else if (get_dir(target, thrower) & last_move)
+ user_momentum = -user_momentum //we are moving away from the target, lets slowdown the throw accordingly
+ else
+ user_momentum = 0
+
+
+ if (user_momentum)
+ //first lets add that momentum to range.
+ range *= (user_momentum / speed) + 1
+ //then lets add it to speed
+ speed += user_momentum
+ if (speed <= 0)
+ return//no throw speed, the user was moving too fast.
+
+ . = TRUE // No failure conditions past this point.
+
+ var/target_zone
+ if(QDELETED(thrower))
+ thrower = null //Let's not pass a qdeleting reference if any.
+ else
+ target_zone = thrower.zone_sel
+
+ var/datum/thrownthing/thrown_thing = new(src, target, get_dir(src, target), range, speed, thrower, diagonals_first, force, gentle, callback, target_zone)
var/dist_x = abs(target.x - src.x)
var/dist_y = abs(target.y - src.y)
+ var/dx = (target.x > src.x) ? EAST : WEST
+ var/dy = (target.y > src.y) ? NORTH : SOUTH
- var/dx
- if (target.x > src.x)
- dx = EAST
- else
- dx = WEST
+ if (dist_x == dist_y)
+ thrown_thing.pure_diagonal = 1
- var/dy
- if (target.y > src.y)
- dy = NORTH
- else
- dy = SOUTH
- var/error
- var/major_dir
- var/major_dist
- var/minor_dir
- var/minor_dist
- if(dist_x > dist_y)
- error = dist_x/2 - dist_y
- major_dir = dx
- major_dist = dist_x
- minor_dir = dy
- minor_dist = dist_y
- else
- error = dist_y/2 - dist_x
- major_dir = dy
- major_dist = dist_y
- minor_dir = dx
- minor_dist = dist_x
+ else if(dist_x <= dist_y)
+ var/olddist_x = dist_x
+ var/olddx = dx
+ dist_x = dist_y
+ dist_y = olddist_x
+ dx = dy
+ dy = olddx
+ thrown_thing.dist_x = dist_x
+ thrown_thing.dist_y = dist_y
+ thrown_thing.dx = dx
+ thrown_thing.dy = dy
+ thrown_thing.diagonal_error = dist_x/2 - dist_y
+ thrown_thing.start_time = world.time
- while(src && target && src.throwing && istype(src.loc, /turf) \
- && ((abs(target.x - src.x)+abs(target.y - src.y) > 0 && dist_travelled < range) \
- || (a && a.has_gravity == 0) \
- || istype(src.loc, /turf/space)))
- // only stop when we've gone the whole distance (or max throw range) and are on a non-space tile, or hit something, or hit the end of the map, or someone picks it up
- var/atom/step
- if(error >= 0)
- step = get_step(src, major_dir)
- error -= minor_dist
- else
- step = get_step(src, minor_dir)
- error += major_dist
- if(!step) // going off the edge of the map makes get_step return null, don't let things go off the edge
- break
- src.Move(step)
- hit_check(speed, target)
- dist_travelled++
- dist_since_sleep++
- if(dist_since_sleep >= speed)
- dist_since_sleep = 0
- sleep(1)
- a = get_area(src.loc)
- // and yet it moves
- if(do_throw_animation)
- if(src.does_spin)
- src.SpinAnimation(speed = 4, loops = 1)
+ // if(pulledby)
+ // pulledby.stop_pulling()
+ if (quickstart && (throwing || SSthrowing.state == SS_RUNNING)) //Avoid stack overflow edgecases.
+ quickstart = FALSE
+ throwing = thrown_thing
+ if(spin)
+ SpinAnimation(5, 1)
- //done throwing, either because it hit something or it finished moving
- if(isturf(loc) && isobj(src))
- throw_impact(loc, speed)
- src.throwing = 0
- src.thrower = null
- src.throw_source = null
-
- if (isturf(loc))
- var/turf/Tloc = loc
- Tloc.Entered(src)
+ SEND_SIGNAL(src, COMSIG_MOVABLE_POST_THROW, thrown_thing, spin)
+ SSthrowing.processing[src] = thrown_thing
+ if (SSthrowing.state == SS_PAUSED && length(SSthrowing.currentrun))
+ SSthrowing.currentrun[src] = thrown_thing
+ if (quickstart)
+ thrown_thing.tick()
/atom/movable/proc/throw_at_random(var/include_own_turf, var/maxrange, var/speed)
var/list/turfs = RANGE_TURFS(maxrange, src)
@@ -742,3 +747,49 @@
/atom/movable/proc/show_message(msg, type, alt, alt_type) //Message, type of message (1 or 2), alternative message, alt message type (1 or 2)
return
+
+/**
+ * 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]
+ *
+ * Return FALSE to have src start/keep drifting in a no-grav area and TRUE to stop/not start drifting
+ *
+ * Mobs should return 1 if they should be able to move of their own volition, see [/client/proc/Move]
+ *
+ * Arguments:
+ * * movement_dir - 0 when stopping or any dir when trying to move
+ * * continuous_move - If this check is coming from something in the context of already drifting
+ */
+/atom/movable/proc/Process_Spacemove(movement_dir = 0, continuous_move = FALSE)
+ if(has_gravity())
+ return TRUE
+
+ if(SEND_SIGNAL(src, COMSIG_MOVABLE_SPACEMOVE, movement_dir, continuous_move) & COMSIG_MOVABLE_STOP_SPACEMOVE)
+ return TRUE
+
+ if(pulledby && (pulledby.pulledby != src)) //Different from TG
+ return TRUE
+
+ if(throwing)
+ return TRUE
+
+ if(!isturf(loc))
+ return TRUE
+
+ if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier
+ return TRUE
+
+ return FALSE
+
+/// Only moves the object if it's under no gravity
+/// Accepts the direction to move, if the push should be instant, and an optional parameter to fine tune the start delay
+/atom/movable/proc/newtonian_move(direction, instant = FALSE, start_delay = 0)
+ if(!isturf(loc) || Process_Spacemove(direction, continuous_move = TRUE))
+ return FALSE
+
+ if(SEND_SIGNAL(src, COMSIG_MOVABLE_NEWTONIAN_MOVE, direction, start_delay) & COMPONENT_MOVABLE_NEWTONIAN_BLOCK)
+ return TRUE
+
+ AddComponent(/datum/component/drift, direction, instant, start_delay)
+
+ return TRUE
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index 5dbc23f3466..97874902637 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -4,6 +4,7 @@
desc_info = "Click your target with Grab intent, then click on the table with an empty hand, to place them on it."
icon = 'icons/obj/surgery.dmi'
icon_state = "table2-idle"
+ pass_flags_self = PASSTABLE
density = TRUE
anchored = TRUE
use_power = POWER_USE_IDLE
@@ -162,12 +163,6 @@
user.visible_message(SPAN_NOTICE("\The [user] switches [suppressing ? "on" : "off"] \the [src]'s neural suppressor."), intent_message = BUTTON_FLICK)
playsound(loc, /singleton/sound_category/switch_sound, 50, 1)
-/obj/machinery/optable/CanPass(atom/movable/mover, turf/target, height = 0, air_group = 0)
- if(air_group || (height == 0))
- return FALSE
-
- return istype(mover) && mover.checkpass(PASSTABLE)
-
/**
* Refreshes the icon state based on the table status
*/
diff --git a/code/game/machinery/chem_heater.dm b/code/game/machinery/chem_heater.dm
index ce2e76b569a..8b9080a3b5a 100644
--- a/code/game/machinery/chem_heater.dm
+++ b/code/game/machinery/chem_heater.dm
@@ -8,6 +8,7 @@
use_power = POWER_USE_OFF
idle_power_usage = 100
density = 1
+ pass_flags_self = PASSMACHINE | LETPASSTHROW
anchored = 1
var/obj/item/reagent_containers/container
var/target_temperature = 300 //Measured in kelvin.
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index 760e04408f6..ebd9297d6ad 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -204,7 +204,7 @@
return 1
else
return 0
- else if(mover.checkpass(PASSTABLE) && can_pass_under)
+ else if((mover.pass_flags & PASSTABLE) && can_pass_under)
//Animals can run under them, lots of empty space
return 1
return ..()
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index 705563f73e4..5645b029f3b 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -237,7 +237,7 @@
return TRUE
else
return FALSE
- else if(mover.checkpass(PASSTABLE)) // Animals can run under them, lots of empty space
+ else if(mover.pass_flags & PASSTABLE) // Animals can run under them, lots of empty space
return TRUE
return ..()
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index ef97a90c2aa..8ba4db2c128 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -114,7 +114,7 @@ Deployable Kits
return prob(35)
if(isliving(mover))
return FALSE
- if(istype(mover) && mover.checkpass(PASSTABLE))
+ if(istype(mover) && mover.pass_flags & PASSTABLE)
return TRUE
return FALSE
@@ -219,7 +219,7 @@ Deployable Kits
/obj/machinery/deployable/barrier/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)//So bullets will fly over and stuff.
if(air_group || (height==0))
return 1
- if(istype(mover) && mover.checkpass(PASSTABLE))
+ if(istype(mover) && mover.pass_flags & PASSTABLE)
return 1
else
return 0
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 1add0d79f52..34e0b9e576f 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -32,6 +32,7 @@
normalspeed = TRUE
pixel_x = -16
pixel_y = -16
+ pass_flags_self = PASSDOORS
/// Boolean. Whether or not the AI control mechanism is disabled.
var/ai_control_disabled = FALSE
/// Boolean. If set, the door cannot by hacked or bypassed by the AI.
@@ -1987,7 +1988,7 @@ About the new airlock wires panel:
var/has_opened_hatch = FALSE
for(var/turf/turf in locs)
for(var/atom/movable/AM in turf)
- if(hashatch && AM.checkpass(PASSDOORHATCH))
+ if(hashatch && AM.pass_flags & PASSDOORHATCH)
if(!has_opened_hatch)
open_hatch(AM)
has_opened_hatch = TRUE
diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm
index 27325da4fbe..cdf0bd50c40 100644
--- a/code/game/machinery/doors/blast_door.dm
+++ b/code/game/machinery/doors/blast_door.dm
@@ -17,6 +17,7 @@
dir = 1
closed_layer = ABOVE_WINDOW_LAYER
explosion_resistance = 25
+ pass_flags_self = PASSDOORS
/// Most blast doors are infrequently toggled and sometimes used with regular doors anyways.
/// Turning this off prevents awkward zone geometry in places like medbay lobby, for example.
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index aae31fa1cb7..ad4ab87ce34 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -209,9 +209,9 @@
/obj/machinery/door/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group) return !block_air_zones
if (istype(mover))
- if(mover.checkpass(PASSGLASS))
+ if(mover.pass_flags & PASSGLASS)
return !opacity
- if(density && hashatch && mover.checkpass(PASSDOORHATCH))
+ if(density && hashatch && mover.pass_flags & PASSDOORHATCH)
if (istype(mover, /mob/living/silicon/pai))
var/mob/living/silicon/pai/P = mover
if (allowed(P))
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index 593c56616d8..c9824dc0ecd 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -511,7 +511,7 @@
air_properties_vary_with_direction = 1
CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
- if(istype(mover) && mover.checkpass(PASSGLASS))
+ if(istype(mover) && mover.pass_flags & PASSGLASS)
return 1
if(get_dir(loc, target) == dir) //Make sure looking at appropriate border
if(air_group) return 0
@@ -520,7 +520,7 @@
return 1
CheckExit(atom/movable/mover as mob|obj, turf/target as turf)
- if(istype(mover) && mover.checkpass(PASSGLASS))
+ if(istype(mover) && mover.pass_flags & PASSGLASS)
return 1
if(get_dir(loc, target) == dir)
return !density
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index f119499bd9a..44e86fa129b 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -18,6 +18,7 @@
air_properties_vary_with_direction = 1
atmos_canpass = CANPASS_PROC
+ pass_flags_self = PASSGLASS
/obj/machinery/door/window/Initialize(mapload)
. = ..()
@@ -75,8 +76,6 @@
flick("[base_state]deny", src)
/obj/machinery/door/window/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
- if(istype(mover) && mover.checkpass(PASSGLASS))
- return 1
if(get_dir(loc, target) == dir) //Make sure looking at appropriate border
if(air_group) return 0
return !density
@@ -84,7 +83,7 @@
return 1
/obj/machinery/door/window/CheckExit(atom/movable/mover as mob|obj, turf/target as turf)
- if(istype(mover) && mover.checkpass(PASSGLASS))
+ if(istype(mover) && mover.pass_flags & PASSGLASS)
return 1
if(get_dir(loc, target) == dir)
return !density
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index 69148ac95fb..be1d97c65f6 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -8,6 +8,7 @@
icon_state = "iv_stand"
anchored = 0
density = FALSE
+ pass_flags_self = PASSTABLE
var/tipped = FALSE
var/last_full // Spam check
var/last_warning
@@ -73,8 +74,6 @@
/obj/machinery/iv_drip/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(istype(mover, /obj/machinery/iv_drip))
return FALSE
- if(height && istype(mover) && mover.checkpass(PASSTABLE)) //allow bullets, beams, thrown objects, rats, drones, and the like through.
- return TRUE
return ..()
/obj/machinery/iv_drip/Crossed(var/mob/H)
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 2cfc1a66879..e99d1f4450a 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -86,6 +86,7 @@ Class Procs:
w_class = ITEMSIZE_IMMENSE
layer = STRUCTURE_LAYER
init_flags = INIT_MACHINERY_PROCESS_SELF
+ pass_flags_self = PASSMACHINE | LETPASSCLICKS
var/stat = 0
var/emagged = 0
diff --git a/code/game/objects/effects/chem/chemsmoke.dm b/code/game/objects/effects/chem/chemsmoke.dm
index 97c573dbe0e..8667c78b245 100644
--- a/code/game/objects/effects/chem/chemsmoke.dm
+++ b/code/game/objects/effects/chem/chemsmoke.dm
@@ -27,10 +27,10 @@
//float over to our destination, if we have one
destination = dest_turf
if(destination)
- SSmove_manager.move_to(src, destination, priority = MOVEMENT_SPACE_PRIORITY)
+ GLOB.move_manager.move_to(src, destination, priority = MOVEMENT_SPACE_PRIORITY)
/obj/effect/effect/smoke/chem/Destroy()
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
return ..()
/obj/effect/effect/smoke/chem/Move()
diff --git a/code/game/objects/effects/chem/foam.dm b/code/game/objects/effects/chem/foam.dm
index 3248b2e849b..eaa003e0327 100644
--- a/code/game/objects/effects/chem/foam.dm
+++ b/code/game/objects/effects/chem/foam.dm
@@ -238,4 +238,4 @@
/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
if(air_group)
return 0
- return !density
+ return ..()
diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm
index dcc58baad50..1a41692751e 100644
--- a/code/game/objects/effects/spiders.dm
+++ b/code/game/objects/effects/spiders.dm
@@ -230,7 +230,7 @@
var/list/nearby = oview(5, src)
if(nearby.len)
var/target_atom = pick(nearby)
- SSmove_manager.move_to(src, target_atom, 0, 5)
+ GLOB.move_manager.move_to(src, target_atom, 0, 5)
if(prob(25))
src.visible_message(SPAN_NOTICE("\The [src] skitters[pick(" away"," around","")]."))
else if(prob(5))
@@ -238,7 +238,7 @@
for(var/obj/machinery/atmospherics/unary/vent_pump/v in view(7,src))
if(!v.welded)
entry_vent = v
- SSmove_manager.move_to(src, entry_vent, 0, 5)
+ GLOB.move_manager.move_to(src, entry_vent, 0, 5)
break
if(isturf(loc) && amount_grown >= 100)
@@ -275,7 +275,7 @@
visible_message(SPAN_WARNING("\The [user] tries to stomp on \the [src], but misses!"))
var/list/nearby = oview(2, src)
if(length(nearby))
- SSmove_manager.move_to(src, pick(nearby), 0, 2)
+ GLOB.move_manager.move_to(src, pick(nearby), 0, 2)
return
visible_message(SPAN_WARNING("\The [user] stomps \the [src] dead!"))
die()
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 2ee40c82f90..0126945c665 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -400,7 +400,7 @@
src.pickup(user)
if(S)
S.remove_from_storage(src)
- src.throwing = 0
+ QDEL_NULL(throwing)
if (src.loc == user)
if(!user.prepare_for_slotmove(src))
return
@@ -449,7 +449,7 @@
else
return 0
-/obj/item/throw_impact(atom/hit_atom)
+/obj/item/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(isliving(hit_atom)) //Living mobs handle hit sounds differently.
var/mob/living/L = hit_atom
if(L.in_throw_mode)
diff --git a/code/game/objects/items/weapons/cigs_lighters.dm b/code/game/objects/items/weapons/cigs_lighters.dm
index d442cbd3e3b..d6d60f00475 100644
--- a/code/game/objects/items/weapons/cigs_lighters.dm
+++ b/code/game/objects/items/weapons/cigs_lighters.dm
@@ -984,8 +984,9 @@ CIGARETTE PACKETS ARE IN FANCY.DM
else
..()
-/obj/item/flame/lighter/throw_impact(mob/living/carbon/M as mob)
+/obj/item/flame/lighter/throw_impact(atom/hit_atom)
. = ..()
+ var/mob/living/carbon/M = hit_atom
if(istype(M) && lit && M.IgniteMob())
M.visible_message(SPAN_DANGER("\The [M] is ignited by \the [src]!"))
diff --git a/code/game/objects/items/weapons/material/twohanded.dm b/code/game/objects/items/weapons/material/twohanded.dm
index 75a94460182..2b04b6c02c7 100644
--- a/code/game/objects/items/weapons/material/twohanded.dm
+++ b/code/game/objects/items/weapons/material/twohanded.dm
@@ -309,7 +309,7 @@
update_icon()
src.shatter()
-/obj/item/material/twohanded/spear/throw_impact(atom/target)
+/obj/item/material/twohanded/spear/throw_impact(atom/hit_atom)
. = ..()
if(!.) //not caught
if(explosive)
diff --git a/code/game/objects/items/weapons/policetape.dm b/code/game/objects/items/weapons/policetape.dm
index e237c568264..adc80fa8fb7 100644
--- a/code/game/objects/items/weapons/policetape.dm
+++ b/code/game/objects/items/weapons/policetape.dm
@@ -6,6 +6,7 @@ var/list/tape_roll_applications = list()
icon = 'icons/obj/policetape.dmi'
icon_state = "tape"
w_class = ITEMSIZE_SMALL
+ pass_flags_self = PASSTABLE
var/static/list/hazard_overlays
var/turf/start
var/turf/end
diff --git a/code/game/objects/structures/barricades/_barricade.dm b/code/game/objects/structures/barricades/_barricade.dm
index 2d7b3c5dbd9..c2b98177147 100644
--- a/code/game/objects/structures/barricades/_barricade.dm
+++ b/code/game/objects/structures/barricades/_barricade.dm
@@ -104,7 +104,7 @@
return TRUE
/obj/structure/barricade/CheckExit(atom/movable/O as mob|obj, target as turf)
- if(istype(O) && O.checkpass(PASSTABLE))
+ if(istype(O) && O.pass_flags & PASSTABLE)
return TRUE
if (get_dir(loc, target) == dir)
return !density
diff --git a/code/game/objects/structures/bonfire.dm b/code/game/objects/structures/bonfire.dm
index fca398d1528..83097421734 100644
--- a/code/game/objects/structures/bonfire.dm
+++ b/code/game/objects/structures/bonfire.dm
@@ -11,6 +11,7 @@ GLOBAL_LIST_EMPTY(total_active_bonfires)
density = FALSE
light_color = LIGHT_COLOR_FIRE
build_amt = 20
+ pass_flags_self = PASSTABLE | LETPASSTHROW
var/fuel = 2000
var/max_fuel = 2000
var/on_fire = FALSE
@@ -344,6 +345,7 @@ GLOBAL_LIST_EMPTY(total_active_bonfires)
safe = TRUE
density = TRUE
burn_out = FALSE
+ pass_flags_self = PASSTABLE
/obj/structure/bonfire/fireplace/New(var/newloc, var/material_name)
..()
@@ -373,8 +375,6 @@ GLOBAL_LIST_EMPTY(total_active_bonfires)
AddOverlays("fireplace_glow")
/obj/structure/bonfire/fireplace/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
- if(!istype(mover) || mover.checkpass(PASSTABLE))
- return TRUE
if(get_dir(loc, target) == NORTH)
return !density
return TRUE
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 438789e7faa..d9d698e011b 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -6,6 +6,7 @@
density = TRUE
build_amt = 2
slowdown = 5
+ pass_flags_self = PASSTRACE
var/icon_door = null
/// Override to have open overlay use icon different to its base's
@@ -139,9 +140,7 @@
/obj/structure/closet/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0 || wall_mounted)) return 1
- if(istype(mover) && mover.checkpass(PASSTRACE))
- return 1
- return (!density)
+ return ..()
/obj/structure/closet/proc/can_open()
if(welded || locked)
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index b188b8d526d..92193b26356 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -20,6 +20,8 @@
door_anim_time = 3
door_anim_angle = 140
door_hinge = 3.5
+ pass_flags_self = PASSSTRUCTURE | LETPASSTHROW
+
var/tablestatus = 0
var/azimuth_angle_2 = 180 //in this context the azimuth angle for over 90 degree
@@ -96,7 +98,7 @@
if (istype(mover,/obj/item/projectile))
// Crates on a table always block shots, otherwise they only occasionally do so.
return tablestatus == ABOVE_TABLE ? FALSE : (prob(15) ? FALSE : TRUE)
- else if(istype(mover) && mover.checkpass(PASSTABLE) && tablestatus == ABOVE_TABLE)
+ else if((istype(mover) && (mover.pass_flags & PASSTABLE)) && tablestatus == ABOVE_TABLE)
return TRUE
return ..()
diff --git a/code/game/objects/structures/full_window_frame.dm b/code/game/objects/structures/full_window_frame.dm
index 5e07fc774ce..43c9703b0c7 100644
--- a/code/game/objects/structures/full_window_frame.dm
+++ b/code/game/objects/structures/full_window_frame.dm
@@ -50,7 +50,7 @@
return TRUE
if(istype(mover, /obj/structure/closet/crate))
return TRUE
- if(istype(mover) && mover.checkpass(PASSTABLE))
+ if(istype(mover) && mover.pass_flags & PASSTABLE)
return TRUE
if(locate(/obj/structure/window_frame) in get_turf(mover))
return TRUE
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index 849c2780dfd..815fbc4a48f 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -10,6 +10,7 @@
layer = BELOW_OBJ_LAYER
w_class = ITEMSIZE_HUGE
obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED
+ pass_flags_self = PASSTABLE
var/state = 0
var/health = 200
var/cover = 50 //how much cover the girder provides against projectiles.
@@ -380,7 +381,4 @@
return 1
else
return 0
- else if(mover.checkpass(PASSTABLE))
-//Animals can run under them, lots of empty space
- return 1
return ..()
diff --git a/code/game/objects/structures/gore/core.dm b/code/game/objects/structures/gore/core.dm
index 4e0a96891fc..cae9c9fdb71 100644
--- a/code/game/objects/structures/gore/core.dm
+++ b/code/game/objects/structures/gore/core.dm
@@ -78,6 +78,6 @@
/obj/structure/gore/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group)
return FALSE
- if(istype(mover) && mover.checkpass(PASSGLASS))
+ if(istype(mover) && mover.pass_flags & PASSGLASS)
return !opacity
return !density
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index dcbad401da1..1d8885fd3aa 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -102,7 +102,7 @@
/obj/structure/grille/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0)) return 1
- if(istype(mover) && mover.checkpass(PASSGRILLE))
+ if(istype(mover) && mover.pass_flags & PASSGRILLE)
return 1
else
if(istype(mover, /obj/item/projectile))
diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm
index 17932ad18c4..3f65a7de442 100644
--- a/code/game/objects/structures/janicart.dm
+++ b/code/game/objects/structures/janicart.dm
@@ -422,7 +422,7 @@
/obj/structure/janitorialcart/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0)) return 1
- if(istype(mover) && mover.checkpass(PASSTABLE))
+ if(istype(mover) && mover.pass_flags & PASSTABLE)
return 1
if(istype(mover, /mob/living) && mover == pulling)
return 1
diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm
index 87e97006c76..0d581b40376 100644
--- a/code/game/objects/structures/kitchen_spike.dm
+++ b/code/game/objects/structures/kitchen_spike.dm
@@ -7,6 +7,7 @@
desc = "A spike for collecting meat from animals."
density = 1
anchored = 1
+ pass_flags_self = PASSTABLE
var/meat = 0
var/occupied
var/meat_type
@@ -72,7 +73,4 @@
return 1
else
return 0
- else if(mover.checkpass(PASSTABLE))
-//Animals can run under them, lots of empty space
- return 1
return ..()
diff --git a/code/game/objects/structures/plasticflaps.dm b/code/game/objects/structures/plasticflaps.dm
index 1c4ffc7f2c1..113c9175e2a 100644
--- a/code/game/objects/structures/plasticflaps.dm
+++ b/code/game/objects/structures/plasticflaps.dm
@@ -57,7 +57,7 @@
return FALSE
/obj/structure/plasticflaps/CanPass(atom/A, turf/T)
- if(istype(A) && A.checkpass(PASSGLASS))
+ if(istype(A) && A.pass_flags & PASSGLASS)
return prob(60)
var/obj/structure/bed/B = A
diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm
index 50fcf2676c0..bfc6ab5ccc5 100644
--- a/code/game/objects/structures/railing.dm
+++ b/code/game/objects/structures/railing.dm
@@ -8,6 +8,7 @@
climbable = TRUE
layer = OBJ_LAYER
anchored = FALSE
+ pass_flags_self = LETPASSTHROW|PASSSTRUCTURE
atom_flags = ATOM_FLAG_CHECKS_BORDER
obj_flags = OBJ_FLAG_ROTATABLE|OBJ_FLAG_MOVES_UNSUPPORTED
@@ -89,7 +90,7 @@
/obj/structure/railing/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(istype(mover,/obj/item/projectile))
return TRUE
- if(!istype(mover) || mover.checkpass(PASSRAILING))
+ if(!istype(mover) || mover.pass_flags & PASSRAILING)
return TRUE
if(mover.throwing)
return TRUE
diff --git a/code/game/objects/structures/stool_bed_chair_nest/bed.dm b/code/game/objects/structures/stool_bed_chair_nest/bed.dm
index cbd5331c6a3..5db46197f0a 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/bed.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/bed.dm
@@ -27,6 +27,7 @@
buckle_dir = SOUTH
buckle_lying = 1
build_amt = 2
+ pass_flags_self = PASSTABLE
var/material/padding_material
var/base_icon = "bed"
@@ -127,10 +128,7 @@
buckled.forceMove(dest)
/obj/structure/bed/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
- if(istype(mover) && mover.checkpass(PASSTABLE))
- return 1
- else
- return ..()
+ return ..()
/obj/structure/bed/ex_act(severity)
switch(severity)
diff --git a/code/game/objects/structures/urban.dm b/code/game/objects/structures/urban.dm
index 8bc97168ecd..06254707689 100644
--- a/code/game/objects/structures/urban.dm
+++ b/code/game/objects/structures/urban.dm
@@ -265,7 +265,7 @@
/obj/structure/rod_railing/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(istype(mover,/obj/item/projectile))
return TRUE
- if(!istype(mover) || mover.checkpass(PASSRAILING))
+ if(!istype(mover) || mover.pass_flags & PASSRAILING)
return TRUE
if(mover.throwing)
return TRUE
@@ -317,7 +317,7 @@
/obj/structure/road_barrier/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(istype(mover,/obj/item/projectile))
return TRUE
- if(!istype(mover) || mover.checkpass(PASSRAILING))
+ if(!istype(mover) || mover.pass_flags & PASSRAILING)
return TRUE
if(mover.throwing)
return TRUE
@@ -356,7 +356,7 @@
return prob(35)
if(isliving(mover))
return FALSE
- if(istype(mover) && mover.checkpass(PASSTABLE))
+ if(istype(mover) && mover.pass_flags & PASSTABLE)
return TRUE
return FALSE
@@ -382,7 +382,7 @@
/obj/structure/rope_railing/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(istype(mover,/obj/item/projectile))
return TRUE
- if(!istype(mover) || mover.checkpass(PASSRAILING))
+ if(!istype(mover) || mover.pass_flags & PASSRAILING)
return TRUE
if(mover.throwing)
return TRUE
diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm
index cf2cdc723fa..a8aaeb413d6 100644
--- a/code/game/objects/structures/windoor_assembly.dm
+++ b/code/game/objects/structures/windoor_assembly.dm
@@ -49,7 +49,7 @@
icon_state = "[facing]_[secure]windoor_assembly[state]"
/obj/structure/windoor_assembly/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
- if(istype(mover) && mover.checkpass(PASSGLASS))
+ if(istype(mover) && mover.pass_flags & PASSGLASS)
return 1
if(get_dir(loc, target) == dir) //Make sure looking at appropriate border
if(air_group) return 0
@@ -58,7 +58,7 @@
return 1
/obj/structure/windoor_assembly/CheckExit(atom/movable/mover as mob|obj, turf/target as turf)
- if(istype(mover) && mover.checkpass(PASSGLASS))
+ if(istype(mover) && mover.pass_flags & PASSGLASS)
return 1
if(get_dir(loc, target) == dir)
return !density
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 043cc6ae88c..a0a3a4d4e9f 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -167,7 +167,7 @@
return (dir == SOUTHWEST || dir == SOUTHEAST || dir == NORTHWEST || dir == NORTHEAST)
/obj/structure/window/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
- if(istype(mover) && mover.checkpass(PASSGLASS))
+ if(istype(mover) && mover.pass_flags & PASSGLASS)
return 1
if(is_full_window())
return !density //full tile window, you can't move into it if it's solid!
@@ -177,7 +177,7 @@
return 1
/obj/structure/window/CheckExit(atom/movable/O, turf/target)
- if(istype(O) && O.checkpass(PASSGLASS))
+ if(istype(O) && O.pass_flags & PASSGLASS)
return 1
if(get_dir(O.loc, target) == dir)
return 0
diff --git a/code/game/turfs/flooring/urban.dm b/code/game/turfs/flooring/urban.dm
index 6668777009c..f9119ff11f3 100644
--- a/code/game/turfs/flooring/urban.dm
+++ b/code/game/turfs/flooring/urban.dm
@@ -96,7 +96,7 @@
/obj/structure/ledge/roof/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(istype(mover,/obj/item/projectile))
return TRUE
- if(!istype(mover) || mover.checkpass(PASSRAILING))
+ if(!istype(mover) || mover.pass_flags & PASSRAILING)
return TRUE
if(mover.throwing)
return TRUE
diff --git a/code/game/turfs/simulated/shuttle_turfs.dm b/code/game/turfs/simulated/shuttle_turfs.dm
index 52ecd0e2a66..1bab12e263c 100644
--- a/code/game/turfs/simulated/shuttle_turfs.dm
+++ b/code/game/turfs/simulated/shuttle_turfs.dm
@@ -186,12 +186,6 @@
atmos_canpass = CANPASS_DENSITY
obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED|OBJ_FLAG_NOFALL
-/obj/structure/shuttle_part/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
- if(density)
- return 0
- else
- return ..()
-
/obj/structure/window/shuttle/unique
name = "shuttle window"
desc = "It looks extremely strong. Might take many good hits to crack it."
diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm
index 1eec4b017c5..6df426177c3 100644
--- a/code/game/turfs/simulated/walls.dm
+++ b/code/game/turfs/simulated/walls.dm
@@ -80,7 +80,7 @@
STOP_PROCESSING(SSprocessing, src)
/turf/simulated/wall/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
- if(!opacity && istype(mover) && mover.checkpass(PASSGLASS))
+ if(!opacity && istype(mover) && mover.pass_flags & PASSGLASS)
return TRUE
return ..()
diff --git a/code/modules/clothing/spacesuits/rig/modules/utility.dm b/code/modules/clothing/spacesuits/rig/modules/utility.dm
index 25137278086..b3d4cf0a0cb 100644
--- a/code/modules/clothing/spacesuits/rig/modules/utility.dm
+++ b/code/modules/clothing/spacesuits/rig/modules/utility.dm
@@ -715,7 +715,7 @@
SPAN_WARNING("You leap horizontally at \the [T]!"),
SPAN_WARNING("You hear an electric whirr followed by a weighty thump!"))
H.face_atom(T)
- H.throw_at(T, leapDistance, 1, src, do_throw_animation = FALSE)
+ H.throw_at(T, leapDistance, 1, src, spin = FALSE)
return TRUE
else
var/turf/simulated/open/TA = GetAbove(src)
diff --git a/code/modules/heavy_vehicle/mech_interaction.dm b/code/modules/heavy_vehicle/mech_interaction.dm
index adb22c41f5c..3b9f0d8b4af 100644
--- a/code/modules/heavy_vehicle/mech_interaction.dm
+++ b/code/modules/heavy_vehicle/mech_interaction.dm
@@ -232,7 +232,7 @@
if(user.client) user.client.screen |= hud_elements
LAZYDISTINCTADD(user.additional_vision_handlers, src)
update_icon()
- SSmove_manager.stop_looping(src) // stop it from auto moving when the pilot gets in
+ GLOB.move_manager.stop_looping(src) // stop it from auto moving when the pilot gets in
return 1
/mob/living/heavy_vehicle/proc/eject(var/mob/user, var/silent)
@@ -705,7 +705,7 @@
// stop following who you were assigned to follow
if(findtext(text, "stop"))
unassign_following()
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
say("Holding position.")
return
diff --git a/code/modules/heavy_vehicle/mech_life.dm b/code/modules/heavy_vehicle/mech_life.dm
index 4980d15fa0c..ab0f5759264 100644
--- a/code/modules/heavy_vehicle/mech_life.dm
+++ b/code/modules/heavy_vehicle/mech_life.dm
@@ -67,11 +67,11 @@
if(following)
if(isturf(loc) && can_move())
if(resolved_following)
- SSmove_manager.move_to(src, resolved_following, follow_distance, legs.move_delay)
+ GLOB.move_manager.move_to(src, resolved_following, follow_distance, legs.move_delay)
else
unassign_following()
else
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
/mob/living/heavy_vehicle/get_cell(force)
RETURN_TYPE(/obj/item/cell)
diff --git a/code/modules/heavy_vehicle/mecha.dm b/code/modules/heavy_vehicle/mecha.dm
index e59b6fabde9..a4f221fb50b 100644
--- a/code/modules/heavy_vehicle/mecha.dm
+++ b/code/modules/heavy_vehicle/mecha.dm
@@ -10,6 +10,7 @@
can_be_buckled = FALSE
accent = ACCENT_TTS
appearance_flags = KEEP_TOGETHER
+ pass_flags_self = PASSVEHICLE
var/decal
var/emp_damage = 0
diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm
index 448fcedbb4d..9d9eafababc 100644
--- a/code/modules/hydroponics/trays/tray.dm
+++ b/code/modules/hydroponics/trays/tray.dm
@@ -232,7 +232,7 @@
/obj/machinery/portable_atmospherics/hydroponics/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0)) return TRUE
- if(istype(mover) && mover.checkpass(PASSTABLE))
+ if(istype(mover) && mover.pass_flags & PASSTABLE)
return TRUE
else
return !density
diff --git a/code/modules/mob/death.dm b/code/modules/mob/death.dm
index 96aaf48d8c3..b9fcd2d95bd 100644
--- a/code/modules/mob/death.dm
+++ b/code/modules/mob/death.dm
@@ -58,7 +58,7 @@
facing_dir = null
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
if(!gibbed && deathmessage != "no message") // This is gross, but reliable. Only brains use it.
src.visible_message("\The [src.name] [deathmessage]", range = messagerange)
diff --git a/code/modules/mob/living/carbon/alien/diona/life.dm b/code/modules/mob/living/carbon/alien/diona/life.dm
index 22d280b2d8c..ecfc609b1fc 100644
--- a/code/modules/mob/living/carbon/alien/diona/life.dm
+++ b/code/modules/mob/living/carbon/alien/diona/life.dm
@@ -48,6 +48,6 @@
if(!gestalt)
if(stat != DEAD)
if(master_nymph && !client && master_nymph != src)
- SSmove_manager.move_to(src, master_nymph, 1, movement_delay())
+ GLOB.move_manager.move_to(src, master_nymph, 1, movement_delay())
else
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 1f38ae71c6d..0ea22f2b46a 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -346,21 +346,21 @@ emp_act
var/throw_damage = O.throwforce*(speed/THROWFORCE_SPEED_DIVISOR)
var/zone
- if (istype(O.thrower, /mob/living))
- var/mob/living/L = O.thrower
+ if (istype(O.throwing?.thrower?.resolve(), /mob/living))
+ var/mob/living/L = O.throwing?.thrower?.resolve()
zone = check_zone(L.zone_sel.selecting)
else
zone = ran_zone(BP_CHEST,75) //Hits a random part of the body, geared towards the chest
//check if we hit
var/miss_chance = 15
- if (O.throw_source)
- var/distance = get_dist(O.throw_source, loc)
+ if (O.throwing?.thrower?.resolve())
+ var/distance = get_dist(O.throwing?.thrower?.resolve(), loc)
miss_chance = 15 * (distance - 2)
zone = get_zone_with_miss_chance(zone, src, miss_chance, 1)
- if(zone && O.thrower != src)
- var/shield_check = check_shields(throw_damage, O, thrower, zone, "[O]")
+ if(zone && O.throwing?.thrower?.resolve() != src)
+ var/shield_check = check_shields(throw_damage, O, throwing?.thrower?.resolve(), zone, "[O]")
if(shield_check == PROJECTILE_FORCE_MISS)
zone = null
else if(shield_check)
@@ -371,8 +371,6 @@ emp_act
playsound(src, 'sound/effects/throw_miss.ogg', rand(10, 50), 1)
return
- O.throwing = 0 //it hit, so stop moving
-
var/obj/item/organ/external/affecting = get_organ(zone)
var/hit_area = affecting.name
@@ -380,8 +378,8 @@ emp_act
SPAN_WARNING("You're hit in the [hit_area] by [O]!"))
apply_damage(throw_damage, dtype, zone, used_weapon = O, damage_flags = O.damage_flags(), armor_pen = O.armor_penetration)
- if(ismob(O.thrower))
- var/mob/M = O.thrower
+ if(ismob(O.throwing?.thrower?.resolve()))
+ var/mob/M = O.throwing?.thrower?.resolve()
var/client/assailant = M.client
if(assailant)
src.attack_log += text("\[[time_stamp()]\] Has been hit with a [O], thrown by [M.name] ([assailant.ckey])")
@@ -413,8 +411,8 @@ emp_act
mass = I.w_class/THROWNOBJ_KNOCKBACK_DIVISOR
var/momentum = speed*mass
- if(O.throw_source && momentum >= THROWNOBJ_KNOCKBACK_SPEED)
- var/dir = get_dir(O.throw_source, src)
+ if(O.throwing?.thrower?.resolve() && momentum >= THROWNOBJ_KNOCKBACK_SPEED)
+ var/dir = get_dir(O.throwing?.thrower?.resolve(), src)
visible_message(SPAN_WARNING("[src] staggers under the impact!"),
SPAN_WARNING("You stagger under the impact!"))
diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm
index abf3945cb12..b555d90d68d 100644
--- a/code/modules/mob/living/carbon/human/human_powers.dm
+++ b/code/modules/mob/living/carbon/human/human_powers.dm
@@ -167,7 +167,7 @@
visible_message(SPAN_DANGER("[src] leaps at [T]!"),
SPAN_DANGER("You leap at [T]!"))
- throw_at(get_step(get_turf(T), get_turf(src)), 4, 1, src, do_throw_animation = FALSE)
+ throw_at(get_step(get_turf(T), get_turf(src)), 4, 1, src, spin = FALSE)
sleep(5)
diff --git a/code/modules/mob/living/carbon/slime/slime.dm b/code/modules/mob/living/carbon/slime/slime.dm
index 6eb1fb98a05..b09aeea4312 100644
--- a/code/modules/mob/living/carbon/slime/slime.dm
+++ b/code/modules/mob/living/carbon/slime/slime.dm
@@ -202,7 +202,7 @@
if(istype(AM, /obj/structure/window) || istype(AM, /obj/structure/grille))
if(nutrition <= get_hunger_nutrition() && !Atkcool)
if(is_adult || prob(5))
- UnarmedAttack(AM)
+ INVOKE_ASYNC(src, PROC_REF(UnarmedAttack), AM)
Atkcool = TRUE
addtimer(CALLBACK(src, PROC_REF(reset_atkcooldown)), 45)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index e9e537cd1c8..39efe24c797 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -54,122 +54,121 @@ default behaviour is:
var/tmp/last_push_notif
/mob/living/Collide(atom/movable/AM)
- spawn
- if (now_pushing || !loc)
+ if (now_pushing || !loc)
+ return
+
+ now_pushing = TRUE
+ if (istype(AM, /mob/living))
+ var/mob/living/tmob = AM
+
+ for(var/mob/living/M in range(tmob, 1))
+ if(tmob.pinned.len || ((M.pulling == tmob && ( tmob.restrained() && !( M.restrained() ) && M.stat == 0)) || locate(/obj/item/grab, tmob.grabbed_by.len)) )
+ if (last_push_notif + 0.5 SECONDS <= world.time)
+ to_chat(src, SPAN_WARNING("[tmob] is restrained, you cannot push past"))
+ last_push_notif = world.time
+
+ now_pushing = FALSE
+ return
+ if( tmob.pulling == M && ( M.restrained() && !( tmob.restrained() ) && tmob.stat == 0) )
+ if (last_push_notif + 0.5 SECONDS <= world.time)
+ to_chat(src, SPAN_WARNING("[tmob] is restraining [M], you cannot push past"))
+ last_push_notif = world.time
+
+ now_pushing = FALSE
+ return
+
+ //Leaping mobs just land on the tile, no pushing, no anything.
+ if(status_flags & LEAPING)
+ forceMove(tmob.loc)
+ status_flags &= ~LEAPING
+ now_pushing = FALSE
return
- now_pushing = TRUE
- if (istype(AM, /mob/living))
- var/mob/living/tmob = AM
-
- for(var/mob/living/M in range(tmob, 1))
- if(tmob.pinned.len || ((M.pulling == tmob && ( tmob.restrained() && !( M.restrained() ) && M.stat == 0)) || locate(/obj/item/grab, tmob.grabbed_by.len)) )
- if (last_push_notif + 0.5 SECONDS <= world.time)
- to_chat(src, SPAN_WARNING("[tmob] is restrained, you cannot push past"))
- last_push_notif = world.time
-
- now_pushing = FALSE
- return
- if( tmob.pulling == M && ( M.restrained() && !( tmob.restrained() ) && tmob.stat == 0) )
- if (last_push_notif + 0.5 SECONDS <= world.time)
- to_chat(src, SPAN_WARNING("[tmob] is restraining [M], you cannot push past"))
- last_push_notif = world.time
-
- now_pushing = FALSE
- return
-
- //Leaping mobs just land on the tile, no pushing, no anything.
- if(status_flags & LEAPING)
- forceMove(tmob.loc)
- status_flags &= ~LEAPING
- now_pushing = FALSE
- return
-
- if(can_swap_with(tmob)) // mutual brohugs all around!
- var/turf/tmob_oldloc = get_turf(tmob)
- var/turf/src_oldloc = get_turf(src)
- if(pulling?.density)
- tmob.forceMove(pulling.loc)
- forceMove(tmob_oldloc)
+ if(can_swap_with(tmob)) // mutual brohugs all around!
+ var/turf/tmob_oldloc = get_turf(tmob)
+ var/turf/src_oldloc = get_turf(src)
+ if(pulling?.density)
+ tmob.forceMove(pulling.loc)
+ forceMove(tmob_oldloc)
+ pulling.forceMove(src_oldloc)
+ else if(tmob.pulling?.density)
+ forceMove(tmob.pulling.loc)
+ tmob.forceMove(src_oldloc)
+ tmob.pulling.forceMove(tmob_oldloc)
+ else
+ forceMove(tmob_oldloc)
+ if(pulling)
pulling.forceMove(src_oldloc)
- else if(tmob.pulling?.density)
- forceMove(tmob.pulling.loc)
- tmob.forceMove(src_oldloc)
+ tmob.forceMove(src_oldloc)
+ if(tmob.pulling)
tmob.pulling.forceMove(tmob_oldloc)
- else
- forceMove(tmob_oldloc)
- if(pulling)
- pulling.forceMove(src_oldloc)
- tmob.forceMove(src_oldloc)
- if(tmob.pulling)
- tmob.pulling.forceMove(tmob_oldloc)
- for(var/obj/item/grab/G in list(l_hand, r_hand))
- G.affecting.forceMove(loc)
- for(var/obj/item/grab/G in list(tmob.l_hand, tmob.r_hand))
- G.affecting.forceMove(tmob.loc)
- now_pushing = FALSE
- for(var/mob/living/carbon/slime/slime in view(2, tmob))
- if(slime.victim == tmob)
- slime.UpdateFeed()
- return
+ for(var/obj/item/grab/G in list(l_hand, r_hand))
+ G.affecting.forceMove(loc)
+ for(var/obj/item/grab/G in list(tmob.l_hand, tmob.r_hand))
+ G.affecting.forceMove(tmob.loc)
+ now_pushing = FALSE
+ for(var/mob/living/carbon/slime/slime in view(2, tmob))
+ if(slime.victim == tmob)
+ slime.UpdateFeed()
+ return
- if(!can_move_mob(tmob, 0, 0))
+ if(!can_move_mob(tmob, 0, 0))
+ now_pushing = FALSE
+ return
+
+ if(a_intent == I_HELP || src.restrained())
+ now_pushing = FALSE
+ return
+
+ if(istype(tmob, /mob/living/carbon/human) && (tmob.mutations & FAT))
+ if(prob(40) && !(mutations & FAT))
+ to_chat(src, SPAN_DANGER("You fail to push [tmob]'s fat ass out of the way."))
now_pushing = FALSE
return
- if(a_intent == I_HELP || src.restrained())
+ if(istype(tmob.r_hand, /obj/item/shield/riot))
+ if(prob(99))
now_pushing = FALSE
return
- if(istype(tmob, /mob/living/carbon/human) && (tmob.mutations & FAT))
- if(prob(40) && !(mutations & FAT))
- to_chat(src, SPAN_DANGER("You fail to push [tmob]'s fat ass out of the way."))
+ if(istype(tmob.l_hand, /obj/item/shield/riot))
+ if(prob(99))
+ now_pushing = FALSE
+ return
+
+ if(!(tmob.status_flags & CANPUSH))
+ now_pushing = FALSE
+ return
+
+ tmob.LAssailant = WEAKREF(src)
+
+ now_pushing = FALSE
+ . = ..()
+ if (!istype(AM, /atom/movable))
+ return
+ if (!now_pushing)
+ now_pushing = TRUE
+
+ if (!AM.anchored)
+ if(isobj(AM))
+ var/obj/O = AM
+ if ((can_pull_size == 0) || (can_pull_size < O.w_class))
now_pushing = FALSE
return
- if(istype(tmob.r_hand, /obj/item/shield/riot))
- if(prob(99))
+ var/t = get_dir(src, AM)
+ if (istype(AM, /obj/structure/window))
+ for(var/obj/structure/window/win in get_step(AM,t))
now_pushing = FALSE
return
- if(istype(tmob.l_hand, /obj/item/shield/riot))
- if(prob(99))
- now_pushing = FALSE
- return
-
- if(!(tmob.status_flags & CANPUSH))
- now_pushing = FALSE
- return
-
- tmob.LAssailant = WEAKREF(src)
+ step(AM, t)
+ if(ishuman(AM) && AM:grabbed_by)
+ for(var/obj/item/grab/G in AM:grabbed_by)
+ step(G:assailant, get_dir(G:assailant, AM))
+ G.adjust_position()
now_pushing = FALSE
- . = ..()
- if (!istype(AM, /atom/movable))
- return
- if (!now_pushing)
- now_pushing = TRUE
-
- if (!AM.anchored)
- if(isobj(AM))
- var/obj/O = AM
- if ((can_pull_size == 0) || (can_pull_size < O.w_class))
- now_pushing = FALSE
- return
-
- var/t = get_dir(src, AM)
- if (istype(AM, /obj/structure/window))
- for(var/obj/structure/window/win in get_step(AM,t))
- now_pushing = FALSE
- return
-
- step(AM, t)
- if(ishuman(AM) && AM:grabbed_by)
- for(var/obj/item/grab/G in AM:grabbed_by)
- step(G:assailant, get_dir(G:assailant, AM))
- G.adjust_position()
-
- now_pushing = FALSE
/**
* Checks if two mobs can swap with each other based on the density
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index eeb5ac30272..1757996e036 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -175,8 +175,8 @@
var/throw_damage = O.throwforce*(speed/THROWFORCE_SPEED_DIVISOR)
var/miss_chance = 15
- if (O.throw_source)
- var/distance = get_dist(O.throw_source, loc)
+ if (O.throwing?.thrower?.resolve())
+ var/distance = get_dist(O.throwing?.thrower?.resolve(), loc)
miss_chance = max(15*(distance-2), 0)
if (prob(miss_chance))
@@ -187,10 +187,10 @@
src.visible_message(SPAN_WARNING("[src] has been hit by [O]."))
apply_damage(throw_damage, dtype, null, damage_flags = O.damage_flags(), used_weapon = O)
- O.throwing = 0 //it hit, so stop moving
+ O.throwing?.finalize(hit = TRUE, target = src) //it hit, so stop moving
- if(ismob(O.thrower))
- var/mob/M = O.thrower
+ if(ismob(O.throwing?.thrower?.resolve()))
+ var/mob/M = O.throwing?.thrower?.resolve()
var/client/assailant = M.client
if(assailant)
src.attack_log += text("\[[time_stamp()]\] Has been hit with a [O], thrown by [M.name] ([assailant.ckey])")
@@ -205,8 +205,8 @@
mass = I.w_class/THROWNOBJ_KNOCKBACK_DIVISOR
var/momentum = speed*mass
- if(O.throw_source && momentum >= THROWNOBJ_KNOCKBACK_SPEED)
- var/dir = get_dir(O.throw_source, src)
+ if(O.throwing?.thrower?.resolve() && momentum >= THROWNOBJ_KNOCKBACK_SPEED)
+ var/dir = get_dir(O.throwing?.thrower?.resolve(), src)
visible_message(SPAN_WARNING("[src] staggers under the impact!"),
SPAN_WARNING("You stagger under the impact!"))
diff --git a/code/modules/mob/living/maneuvers/maneuver_leap.dm b/code/modules/mob/living/maneuvers/maneuver_leap.dm
index f9cc71f5d2d..af5bd9c0095 100644
--- a/code/modules/mob/living/maneuvers/maneuver_leap.dm
+++ b/code/modules/mob/living/maneuvers/maneuver_leap.dm
@@ -15,8 +15,8 @@
strength *= reflexive_modifier
animate(user, pixel_z = 16, time = 3, easing = SINE_EASING | EASE_IN)
animate(pixel_z = 0, time = 3, easing = SINE_EASING | EASE_OUT)
- user.throw_at(get_turf(target), strength, 1, user, FALSE)
- end_leap(user, target, old_pass_flags)
+ var/end_leap_callback = CALLBACK(src, PROC_REF(end_leap), user, target, old_pass_flags)
+ user.throw_at(get_turf(target), strength, 1, user, spin = FALSE, diagonals_first = TRUE, callback = end_leap_callback)
/singleton/maneuver/leap/proc/end_leap(var/mob/living/user, var/atom/target, var/pass_flag)
SHOULD_NOT_SLEEP(TRUE)
diff --git a/code/modules/mob/living/simple_animal/friendly/carp.dm b/code/modules/mob/living/simple_animal/friendly/carp.dm
index 58e09dbd0fa..8d819db4643 100644
--- a/code/modules/mob/living/simple_animal/friendly/carp.dm
+++ b/code/modules/mob/living/simple_animal/friendly/carp.dm
@@ -70,11 +70,11 @@
/mob/living/simple_animal/carp/fluff/think()
..()
if(!stat && !buckled_to && (turns_since_move > 5))
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
turns_since_move = 0
handle_movement_target()
if(!movement_target && (turns_since_move > 5))
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
/mob/living/simple_animal/carp/fluff/proc/handle_movement_target()
if(!QDELETED(friend))
@@ -89,17 +89,17 @@
if(movement_target != friend)
if(current_dist > follow_dist && (friend in oview(src)))
//stop existing movement
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
turns_since_scan = 0
//walk to friend
stop_automated_movement = 1
movement_target = friend
- SSmove_manager.move_to(src, movement_target, near_dist, seek_move_delay)
+ GLOB.move_manager.move_to(src, movement_target, near_dist, seek_move_delay)
//already following and close enough, stop
else if(current_dist <= near_dist)
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
movement_target = null
stop_automated_movement = 0
if(prob(10))
diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm
index 100e844b72a..9eec84ecfe1 100644
--- a/code/modules/mob/living/simple_animal/friendly/cat.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cat.dm
@@ -64,7 +64,7 @@
if(!buckled_to)
if (turns_since_move > 5 || (flee_target || rattarget))
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
turns_since_move = 0
if (flee_target) //fleeing takes precendence
@@ -73,7 +73,7 @@
handle_movement_target()
if (!movement_target)
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
if(prob(2)) //spooky
var/mob/abstract/observer/spook = locate() in range(src,5)
@@ -164,7 +164,7 @@
if (flee_target)
if(prob(25)) say("HSSSSS")
stop_automated_movement = 1
- SSmove_manager.move_away(src, flee_target, 7, 2)
+ GLOB.move_manager.move_away(src, flee_target, 7, 2)
/mob/living/simple_animal/cat/proc/set_flee_target(atom/A)
if(A)
@@ -191,7 +191,7 @@
/mob/living/simple_animal/cat/hitby(atom/movable/AM)
. = ..()
- set_flee_target(AM.thrower? AM.thrower : src.loc)
+ set_flee_target(AM.throwing?.thrower?.resolve() ? AM.throwing?.thrower?.resolve() : src.loc)
/mob/living/simple_animal/cat/fall_impact()
src.visible_message(SPAN_NOTICE("\The [src] lands softly on \the [loc]!"))
@@ -215,17 +215,17 @@
if (movement_target != friend)
if (current_dist > follow_dist && !istype(movement_target, /mob/living/simple_animal/rat) && (friend in oview(src)))
//stop existing movement
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
turns_since_scan = 0
//walk to friend
stop_automated_movement = 1
movement_target = friend
- SSmove_manager.move_to(src, movement_target, near_dist, seek_move_delay)
+ GLOB.move_manager.move_to(src, movement_target, near_dist, seek_move_delay)
//already following and close enough, stop
else if (current_dist <= near_dist)
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
movement_target = null
stop_automated_movement = 0
if (prob(10))
diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm
index 77bf1ec1b12..5f35c98039d 100644
--- a/code/modules/mob/living/simple_animal/hostile/bear.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bear.dm
@@ -247,7 +247,7 @@
set_stance(HOSTILE_STANCE_TIRED)
speak_audio()
stance_step = 0
- SSmove_manager.stop_looping(src) //This stops the bear's walking
+ GLOB.move_manager.stop_looping(src) //This stops the bear's walking
/mob/living/simple_animal/hostile/bear/spatial/tire_out()
..()
@@ -320,7 +320,7 @@
if (stance > HOSTILE_STANCE_ALERT)//If we're currently above alert
set_stance(HOSTILE_STANCE_ALERT)//Drop to alert and cease attacking
target_mob = null
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
/mob/living/simple_animal/hostile/bear/AttackingTarget()
var/targetname = target_mob.name
diff --git a/code/modules/mob/living/simple_animal/hostile/commanded/commanded.dm b/code/modules/mob/living/simple_animal/hostile/commanded/commanded.dm
index 230a96eaa17..d3d448392bb 100644
--- a/code/modules/mob/living/simple_animal/hostile/commanded/commanded.dm
+++ b/code/modules/mob/living/simple_animal/hostile/commanded/commanded.dm
@@ -333,8 +333,8 @@
if(istype(AM,/obj/))
var/obj/O = AM
- if(ismob(O.thrower))
- if(O.thrower == master)
+ if(ismob(O.throwing?.thrower?.resolve()))
+ if(O.throwing?.thrower?.resolve() == master)
target_mob = null
change_stance(HOSTILE_STANCE_IDLE)
audible_emote("[pick(sad_emote)].",0)
diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
index fe6a6bd5778..db7c0d7abb4 100644
--- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
+++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm
@@ -222,12 +222,12 @@
for(var/turf/T in orange(20, src))
move_targets.Add(T)*/
stop_automated_movement = 1
- SSmove_manager.move_to(src, pick(orange(20, src)), 1, move_to_delay)
+ GLOB.move_manager.move_to(src, pick(orange(20, src)), 1, move_to_delay)
addtimer(CALLBACK(src, PROC_REF(stop_walking)), 50, TIMER_UNIQUE)
/mob/living/simple_animal/hostile/giant_spider/proc/stop_walking()
stop_automated_movement = 0
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
/mob/living/simple_animal/hostile/giant_spider/nurse/think()
..()
@@ -240,7 +240,7 @@
if(C.stat)
cocoon_target = C
busy = MOVING_TO_TARGET
- SSmove_manager.move_to(src, C, 1, move_to_delay)
+ GLOB.move_manager.move_to(src, C, 1, move_to_delay)
//give up if we can't reach them after 10 seconds
addtimer(CALLBACK(src, PROC_REF(GiveUp), C), 100, TIMER_UNIQUE)
return
@@ -270,7 +270,7 @@
cocoon_target = O
busy = MOVING_TO_TARGET
stop_automated_movement = 1
- SSmove_manager.move_to(src, O, 1, move_to_delay)
+ GLOB.move_manager.move_to(src, O, 1, move_to_delay)
//give up if we can't reach them after 10 seconds
GiveUp(O)
@@ -279,7 +279,7 @@
busy = SPINNING_COCOON
src.visible_message(SPAN_NOTICE("\The [src] begins to secrete a sticky substance around \the [cocoon_target]."))
stop_automated_movement = 1
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
addtimer(CALLBACK(src, PROC_REF(finalize_cocoon)), 50, TIMER_UNIQUE)
else
diff --git a/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot_beacon.dm b/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot_beacon.dm
index 4e2f9b97f5d..245e787425f 100644
--- a/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot_beacon.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hivebots/hivebot_beacon.dm
@@ -188,7 +188,7 @@
LoseTarget()
if(target_mob in targets)
if(get_dist(src, target_mob) <= 6)
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
OpenFire(target_mob)
/mob/living/simple_animal/hostile/hivebotbeacon/proc/activate_beacon()
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index c4982ad9a9b..52479f8e81f 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -136,8 +136,8 @@
..()
if(istype(AM,/obj/))
var/obj/O = AM
- if((target_mob != O.thrower) && ismob(O.thrower))
- target_mob = O.thrower
+ if((target_mob != O.throwing?.thrower?.resolve()) && ismob(O.throwing?.thrower?.resolve()))
+ target_mob = O.throwing?.thrower?.resolve()
change_stance(HOSTILE_STANCE_ATTACK)
/mob/living/simple_animal/hostile/attack_generic(var/mob/user, var/damage, var/attack_message)
@@ -168,13 +168,13 @@
if(target_mob in targets)
if(ranged)
if(get_dist(src, target_mob) <= ranged_attack_range)
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
OpenFire(target_mob)
else
- SSmove_manager.move_to(src, target_mob, 6, move_to_delay)
+ GLOB.move_manager.move_to(src, target_mob, 6, move_to_delay)
else
change_stance(HOSTILE_STANCE_ATTACKING)
- SSmove_manager.move_to(src, target_mob, 1, move_to_delay)
+ GLOB.move_manager.move_to(src, target_mob, 1, move_to_delay)
/mob/living/simple_animal/hostile/proc/AttackTarget()
stop_automated_movement = 1
@@ -265,7 +265,7 @@
/mob/living/simple_animal/hostile/proc/LoseTarget()
change_stance(HOSTILE_STANCE_IDLE)
target_mob = null
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
LostTarget()
/mob/living/simple_animal/hostile/proc/LostTarget()
@@ -276,7 +276,7 @@
/mob/living/simple_animal/hostile/death()
..()
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
/mob/living/simple_animal/hostile/think()
..()
diff --git a/code/modules/mob/living/simple_animal/hostile/icarus_drone.dm b/code/modules/mob/living/simple_animal/hostile/icarus_drone.dm
index aa031587c41..d3278eba683 100644
--- a/code/modules/mob/living/simple_animal/hostile/icarus_drone.dm
+++ b/code/modules/mob/living/simple_animal/hostile/icarus_drone.dm
@@ -207,7 +207,7 @@
else
visible_message(SPAN_NOTICE("\The [src] suddenly lies still and quiet."))
disabled = rand(150, 600)
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
if(exploding && prob(20))
if(prob(50))
@@ -220,7 +220,7 @@
exploding = TRUE
set_stat(UNCONSCIOUS)
wander = 1
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
spawn(rand(50, 150))
if(!disabled && exploding)
explosion(get_turf(src), 0, 1, 4, 7)
@@ -233,7 +233,7 @@
health -= rand(3, 15) * (severity + 1)
disabled = rand(150, 600)
hostile_drone = FALSE
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
/mob/living/simple_animal/hostile/icarus_drone/death()
..(null, "suddenly breaks apart.")
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/cavern.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/cavern.dm
index 99450ad1ef1..2441cc7096b 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/cavern.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/cavern.dm
@@ -175,7 +175,7 @@
break
if(target_ore)
- SSmove_manager.move_to(src, target_ore, 1, move_to_delay)
+ GLOB.move_manager.move_to(src, target_ore, 1, move_to_delay)
else if(found_turfs.len)
for(var/turf/simulated/mineral/M in found_turfs)
if(!QDELETED(M) || !M.mineral)
diff --git a/code/modules/mob/living/simple_animal/hostile/space_fauna.dm b/code/modules/mob/living/simple_animal/hostile/space_fauna.dm
index 63e83acc75d..2ad3c13d356 100644
--- a/code/modules/mob/living/simple_animal/hostile/space_fauna.dm
+++ b/code/modules/mob/living/simple_animal/hostile/space_fauna.dm
@@ -67,7 +67,7 @@
stop_automated_movement = 1
if(istype(target_mob, /obj/effect/energy_field) && !QDELETED(target_mob) && (target_mob in targets))
change_stance(HOSTILE_STANCE_ATTACKING)
- SSmove_manager.move_to(src, target_mob, 1, move_to_delay)
+ GLOB.move_manager.move_to(src, target_mob, 1, move_to_delay)
return 1
..()
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
index ff76905b94f..7984a09c343 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -116,7 +116,7 @@
if(held_item)
held_item.forceMove(src.loc)
held_item = null
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
..()
/mob/living/simple_animal/parrot/get_status_tab_items()
@@ -356,7 +356,7 @@
//-----WANDERING - This is basically a 'I dont know what to do yet' state
else if(parrot_state == PARROT_WANDER)
//Stop movement, we'll set it later
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
parrot_interest = null
//Wander around aimlessly. This will help keep the loops from searches down
@@ -394,7 +394,7 @@
return
//-----STEALING
else if(parrot_state == (PARROT_SWOOP | PARROT_STEAL))
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
if(!parrot_interest || held_item)
parrot_state = PARROT_SWOOP | PARROT_RETURN
return
@@ -418,12 +418,12 @@
parrot_state = PARROT_SWOOP | PARROT_RETURN
return
- SSmove_manager.move_to(src, parrot_interest, 1, parrot_speed)
+ GLOB.move_manager.move_to(src, parrot_interest, 1, parrot_speed)
return
//-----RETURNING TO PERCH
else if(parrot_state == (PARROT_SWOOP | PARROT_RETURN))
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
if(!parrot_perch || !isturf(parrot_perch.loc)) //Make sure the perch exists and somehow isnt inside of something else.
parrot_perch = null
parrot_state = PARROT_WANDER
@@ -436,16 +436,16 @@
icon_state = "parrot_sit"
return
- SSmove_manager.move_to(src, parrot_perch, 1, parrot_speed)
+ GLOB.move_manager.move_to(src, parrot_perch, 1, parrot_speed)
return
//-----FLEEING
else if(parrot_state == (PARROT_SWOOP | PARROT_FLEE))
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
if(!parrot_interest || !isliving(parrot_interest)) //Sanity
parrot_state = PARROT_WANDER
- SSmove_manager.move_away(src, parrot_interest, 1, (parrot_speed-parrot_been_shot))
+ GLOB.move_manager.move_away(src, parrot_interest, 1, (parrot_speed-parrot_been_shot))
parrot_been_shot--
return
@@ -493,11 +493,11 @@
//Otherwise, fly towards the mob!
else
- SSmove_manager.move_to(src, parrot_interest, 1, parrot_speed)
+ GLOB.move_manager.move_to(src, parrot_interest, 1, parrot_speed)
return
//-----STATE MISHAP
else //This should not happen. If it does lets reset everything and try again
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
parrot_interest = null
parrot_perch = null
drop_held_item()
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index acee0c42f42..fe6bf9108b6 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -642,8 +642,8 @@
/mob/living/simple_animal/hitby(atom/movable/AM, speed)
. = ..()
- if(ismob(AM.thrower))
- handle_attack_by(AM.thrower)
+ if(ismob(AM.throwing?.thrower?.resolve()))
+ handle_attack_by(AM.throwing?.thrower?.resolve())
/mob/living/simple_animal/bullet_act(obj/item/projectile/P, def_zone)
. = ..()
@@ -700,7 +700,7 @@
if(movement_target)
stop_automated_movement = 1
- SSmove_manager.move_to(src, movement_target, 0, seek_move_delay)
+ GLOB.move_manager.move_to(src, movement_target, 0, seek_move_delay)
/mob/living/simple_animal/get_status_tab_items()
. = ..()
@@ -715,7 +715,7 @@
death()
/mob/living/simple_animal/death(gibbed, deathmessage = "dies!")
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
movement_target = null
density = FALSE
if (isopenturf(loc))
@@ -881,7 +881,7 @@
set_stat(UNCONSCIOUS)
canmove = 0
wander = 0
- SSmove_manager.stop_looping(src)
+ GLOB.move_manager.stop_looping(src)
movement_target = null
update_icon()
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 4a8f9d28bee..5a59df579fd 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -752,7 +752,7 @@
src.pulling = AM
AM.pulledby = src
- SSmove_manager.stop_looping(AM)
+ GLOB.move_manager.stop_looping(AM)
if(pullin)
pullin.icon_state = "pull1"
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index d9015b1f354..ffd50ab59b8 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -131,47 +131,54 @@
return
//This proc should never be overridden elsewhere at /atom/movable to keep directions sane.
-/atom/movable/Move(atom/newloc, direction)
+/atom/movable/Move(atom/newloc, direction, glide_size_override = 0, update_dir = TRUE) //Last 2 parameters are not used but they're caught
+ . = FALSE
+ if(!newloc || newloc == loc)
+ return
+
if(SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_MOVE, newloc) & COMPONENT_MOVABLE_BLOCK_PRE_MOVE)
return
var/old_loc = loc
- if (direction & (direction - 1))
- if (direction & 1)
- if (direction & 4)
- if (step(src, NORTH))
- step(src, EAST)
+ //Cardinal move
+ if(direction & (direction - 1))
+ if(direction & 1)
+ if(direction & 4)
+ if(step(src, NORTH))
+ . = step(src, EAST)
else
- if (step(src, EAST))
- step(src, NORTH)
+ if(step(src, EAST))
+ . = step(src, NORTH)
else
- if (direction & 8)
- if (step(src, NORTH))
- step(src, WEST)
+ if(direction & 8)
+ if(step(src, NORTH))
+ . = step(src, WEST)
else
- if (step(src, WEST))
- step(src, NORTH)
+ if(step(src, WEST))
+ . = step(src, NORTH)
else
- if (direction & 2)
- if (direction & 4)
- if (step(src, SOUTH))
- step(src, EAST)
+ if(direction & 2)
+ if(direction & 4)
+ if(step(src, SOUTH))
+ . = step(src, EAST)
else
- if (step(src, EAST))
- step(src, SOUTH)
+ if(step(src, EAST))
+ . = step(src, SOUTH)
else
- if (direction & 8)
- if (step(src, SOUTH))
- step(src, WEST)
+ if(direction & 8)
+ if(step(src, SOUTH))
+ . = step(src, WEST)
else
- if (step(src, WEST))
- step(src, SOUTH)
+ if(step(src, WEST))
+ . = step(src, SOUTH)
+
+ //Diagonal move
else
var/atom/A = src.loc
var/olddir = dir //we can't override this without sacrificing the rest of movable/New()
- . = ..()
+ . = ..(newloc, direction)
if(.)
// Events.
diff --git a/code/modules/modular_computers/computers/subtypes/dev_console.dm b/code/modules/modular_computers/computers/subtypes/dev_console.dm
index 44811ae7dfc..6e20e9e9ace 100644
--- a/code/modules/modular_computers/computers/subtypes/dev_console.dm
+++ b/code/modules/modular_computers/computers/subtypes/dev_console.dm
@@ -21,3 +21,4 @@
screensaver_light_range = 1.4
screensaver_light_color = LIGHT_COLOR_WHITE
is_holographic = TRUE
+ pass_flags_self = PASSTABLE
diff --git a/code/modules/modular_computers/computers/subtypes/preset_console.dm b/code/modules/modular_computers/computers/subtypes/preset_console.dm
index dc11d47b492..6fd316f78ec 100644
--- a/code/modules/modular_computers/computers/subtypes/preset_console.dm
+++ b/code/modules/modular_computers/computers/subtypes/preset_console.dm
@@ -4,9 +4,6 @@
//Holoscreens are non solid, and the frames of the computers are thin. So projectiles will usually
//pass through
return TRUE
- else if(istype(mover) && mover.checkpass(PASSTABLE))
- //Animals can run under them, lots of empty space
- return TRUE
return ..()
/obj/item/modular_computer/console/preset/install_default_hardware()
diff --git a/code/modules/multiz/structures.dm b/code/modules/multiz/structures.dm
index ba788239cce..38beefe4648 100644
--- a/code/modules/multiz/structures.dm
+++ b/code/modules/multiz/structures.dm
@@ -340,7 +340,7 @@
/obj/structure/stairs_railing/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(istype(mover,/obj/item/projectile))
return TRUE
- if(!istype(mover) || mover.checkpass(PASSRAILING))
+ if(!istype(mover) || mover.pass_flags & PASSRAILING)
return TRUE
if(mover.throwing)
return TRUE
@@ -418,7 +418,7 @@
/obj/structure/platform/CanPass(atom/movable/mover, turf/target, height, air_group)
if(istype(mover, /obj/item/projectile))
return TRUE
- if(!istype(mover) || mover.checkpass(PASSRAILING))
+ if(!istype(mover) || mover.pass_flags & PASSRAILING)
return TRUE
if(mover.throwing)
return TRUE
diff --git a/code/modules/projectiles/guns/launcher/syringe_gun.dm b/code/modules/projectiles/guns/launcher/syringe_gun.dm
index a75a23c01d8..399fde374ab 100644
--- a/code/modules/projectiles/guns/launcher/syringe_gun.dm
+++ b/code/modules/projectiles/guns/launcher/syringe_gun.dm
@@ -42,18 +42,18 @@
icon_state = icon_flight
underlays.Cut()
-/obj/item/syringe_cartridge/throw_impact(atom/hit_atom, var/speed)
+/obj/item/syringe_cartridge/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
..() //handles embedding for us. Should have a decent chance if thrown fast enough
if(syringe)
//check speed to see if we hit hard enough to trigger the rapid injection
//incidentally, this means syringe_cartridges can be used with the pneumatic launcher
- if(speed >= 10 && isliving(hit_atom))
+ if(throwingdatum.speed >= 10 && isliving(hit_atom))
var/mob/living/L = hit_atom
//unfortuately we don't know where the dart will actually hit, since that's done by the parent.
if(L.can_inject() && syringe.reagents)
var/singleton/reagent/reagent_log = syringe.reagents.get_reagents()
syringe.reagents.trans_to_mob(L, 15, CHEM_BLOOD)
- admin_inject_log(thrower, L, src, reagent_log, syringe.reagents.get_temperature(), 15, violent=1)
+ admin_inject_log(throwing?.thrower?.resolve(), L, src, reagent_log, syringe.reagents.get_temperature(), 15, violent=1)
syringe.break_syringe(iscarbon(hit_atom)? hit_atom : null)
syringe.update_icon()
diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm
index c658758c784..dbb96684b2d 100644
--- a/code/modules/projectiles/projectile/special.dm
+++ b/code/modules/projectiles/projectile/special.dm
@@ -82,7 +82,6 @@
/obj/item/projectile/bullet/gyro/law/on_hit(var/atom/target, var/blocked = 0)
explosion(target, -1, 0, 2)
- sleep(0)
var/obj/T = target
var/throwdir = get_dir(firer,target)
T.throw_at(get_edge_target_turf(target, throwdir),3,3)
@@ -118,8 +117,6 @@
loc = A.loc
return
- sleep(-1) //Might not be important enough for a sleep(-1) but the sleep/spawn itself is necessary thanks to explosions and metoerhits
-
if(src)//Do not add to this if() statement, otherwise the meteor won't delete them
if(A)
diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm
index 9e22ad1a883..b4022673b6a 100644
--- a/code/modules/reagents/reagent_containers.dm
+++ b/code/modules/reagents/reagent_containers.dm
@@ -74,17 +74,17 @@
return last_increment
-/obj/item/reagent_containers/throw_impact(atom/hit_atom, var/speed)
+/obj/item/reagent_containers/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
. = ..()
if(ismob(loc))
return
- if(fragile && (speed >= fragile))
+ if(fragile && (throwingdatum.speed >= fragile))
shatter()
if(atom_flags && ATOM_FLAG_NO_REACT)
return
if(!reagents)
return
- reagents.apply_force(speed)
+ reagents.apply_force(throwingdatum.speed)
/obj/item/reagent_containers/proc/shatter(var/obj/item/W, var/mob/user)
if(reagents?.total_volume)
diff --git a/code/modules/reagents/reagent_containers/food/drinks/bottle.dm b/code/modules/reagents/reagent_containers/food/drinks/bottle.dm
index 6bf7a90cee4..b94dcfd79a3 100644
--- a/code/modules/reagents/reagent_containers/food/drinks/bottle.dm
+++ b/code/modules/reagents/reagent_containers/food/drinks/bottle.dm
@@ -33,13 +33,13 @@
return ..()
//when thrown on impact, bottles smash and spill their contents
-/obj/item/reagent_containers/food/drinks/bottle/throw_impact(atom/hit_atom, var/speed)
+/obj/item/reagent_containers/food/drinks/bottle/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
..()
- var/mob/M = thrower
+ var/mob/M = throwing?.thrower?.resolve()
if((drink_flags & IS_GLASS) && istype(M) && M.a_intent == I_HURT)
- var/throw_dist = get_dist(throw_source, loc)
- if(speed >= throw_speed && smash_check(throw_dist)) //not as reliable as smashing directly
+ var/throw_dist = get_dist(throwing?.thrower?.resolve(), loc)
+ if(throwingdatum.speed >= throw_speed && smash_check(throw_dist)) //not as reliable as smashing directly
if(reagents)
hit_atom.visible_message(SPAN_NOTICE("The contents of \the [src] splash all over [hit_atom]!"))
reagents.splash(hit_atom, reagents.total_volume)
diff --git a/code/modules/shieldgen/shieldwallgen.dm b/code/modules/shieldgen/shieldwallgen.dm
index 8b9757fe9f1..7a94805d30a 100644
--- a/code/modules/shieldgen/shieldwallgen.dm
+++ b/code/modules/shieldgen/shieldwallgen.dm
@@ -294,7 +294,7 @@
/obj/shieldwall/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(air_group || (height==0))
return TRUE
- if(istype(mover) && mover.checkpass(PASSGLASS))
+ if(istype(mover) && mover.pass_flags & PASSGLASS)
return prob(20)
else
if(istype(mover, /obj/item/projectile))
diff --git a/code/modules/tables/interactions.dm b/code/modules/tables/interactions.dm
index 44d60ed755a..416770ab91a 100644
--- a/code/modules/tables/interactions.dm
+++ b/code/modules/tables/interactions.dm
@@ -9,7 +9,7 @@
return 1
if(istype(mover, /obj/structure/closet/crate))
return TRUE
- if(istype(mover) && mover.checkpass(PASSTABLE))
+ if(istype(mover) && mover.pass_flags & PASSTABLE)
return 1
if(locate(/obj/structure/table) in get_turf(mover))
return 1
@@ -49,7 +49,7 @@
return 1
/obj/structure/table/CheckExit(atom/movable/O as mob|obj, target as turf)
- if(istype(O) && O.checkpass(PASSTABLE))
+ if(istype(O) && O.pass_flags & PASSTABLE)
return 1
if (flipped==1)
if (get_dir(loc, target) == dir)
diff --git a/code/modules/tables/presets.dm b/code/modules/tables/presets.dm
index ff67031adea..666adf71732 100644
--- a/code/modules/tables/presets.dm
+++ b/code/modules/tables/presets.dm
@@ -1,10 +1,4 @@
-/obj/structure/table
- icon = 'icons/obj/structure/tables/table.dmi'
- var/table_mat
- var/table_reinf
- var/no_cargo
- build_amt = 1
- // note : material_alteration does not work here because it is constructed piece by piece and not spawned in one shot like chairs
+// note : material_alteration does not work here because it is constructed piece by piece and not spawned in one shot like chairs
/obj/structure/table/standard
icon_state = "solid_preview"
diff --git a/code/modules/tables/rack.dm b/code/modules/tables/rack.dm
index 84ecdd926c4..5135f067995 100644
--- a/code/modules/tables/rack.dm
+++ b/code/modules/tables/rack.dm
@@ -3,6 +3,7 @@
desc = "Different from the Middle Ages version."
icon = 'icons/obj/structure/tables/table.dmi'
icon_state = "rack"
+ pass_flags_self = LETPASSTHROW //You can throw objects over this, despite it's density.
build_amt = 1
can_plate = 0
can_reinforce = 0
diff --git a/code/modules/tables/tables.dm b/code/modules/tables/tables.dm
index 852013c8fa2..60b649653da 100644
--- a/code/modules/tables/tables.dm
+++ b/code/modules/tables/tables.dm
@@ -9,6 +9,14 @@
layer = TABLE_LAYER
throwpass = 1
breakable = TRUE
+ build_amt = 1
+ pass_flags_self = PASSTABLE | LETPASSTHROW
+
+ //Preset shit
+ var/table_mat
+ var/table_reinf
+ var/no_cargo
+
var/flipped = 0
var/maxhealth = 10
var/health = 10
diff --git a/html/changelogs/fluffyghost-ssthrowing.yml b/html/changelogs/fluffyghost-ssthrowing.yml
new file mode 100644
index 00000000000..c4d4ecd5ead
--- /dev/null
+++ b/html/changelogs/fluffyghost-ssthrowing.yml
@@ -0,0 +1,61 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# - (fixes bugs)
+# wip
+# - (work in progress)
+# qol
+# - (quality of life)
+# soundadd
+# - (adds a sound)
+# sounddel
+# - (removes a sound)
+# rscadd
+# - (adds a feature)
+# rscdel
+# - (removes a feature)
+# imageadd
+# - (adds an image or sprite)
+# imagedel
+# - (removes an image or sprite)
+# spellcheck
+# - (fixes spelling or grammar)
+# experiment
+# - (experimental change)
+# balance
+# - (balance changes)
+# code_imp
+# - (misc internal code change)
+# refactor
+# - (refactors code)
+# config
+# - (makes a change to the config files)
+# admin
+# - (makes changes to administrator tools)
+# server
+# - (miscellaneous changes to server)
+#################################
+
+# Your name.
+author: FluffyGhost
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit.
+# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - rscadd: "Ported SSThrowing from TG, to handle throwings."
+ - rscadd: "Updated movement system to the latest iteration, made it a datum as per latest iteration."
+ - rscadd: "Updated pass/hit handling of atoms, introduced pass_flag_self to determine what atoms allow to pass."
+ - refactor: "Moved procs and defines around to make them more organized."