diff --git a/code/__DEFINES/move_force.dm b/code/__DEFINES/move_force.dm new file mode 100644 index 00000000000..750821bd898 --- /dev/null +++ b/code/__DEFINES/move_force.dm @@ -0,0 +1,19 @@ +//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) \ No newline at end of file diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 6ce486bdc05..44522f89e8e 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1495,7 +1495,7 @@ var/mob/dview/dview_mob = new invisibility = 101 density = 0 - anchored = 1 + move_resist = INFINITY simulated = 0 see_in_dark = 1e6 diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 8ce2177751c..7b700ad4c6d 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -285,12 +285,12 @@ /mob/proc/CtrlClickOn(var/atom/A) A.CtrlClick(src) return -/atom/proc/CtrlClick(var/mob/user) - return -/atom/movable/CtrlClick(var/mob/user) - if(Adjacent(user)) - user.start_pulling(src) +/atom/proc/CtrlClick(mob/user) + SEND_SIGNAL(src, COMSIG_CLICK_CTRL, user) + var/mob/living/ML = user + if(istype(ML)) + ML.pulled(src) /* Alt click diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm index b74e3a1a6c9..fb32991b42b 100644 --- a/code/controllers/subsystem/throwing.dm +++ b/code/controllers/subsystem/throwing.dm @@ -53,6 +53,7 @@ SUBSYSTEM_DEF(throwing) var/dist_y var/dx var/dy + var/force = MOVE_FORCE_DEFAULT var/pure_diagonal var/diagonal_error var/datum/callback/callback diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 30b901875b3..58197cbadf1 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -86,7 +86,7 @@ if(opacity && isturf(loc)) var/turf/T = loc T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guranteed to be on afterwards anyways. - + if(loc) loc.InitializedOn(src) // Used for poolcontroller / pool to improve performance greatly. However it also open up path to other usage of observer pattern on turfs. @@ -324,7 +324,7 @@ // Atoms that return TRUE prevent RPDs placing any kind of pipes on their turf. return FALSE -/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked) +/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...). addtimer(CALLBACK(src, .proc/hitby_react, AM), 2) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index a5d2366c46c..46b86a05ecc 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -3,6 +3,9 @@ appearance_flags = TILE_BOUND var/last_move = null var/anchored = 0 + var/move_resist = MOVE_RESIST_DEFAULT + var/move_force = MOVE_FORCE_DEFAULT + var/pull_force = PULL_FORCE_DEFAULT // var/elevation = 2 - not used anywhere var/move_speed = 10 var/l_move_time = 1 @@ -13,6 +16,8 @@ var/no_spin_thrown = 0 var/moved_recently = 0 var/mob/pulledby = null + var/atom/movable/pulling + var/canmove = 1 var/inertia_dir = 0 var/atom/inertia_last_loc @@ -55,6 +60,70 @@ pulledby = null return ..() +/atom/movable/proc/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) + if(QDELETED(AM)) + return FALSE + if(!(AM.can_be_pulled(src, state, force))) + return FALSE + + // If we're pulling something then drop what we're currently pulling and pull this instead. + if(pulling) + if(state == 0) + stop_pulling() + return FALSE + // Are we trying to pull something we are already pulling? Then enter grab cycle and end. + if(AM == pulling) + if(isliving(AM)) + var/mob/living/AMob = AM + AMob.grabbedby(src) + return TRUE + stop_pulling() + if(AM.pulledby) + add_attack_logs(AM, AM.pulledby, "pulled from", ATKLOG_ALMOSTALL) + AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. + pulling = AM + AM.pulledby = src + if(ismob(AM)) + var/mob/M = AM + add_attack_logs(src, M, "passively grabbed", ATKLOG_ALMOSTALL) + if(!supress_message) + visible_message("[src] has grabbed [M] passively!") + return TRUE + +/atom/movable/proc/stop_pulling() + if(pulling) + pulling.pulledby = null + var/mob/living/ex_pulled = pulling + pulling = null + if(isliving(ex_pulled)) + var/mob/living/L = ex_pulled + L.update_canmove()// mob gets up if it was lyng down in a chokehold + +/atom/movable/proc/check_pulling() + if(pulling) + var/atom/movable/pullee = pulling + if(pullee && get_dist(src, pullee) > 1) + stop_pulling() + return + if(!isturf(loc)) + stop_pulling() + return + if(pullee && !isturf(pullee.loc) && pullee.loc != loc) //to be removed once all code that changes an object's loc uses forceMove(). + log_game("DEBUG:[src]'s pull on [pullee] wasn't broken despite [pullee] being in [pullee.loc]. Pull stopped manually.") + stop_pulling() + return + if(pulling.anchored) + stop_pulling() + return + +/atom/movable/proc/can_be_pulled(user, grab_state, force) + if(src == user || !isturf(loc)) + return FALSE + if(anchored || throwing) + return FALSE + if(force < (move_resist * MOVE_FORCE_PULL_RATIO)) + return FALSE + return TRUE // Used in shuttle movement and AI eye stuff. // Primarily used to notify objects being moved by a shuttle/bluespace fuckup. /atom/movable/proc/setLoc(var/T, var/teleported=0) @@ -218,12 +287,12 @@ if(!QDELETED(hit_atom)) return hit_atom.hitby(src) -/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked) - if(!anchored && hitpush) +/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked, datum/thrownthing/throwingdatum) + if(!anchored && hitpush && (!throwingdatum || (throwingdatum.force >= (move_resist * MOVE_FORCE_PUSH_RATIO)))) step(src, AM.dir) ..() -/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, var/datum/callback/callback) +/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY) if(!target || (flags & NODROP) || speed <= 0) return 0 @@ -330,6 +399,22 @@ return 0 return 1 +/atom/movable/proc/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + return FALSE + +/atom/movable/proc/force_push(atom/movable/AM, force = move_force, direction, silent = FALSE) + . = AM.force_pushed(src, force, direction) + if(!silent && .) + visible_message("[src] forcefully pushes against [AM]!", "You forcefully push against [AM]!") + +/atom/movable/proc/move_crush(atom/movable/AM, force = move_force, direction, silent = FALSE) + . = AM.move_crushed(src, force, direction) + if(!silent && .) + visible_message("[src] crushes past [AM]!", "You crush [AM]!") + +/atom/movable/proc/move_crushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + return FALSE + /atom/movable/CanPass(atom/movable/mover, turf/target, height=1.5) if(buckled_mob == mover) return 1 diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm index 9a8ead8b289..82a018d9902 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm @@ -311,7 +311,7 @@ to_chat(S, "Destroying this machine while it is occupied would result in biological and sentient resources to be harmed. Aborting.") return ..() - + /mob/living/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) S.DisperseTarget(src) diff --git a/code/game/gamemodes/miniantags/revenant/revenant.dm b/code/game/gamemodes/miniantags/revenant/revenant.dm index fe7d02488d6..45402fe5fc9 100644 --- a/code/game/gamemodes/miniantags/revenant/revenant.dm +++ b/code/game/gamemodes/miniantags/revenant/revenant.dm @@ -32,7 +32,7 @@ wander = 0 density = 0 flying = 1 - anchored = 1 + move_resist = INFINITY mob_size = MOB_SIZE_TINY pass_flags = PASSTABLE | PASSGRILLE | PASSMOB speed = 1 @@ -130,7 +130,7 @@ else message_admins("Revenant was created but has no mind. Put a ghost inside, or a poll will be made in one minute.") addtimer(CALLBACK(src, .proc/setupOrDelete), 1 MINUTES) - + /mob/living/simple_animal/revenant/proc/setupOrDelete() if(mind) giveObjectivesandGoals() diff --git a/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm b/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm index 51f3d277598..d769c2f6807 100644 --- a/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm +++ b/code/game/gamemodes/miniantags/slaughter/bloodcrawl.dm @@ -154,7 +154,6 @@ name = "odd blood" icon = 'icons/effects/effects.dmi' icon_state = "nothing" - var/canmove = 1 density = 0 anchored = 1 invisibility = 60 diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 8d9b17ef7c2..902b0af771f 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -43,6 +43,7 @@ var/list/airlock_overlays = list() name = "airlock" icon = 'icons/obj/doors/airlocks/station/public.dmi' icon_state = "closed" + anchored = 1 max_integrity = 300 integrity_failure = 70 damage_deflection = AIRLOCK_DAMAGE_DEFLECTION_N diff --git a/code/game/machinery/magnet.dm b/code/game/machinery/magnet.dm index 6a11662fc33..3af76895428 100644 --- a/code/game/machinery/magnet.dm +++ b/code/game/machinery/magnet.dm @@ -22,7 +22,7 @@ var/code = 0 // frequency code, they should be different unless you have a group of magnets working together or something var/turf/center // the center of magnetic attraction var/on = 0 - var/pulling = 0 + var/magpulling = 0 // x, y modifiers to the center turf; (0, 0) is centered on the magnet, whereas (1, -1) is one tile right, one tile down var/center_x = 0 @@ -154,10 +154,10 @@ /obj/machinery/magnetic_module/proc/magnetic_process() // proc that actually does the pulling - if(pulling) return + if(magpulling) return while(on) - pulling = 1 + magpulling = 1 center = locate(x+center_x, y+center_y, z) if(center) for(var/obj/M in orange(magnetic_field, center)) @@ -171,7 +171,7 @@ use_power(electricity_level * 5) sleep(13 - electricity_level) - pulling = 0 + magpulling = 0 /obj/machinery/magnetic_controller name = "Magnetic Control Console" diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index b655635ba1a..de3088ae60d 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -154,6 +154,7 @@ active = 1 update_icon() + anchored = 1 for(var/turf/target_tile in range(2, src)) if(istype(target_tile,/turf/space) && !(locate(/obj/machinery/shield) in target_tile)) @@ -166,6 +167,7 @@ active = 0 update_icon() + anchored = 0 for(var/obj/machinery/shield/shield_tile in deployed_shields) qdel(shield_tile) diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm index 5836136401e..a08e7fac021 100644 --- a/code/game/objects/effects/effects.dm +++ b/code/game/objects/effects/effects.dm @@ -6,6 +6,7 @@ icon = 'icons/effects/effects.dmi' burn_state = LAVA_PROOF | FIRE_PROOF resistance_flags = INDESTRUCTIBLE + anchored = 1 can_be_hit = FALSE /obj/effect/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index e3812286714..cd50f079b0c 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -532,10 +532,10 @@ var/global/image/fire_overlay = image("icon" = 'icons/goonstation/effects/fire.d itempush = 0 // too light to push anything return A.hitby(src, 0, itempush) -/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) +/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force) thrownby = thrower callback = CALLBACK(src, .proc/after_throw, callback) //replace their callback with our own - . = ..(target, range, speed, thrower, spin, diagonals_first, callback) + . = ..(target, range, speed, thrower, spin, diagonals_first, callback, force) /obj/item/proc/after_throw(datum/callback/callback) if(callback) //call the original callback diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 572ff92c4fa..3ab8de69f7f 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -87,6 +87,17 @@ return TRUE return FALSE +/obj/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + return TRUE + +/obj/move_crushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + collision_damage(pusher, force, direction) + return TRUE + +/obj/proc/collision_damage(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + var/amt = max(0, ((force - (move_resist * MOVE_FORCE_CRUSH_RATIO)) / (move_resist * MOVE_FORCE_CRUSH_RATIO)) * 10) + take_damage(amt, BRUTE) + /obj/blob_act(obj/structure/blob/B) if(isturf(loc)) var/turf/T = loc diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm index 38b5e81a87b..a5bfcb02e4b 100644 --- a/code/modules/mob/camera/camera.dm +++ b/code/modules/mob/camera/camera.dm @@ -3,7 +3,8 @@ /mob/camera name = "camera mob" density = 0 - anchored = 1 + move_force = INFINITY + move_resist = INFINITY status_flags = GODMODE // You can't damage it. mouse_opacity = MOUSE_OPACITY_TRANSPARENT see_in_dark = 7 diff --git a/code/modules/mob/dead/death.dm b/code/modules/mob/dead/death.dm index 48a04a834c7..704a61abbba 100644 --- a/code/modules/mob/dead/death.dm +++ b/code/modules/mob/dead/death.dm @@ -3,3 +3,6 @@ /mob/dead/gib() //ghosts can't be gibbed. return + +/mob/dead + move_resist = INFINITY \ No newline at end of file diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 7e583216475..cb2bc013154 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -13,7 +13,7 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi density = 0 canmove = 0 alpha = 127 - anchored = 1 // don't get pushed around + move_resist = INFINITY // don't get pushed around invisibility = INVISIBILITY_OBSERVER var/can_reenter_corpse var/bootime = 0 @@ -706,6 +706,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set name = "Mob spawners menu" set desc = "See all currently available ghost spawners" set category = "Ghost" - + var/datum/spawners_menu/menu = new /datum/spawners_menu(src) menu.ui_interact(src) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index e9b09ba1f2b..ca791c9e400 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -574,7 +574,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, if(thrown_thing) visible_message("[src] has thrown [thrown_thing].") newtonian_move(get_dir(target, src)) - thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src) + thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src, null, null, null, move_force) /mob/living/carbon/can_use_hands() if(handcuffed) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index bf49d5b2598..62b9cf6cd65 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -50,7 +50,7 @@ if(ObjBump(A)) return if(istype(A, /atom/movable)) - if(PushAM(A)) + if(PushAM(A, move_force)) return //Called when we bump into a mob @@ -127,32 +127,41 @@ return //Called when we want to push an atom/movable -/mob/living/proc/PushAM(atom/movable/AM) +/mob/living/proc/PushAM(atom/movable/AM, force = move_force) if(now_pushing) - return 1 + return TRUE if(moving_diagonally) // no pushing during diagonal moves - return 1 + return TRUE if(!client && (mob_size < MOB_SIZE_SMALL)) return - if(!AM.anchored) - now_pushing = 1 - var/t = get_dir(src, AM) - if(istype(AM, /obj/structure/window)) - var/obj/structure/window/W = AM - if(W.fulltile) - for(var/obj/structure/window/win in get_step(W, t)) - now_pushing = 0 - return - if(pulling == AM) - stop_pulling() - var/current_dir - if(isliving(AM)) - current_dir = AM.dir - step(AM, t) - if(current_dir) - AM.setDir(current_dir) - now_pushing = 0 - + now_pushing = TRUE + var/t = get_dir(src, AM) + var/push_anchored = FALSE + if((AM.move_resist * MOVE_FORCE_CRUSH_RATIO) <= force) + if(move_crush(AM, move_force, t)) + push_anchored = TRUE + if((AM.move_resist * MOVE_FORCE_FORCEPUSH_RATIO) <= force) //trigger move_crush and/or force_push regardless of if we can push it normally + if(force_push(AM, move_force, t, push_anchored)) + push_anchored = TRUE + if((AM.anchored && !push_anchored) || (force < (AM.move_resist * MOVE_FORCE_PUSH_RATIO))) + now_pushing = FALSE + return + if(istype(AM, /obj/structure/window)) + var/obj/structure/window/W = AM + if(W.fulltile) + for(var/obj/structure/window/win in get_step(W,t)) + now_pushing = FALSE + return + if(pulling == AM) + stop_pulling() + var/current_dir + if(isliving(AM)) + current_dir = AM.dir + if(step(AM, t)) + step(src, t) + if(current_dir) + AM.setDir(current_dir) + now_pushing = FALSE /mob/living/Stat() . = ..() @@ -187,9 +196,20 @@ set name = "Pull" set category = "Object" - if(AM.Adjacent(src)) + if(istype(AM) && Adjacent(AM)) start_pulling(AM) - return + else + stop_pulling() + +/mob/living/stop_pulling() + ..() + if(pullin) + pullin.update_icon(src) + +/mob/living/verb/stop_pulling1() + set name = "Stop Pulling" + set category = "IC" + stop_pulling() //same as above /mob/living/pointed(atom/A as mob|obj|turf in view()) @@ -852,6 +872,37 @@ return 0 return 1 +/mob/living/start_pulling(atom/movable/AM, state, force = pull_force, supress_message = FALSE) + if(!AM || !src) + return FALSE + if(!(AM.can_be_pulled(src, state, force))) + return FALSE + if(incapacitated()) + return + // If we're pulling something then drop what we're currently pulling and pull this instead. + AM.add_fingerprint(src) + if(pulling) + if(AM == pulling)// Are we trying to pull something we are already pulling? Then just stop here, no need to continue. + return + stop_pulling() + if(AM.pulledby) + visible_message("[src] has pulled [AM] from [AM.pulledby]'s grip.") + AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. + pulling = AM + AM.pulledby = src + if(pullin) + pullin.update_icon(src) + if(ismob(AM)) + var/mob/M = AM + if(!iscarbon(src)) + M.LAssailant = null + else + M.LAssailant = usr + +/mob/living/proc/check_pull() + if(pulling && !(pulling in orange(1))) + stop_pulling() + /mob/living/proc/get_taste_sensitivity() return 1 diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index f766a1f53ce..cfe35b58983 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -73,7 +73,7 @@ return 0 //this proc handles being hit by a thrown atom -/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0)//Standardization and logging -Sieve +/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = 1, blocked = 0, datum/thrownthing/throwingdatum)//Standardization and logging -Sieve if(istype(AM, /obj/item)) var/obj/item/I = AM var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest @@ -229,7 +229,7 @@ // End BS12 momentum-transfer code. -/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = 0) +/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = FALSE) if(user == src || anchored) return 0 if(!(status_flags & CANPUSH)) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 2f9ad47399b..239fec3b246 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -38,7 +38,7 @@ var/list/ai_verbs_default = list( name = "AI" icon = 'icons/mob/AI.dmi'// icon_state = "ai" - anchored = 1 // -- TLE + move_resist = MOVE_FORCE_VERY_STRONG density = 1 status_flags = CANSTUN|CANPARALYSE|CANPUSH mob_size = MOB_SIZE_LARGE @@ -533,9 +533,14 @@ var/list/ai_verbs_default = list( if(!isturf(loc)) // if their location isn't a turf return // stop - anchored = !anchored // Toggles the anchor + var/is_anchored = FALSE + if(move_resist == MOVE_FORCE_VERY_STRONG) + move_resist = MOVE_FORCE_VERY_STRONG + else + is_anchored = TRUE + move_resist = MOVE_FORCE_NORMAL - to_chat(src, "[anchored ? "You are now anchored." : "You are now unanchored."]") + to_chat(src, "[is_anchored ? "You are now anchored." : "You are now unanchored."]") /mob/living/silicon/ai/update_canmove() return FALSE diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index eeaa920c83a..e7028ea4422 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -517,12 +517,8 @@ /mob/living/silicon/pai/Bumped() return -/mob/living/silicon/pai/start_pulling(var/atom/movable/AM) - if(stat || sleeping || paralysis || weakened) - return - if(istype(AM,/obj/item)) - to_chat(src, "You are far too small to pull anything!") - return +/mob/living/silicon/pai/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) + return FALSE /mob/living/silicon/pai/update_canmove(delay_action_updates = 0) . = ..() diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 103e443d7e7..49a3b2718db 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -11,8 +11,8 @@ desc = "A Multiple Utility Load Effector bot." icon_state = "mulebot0" density = 1 - anchored = 1 - animate_movement=1 + move_resist = MOVE_FORCE_STRONG + animate_movement = 1 health = 50 maxHealth = 50 damage_coeff = list(BRUTE = 0.5, BURN = 0.7, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index 6a6e44a5852..870b3bf62cc 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -38,7 +38,9 @@ var/elimination = 0 var/anger_modifier = 0 var/obj/item/gps/internal_gps - anchored = TRUE + move_force = MOVE_FORCE_OVERPOWERING + move_resist = MOVE_FORCE_OVERPOWERING + pull_force = MOVE_FORCE_OVERPOWERING mob_size = MOB_SIZE_LARGE layer = MOB_LAYER + 0.5 //Looks weird with them slipping under mineral walls and cameras and shit otherwise mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm index 39799d6e493..0f37482b3e2 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm @@ -136,7 +136,9 @@ throw_message = "does nothing to the rocky hide of the" aggro_vision_range = 9 idle_vision_range = 5 - anchored = 1 //Stays anchored until death as to be unpullable + move_force = MOVE_FORCE_VERY_STRONG + move_resist = MOVE_FORCE_VERY_STRONG + pull_force = MOVE_FORCE_VERY_STRONG var/pre_attack = 0 loot = list(/obj/item/asteroid/goliath_hide{layer = 4.1}) @@ -152,7 +154,9 @@ icon_state = "Goliath_preattack" /mob/living/simple_animal/hostile/asteroid/goliath/revive() - anchored = 1 + move_force = MOVE_FORCE_VERY_STRONG + move_resist = MOVE_FORCE_VERY_STRONG + pull_force = MOVE_FORCE_VERY_STRONG ..() /mob/living/simple_animal/hostile/asteroid/goliath/OpenFire() diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm index 88326747247..b293c1de974 100644 --- a/code/modules/mob/living/simple_animal/hostile/statue.dm +++ b/code/modules/mob/living/simple_animal/hostile/statue.dm @@ -42,7 +42,9 @@ see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS - anchored = 1 + move_force = MOVE_FORCE_EXTREMELY_STRONG + move_resist = MOVE_FORCE_EXTREMELY_STRONG + pull_force = MOVE_FORCE_EXTREMELY_STRONG status_flags = GODMODE // Cannot push also var/cannot_be_seen = 1 diff --git a/code/modules/mob/living/simple_animal/spawner.dm b/code/modules/mob/living/simple_animal/spawner.dm index 22b5fb705a9..7a17dfb202b 100644 --- a/code/modules/mob/living/simple_animal/spawner.dm +++ b/code/modules/mob/living/simple_animal/spawner.dm @@ -10,7 +10,7 @@ var/mob_type = /mob/living/simple_animal/hostile/carp var/spawn_text = "emerges from" status_flags = 0 - anchored = 1 + move_resist = MOVE_FORCE_VERY_STRONG AIStatus = AI_OFF a_intent = INTENT_HARM stop_automated_movement = 1 diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index bfe9ac7484a..3de413ef8a1 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -35,7 +35,6 @@ var/obj/machinery/machine = null var/other_mobs = null var/memory = "" - var/atom/movable/pulling = null var/next_move = null var/notransform = null //Carbon var/other = 0.0 @@ -48,7 +47,6 @@ var/bhunger = 0 //Carbon var/lying = 0 var/lying_prev = 0 - var/canmove = 1 var/lastpuke = 0 var/unacidable = 0 var/can_strip = 1 diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 6d636f0328e..ec57d9d6200 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -12,8 +12,6 @@ stat = 2 canmove = 0 - anchored = 1 // don't get pushed around - /mob/new_player/New() GLOB.mob_list += src diff --git a/code/modules/mob/pulling.dm b/code/modules/mob/pulling.dm deleted file mode 100644 index f5cb9eecbe2..00000000000 --- a/code/modules/mob/pulling.dm +++ /dev/null @@ -1,46 +0,0 @@ -//this and stop_pulling really ought to be /mob/living procs -/mob/proc/start_pulling(atom/movable/AM) - if(src == AM) // Trying to pull yourself is a shortcut to stop pulling - stop_pulling() - return - if(!AM || !isturf(AM.loc)) //if there's no object or the object being pulled is inside something: abort! - return - if(incapacitated()) - return - if(!(AM.anchored)) - AM.add_fingerprint(src) - - // If we're pulling something then drop what we're currently pulling and pull this instead. - if(pulling) - // Are we trying to pull something we are already pulling? Then just stop here, no need to continue. - if(AM == pulling) - return - stop_pulling() - if(AM.pulledby) - visible_message("[src] has pulled [AM] from [AM.pulledby]'s grip.") - AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. - - pulling = AM - AM.pulledby = src - if(pullin) - pullin.update_icon(src) - if(ismob(AM)) - var/mob/M = AM - if(!iscarbon(src)) - M.LAssailant = null - else - M.LAssailant = usr - -/mob/verb/stop_pulling() - set name = "Stop Pulling" - set category = "IC" - - if(pulling) - pulling.pulledby = null - pulling = null - if(pullin) - pullin.update_icon(src) - -/mob/living/proc/check_pull() - if(pulling && !(pulling in orange(1))) - stop_pulling() diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index 64c201a319f..6e1fbb8a842 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -16,6 +16,7 @@ GLOBAL_LIST_INIT(conveyor_switches, list()) desc = "It's a conveyor belt, commonly used to transport large numbers of items elsewhere quite quickly." layer = CONVEYOR_LAYER // so they appear under stuff but not below stuff like vents anchored = TRUE + move_force = MOVE_FORCE_DEFAULT var/operating = FALSE //NB: this can be TRUE while the belt doesn't go var/forwards // The direction the conveyor sends you in var/backwards // hopefully self-explanatory @@ -183,9 +184,12 @@ GLOBAL_LIST_INIT(conveyor_switches, list()) ..() /obj/machinery/conveyor/proc/move_thing(atom/movable/AM) + if(move_force < (AM.move_resist)) + return FALSE if(!AM.anchored && AM.loc == loc) step(AM, forwards) + /obj/machinery/conveyor/proc/can_conveyor_run() if(stat & BROKEN) return FALSE diff --git a/paradise.dme b/paradise.dme index a2e96d73ddf..f04d4909f96 100644 --- a/paradise.dme +++ b/paradise.dme @@ -44,6 +44,7 @@ #include "code\__DEFINES\MC.dm" #include "code\__DEFINES\misc.dm" #include "code\__DEFINES\mobs.dm" +#include "code\__DEFINES\move_force.dm" #include "code\__DEFINES\pda.dm" #include "code\__DEFINES\pipes.dm" #include "code\__DEFINES\preferences.dm" @@ -1611,7 +1612,6 @@ #include "code\modules\mob\mob_helpers.dm" #include "code\modules\mob\mob_movement.dm" #include "code\modules\mob\mob_transformation_simple.dm" -#include "code\modules\mob\pulling.dm" #include "code\modules\mob\say.dm" #include "code\modules\mob\status_procs.dm" #include "code\modules\mob\transform_procs.dm"